CallForCode Part I / 4 - Building Awesome Disaster Machine Learning Applications for Dummies (Me && You)
Taking an indepth look at several new services with IBM's PaaS Platform and Salesforce Einstein in a unique use case, the CallForCode Disaster Relief Initiative IBM Call for Code
By Brandon Kravitz
On August 19th the planet celebrated the United Nation's Humanitarian Day to raise awareness of first responders who provide aid immediately after disasters.
Call for Code aims to help improve the lives of those communities who are most threatened by natural disasters and in turn, will help ease and improve the important role that humanitarian agencies play.
Projects must utilize 5 myCloud Services and provide a need to disaster first responders. Sample projects included utilizing aerial drones that could provide topography insights into which areas need aid, uncovering deep learning image processing to treat and identify victims, while using the provided IBM "Weather Company API" to fuel disaster data and realness to the competition.
Things You Will Need
Item | Location | Description |
---|---|---|
Salesforce | login.salesforce.com | Developer Edition of Salesforce with Analtyics Studio |
IBM myCloud | https://console.bluemix.net/catalog/ | IBM's Catalog of Services |
Weather Company API | http://developer.weather.com | Raw Data to Use for Competition CSV Data File and JSON Data from the API |
Code Softly and Carry Good Analysis
In order to create a well designed supervised machine learning tool, one must ask meaningful questions and prepare or tidy data in a way that allows you to predict closer to your true answer.
Let's Ask Simple Questions From Data Points In Call for Code
How and WHERE do natural disasters occur?
Can we utilize a large dataset or complex API with Salesforce Einstein?
How does one build a natural disaster algorithm?
HIC MANEBIMUS OPTIME
In order to build an event driven disaster project, lets define a few metrics so that our datasets can be meaningful and perform to our scope:
Define Scope: | Predict if a household disaster will occur... |
---|---|
Define Performance: | Our target accurancy should be over < 70% |
**Context: ** | Using IBM Weather Company Data we can predict with 70% or greater accuracy which homes will be effected by disasters. |
Solution Data: | Using Machine Learning Workflows to process and transform Weather Company Data to create a prediction model, this model must predict which homes will be effected by impending types of disasters. |
As long as we keep our scope within reasonable limits we should be able to create two distinct objects, Disasters and Households.
Telling Your Datastory - Enterprise Architect Edition
Anyone in tech knows that now more than ever companies are changing their business requirements and compliance structure on a more frequent basis. With Deep Learning Forward Propagating Networks and constant advances in autonomous services; integrating data realtime is a competitive advantage any skilled developer should have in their wheelhouse. Working with Event Driven Architecture and on-demand data doesn't have to be overly complex, we will look at two classic platforms Salesforce and IBM Bluemix; apply Event Driven architecture (Platform Events) through several methodoligies and use cases.
IBM Call for Code is a great way for Advanced and Beginner Devs to build a cutting edge library of skills or just sharpen existing ones.
So you wanna be a Salesforce Enterprise Architect?
Let's take our proposed data types and transform them into some metadata!
First we are going to define a few items in Salesforce:
Item | Description |
---|---|
Household (Account) | Describes homes with Geolocation, Value, Income, Gender |
Disaster__c | Disaster Types with Geolocation, Intensity, Time |
HouseholdDisaster__e | Platform Event that can return values and transform multiple objects |
Create Household Disaster Platform Event
Create a Platform Event and a Long Text Area Field
Disaster__c Fields and Data Type
Create all these fields on Disaster Custom Object with the Correct Data Type
Implementation
Now that the fields and objects are in place, our implementation is fast and simple:
Utilize our platform event to create a disaster
Push Data from Outside Source into Salesforce (Part II)
Copy the following code into Developer Console - (Ensure you have correct fields created for disaster!!!)
xxxxxxxxxx
//This code creates the ability for Salesforce to take JSON data and build them into our Disaster Object
public class DisasterClass {
public String x_id {get;set;} // in json: _id
public String x_rev {get;set;} // in json: _rev
public String satellite {get;set;}
public String bright_ti4 {get;set;}
public String bright_ti5 {get;set;}
public String scan {get;set;}
public String track {get;set;}
public String confidence {get;set;}
public String longitude {get;set;}
public String acq_date {get;set;}
public String frp {get;set;}
public String version {get;set;}
public String latitude {get;set;}
public String daynight {get;set;}
public String acq_time {get;set;}
public DisasterClass(JSONParser parser) {
while (parser.nextToken() != System.JSONToken.END_OBJECT) {
if (parser.getCurrentToken() == System.JSONToken.FIELD_NAME) {
String text = parser.getText();
if (parser.nextToken() != System.JSONToken.VALUE_NULL) {
if (text == '_id') {
x_id = parser.getText();
} else if (text == '_rev') {
x_rev = parser.getText();
} else if (text == 'satellite') {
satellite = parser.getText();
} else if (text == 'bright_ti4') {
bright_ti4 = parser.getText();
} else if (text == 'bright_ti5') {
bright_ti5 = parser.getText();
} else if (text == 'scan') {
scan = parser.getText();
} else if (text == 'track') {
track = parser.getText();
} else if (text == 'confidence') {
confidence = parser.getText();
} else if (text == 'longitude') {
longitude = parser.getText();
} else if (text == 'acq_date') {
acq_date = parser.getText();
} else if (text == 'frp') {
frp = parser.getText();
} else if (text == 'version') {
version = parser.getText();
} else if (text == 'latitude') {
latitude = parser.getText();
} else if (text == 'daynight') {
daynight = parser.getText();
} else if (text == 'acq_time') {
acq_time = parser.getText();
} else {
System.debug(LoggingLevel.WARN, 'DisasterClass consuming unrecognized property: '+text);
consumeObject(parser);
}
}
}
}
}
public static DisasterClass parse(String json) {
System.JSONParser parser = System.JSON.createParser(json);
return new DisasterClass(parser);
}
public static void consumeObject(System.JSONParser parser) {
Integer depth = 0;
do {
System.JSONToken curr = parser.getCurrentToken();
if (curr == System.JSONToken.START_OBJECT ||
curr == System.JSONToken.START_ARRAY) {
depth++;
} else if (curr == System.JSONToken.END_OBJECT ||
curr == System.JSONToken.END_ARRAY) {
depth--;
}
} while (depth > 0 && parser.nextToken() != null);
}
}
Now that we have our Disaster class ready we can send data to our event channel and create disasters. Copy the following code into developer console (this trigger will produce disaster data on the event channel):
xxxxxxxxxx
/**
* ────────────────────────────────────────────────────────────────────────────────────────────────
* Code Review: IBM Apex App Connect Platform Event
* Class Name: appConnect_DisasterEvent
* Description: Executes upsert of disaster data driven from current API
* ────────────────────────────────────────────────────────────────────────────────────────────────
* @ReviewedBy Brandon Kravitz brandon.kravitz@ibm.com
* @thisCodeReviewTestClass appConnect_DisasterEvent
**/
// Trigger for listening to HouseDisaster__e events.
trigger HouseDisasterEventTrigger on HouseDisaster__e(after insert) {
// List to hold all Disasters to be created.
List < Disaster__c > disasters = new List < Disaster__c > ();
// Documentation ID
// Iterate through each notification.
for (HouseDisaster__e event: Trigger.New) {
// Let's parse through our long text field and grab all disaster objects
JSONParser parser = JSON.createParser(event.Disaster__c);
while (parser.nextToken() != null) {
if (parser.getCurrentToken() == JSONToken.START_ARRAY) {
while (parser.nextToken() != null) {
if (parser.getCurrentToken() == JSONToken.START_OBJECT) {
// System Debug Disasters
DisasterClass d = (DisasterClass) parser.readValueAs(DisasterClass.class);
system.debug('GEOLOCATION long:: ' + d.longitude + 'lat:: ' + d.latitude);
system.debug('Size of list items: ' + d.x_id);
String s = JSON.serialize(d);
system.debug('Serialized Disaster: ' + s);
// Skip the child start array and start object markers.
parser.skipChildren();
Disaster__c disaster = new Disaster__c();
if (d.x_id != null) disaster.Document_ID__c = d.x_id;
if (d.satellite != null) disaster.Satellite__c = d.satellite;
if (d.bright_ti4 != null) disaster.Bright_ti4__c = Decimal.valueOf(d.bright_ti4);
if (d.bright_ti5 != null) disaster.bright_ti5__c = Decimal.valueOf(d.bright_ti5);
if (d.scan != null) disaster.scan__c = Decimal.valueOf(d.scan);
if (d.track != null) disaster.track__c = Decimal.valueOf(d.track);
if (d.confidence != null) disaster.confidence__c = d.confidence;
if (d.longitude != null) disaster.longitude__c = Decimal.valueOf(d.longitude);
if (d.latitude != null) disaster.latitude__c = Decimal.valueOf(d.latitude);
if (d.latitude != null && d.longitude != null) disaster.Geolocation__longitude__s = Decimal.valueOf(d.longitude);
if (d.latitude != null && d.longitude != null) disaster.Geolocation__latitude__s = Decimal.valueOf(d.latitude);
disasters.add(disaster);
}
}
}
}
// Insert all Disasters corresponding to events received.
upsert disasters;
}
}
Verify Our Results and Next Steps
Cool we created some disasterous code!
You can test this data for now using the following raw JSON file and your favorite REST platform tester:
Log in to your Trailhead DE org.
Open a new tab and navigate to Workbench at https://workbench.developerforce.com/login.php
For Environment, select Production.
For API Version, select the highest available number.
Select I agree to the terms of service.
Click Login with Salesforce.
On the next screen, click Allow.
In the top menu, select utilities | REST Explorer.
Click POST.
Replace the URI with:
xxxxxxxxxx
/services/data/v40.0/sobjects/HouseDisaster__e
xxxxxxxxxx
{
"Disaster__c" : "{
"latitude": 27.73063,
"longitude": -81.9941,
"bright_ti4": 308.7,
"scan": 0.38,
"track": 0.59,
"acq_date": "2018-08-21",
"acq_time": "0630",
"satellite": "N",
"confidence": "nominal",
"version": "1.0NRT",
"bright_ti5": 288.1,
"frp": 1.6,
"daynight": "N"}"
}
We will be taking a deeper dive at a brand new connector called APP Connect that will allow us to sync data to Salesforce with low overhead.
Part II...
Now that we have our households, disasters and events setup; lets prepare some data from IBM to send to Salesforce Einstein using some state of the art toolsets.... TBD
0 Comments Leave a comment