As COVID-19 continues to spread, healthcare groups and companies of all kinds are under pressure to provide care in the face of increasing demand. Healthy Data is your window into how data can help organizations address this crisis.

COVID-19 required a worldwide coordinated response of medical professionals, data teams, logistics organizations, and a whole host of other experts to try to flatten the curve, improve treatments, and ultimately develop lasting remedies. Sisense has been at the forefront of the data-based response to this global crisis.

March saw the beginning of Project SiCo: The Sisense effort to make COVID-19 data more accessible and consumer friendly. Dozens of Sisensers took part in project SiCo to create this awesome COVID hub. This article will focus on the AI Research (AIR) team’s effort, specifically an experimental combination of Sisense BloX (actionable embedded analytics) and Quest (an advanced analytics add-on for Sisense) which we called the SEIR app.

Sisense for Cloud Data Teams

Envisioning the SEIR app

The SEIR app was designed to show the effect that social distancing had on the COVID-19 infection rate based on a model named SEIR. This model takes into account the population size of a certain country, social distancing rate, and the number of days that passed between the first confirmed case and when the social distancing policy was enacted.

The model outputs the 4 following time series:

  • S – The number of Susceptible individuals
  • E – The number of people Exposed to an infected individual and are potential carriers
  • I – Infected individuals
  • R – Recovered individuals

Each array contains a list of numbers that can be plotted as a daily time series.

The app was designed to enable users to choose different countries and make adjustments to the social distancing measures, and immediately see the corresponding Exposed and Infected curves plotted on the screen.

SEIR

Calling on Quest to handle complex calculations with ease

The large number of parameter combinations made it very difficult to precalculate all of the options and feed them to the Elasticube. The better option was to perform the model’s calculations only once the parameters were set. These on-the-fly Python model calculations are uniquely suited for Sisense’s Quest advanced analytics add-on.

All we had to do was upload the Python file as a Quest custom model and create a lambda function. The function would take care of all the SEIR calculations for us when called. Each Lambda function can be referenced through Quest’s in-product API.

However, there were two main challenges with using Quest alone:

  1. The Input: The only dynamic parameter that Quest sends custom models comes from the widget’s current data, which made it difficult to send adjustable parameters such as the social distancing rate or the number of days since it began.
  2. The Output: Quest can handle the results returned from models in several ways (e.g.  showing those results as a table, plotting them as a new line on the chart, highlighting an existing point etc.). While it is able to add an additional series to a chart, it can’t handle two series for a single response, which made creating both the Exposed and the Infected plots very difficult.

Creating a custom interface with Sisense BloX

While the Quest runModel API was ideal for executing the SEIR custom model script, we needed an interface that would allow users to make parameter adjustments, execute the runModel API, and then plot the result on the chart.

What we needed was a widget type with sliders and input fields that could execute custom Javascript functionality on demand. Sisense BloX’s input and slider components were uniquely well-suited for accepting user inputs. Its custom actions could then use that information, and more, to communicate with API’s and manipulate the chart’s query result.

Technical deep-dive: Bringing SEIR to life

(Author’s note: The following section uses highly technical language and will be best understood by readers fluent in Javascript.)

Step 1: Creating the SEIR Custom Model

We started by facilitating Sisense Quest’s custom models capabilities in order to create an operational Lambda function. Sisense Quest’s most unique capability is probably the custom model mechanism.

Aside from the several native models that come out of the box, builders may define their own models using Python files.

Once uploaded, Quest generates an AWS Lambda function based on those Python scripts, which we can summon whenever the model is called. That communication is done via an internal API endpoint defined in the Sisense Quest microservice.

For this project, we began with a Python file containing the algorithm we’d like to use for our model. This file was created and adjusted by one of our amazing data scientists, though its content is fairly simple. It extracts our adjustable parameters out of the Lambda’s “Event” attribute and calculates the SEIR series based on them.

Once the Python was set up how we wanted it, we created our custom Sisense Quest model. The visualization type and structure definitions were not important since we were not activating the model from Quest’s UI. 

Before finishing the upload, we needed to open our browser’s developer tools, specifically the “network” tab:

Clicking “done” caused the browser to send a model creation request to the Quest service. 

The response to that request included our new model ID.

Since our plan was to execute the model through Sisense Quest’s API, this ID was our way of identifying the relevant model whenever we wanted to run it.

(If you’re trying to replicate this process, now’s the time when you copy it and save it for later use. For more information about custom models and the best practices of their creation visit our Sisense Quest documentation.)

Step 2: Creating the custom action

In this step, we utilized the model we’ve just created via a Sisense BloX custom action. (If you haven’t had the chance to work with custom actions before, I highly recommend reading this custom action guide, which lays out the foundation for using them.

The action consists of 3 main stages. 

Stage 1: Extracting the action input

While writing the logic for your action, identify the pieces of information that should be provided in the action’s input, whether they come from the Sisense BloX widget’s query, or from user input. In the following steps of this guide, we will include those in the action’s input payload. 

In your code, extract those variables from payload.data.

Stage 2: Running the custom model

The SEIR model will be executed by using Quest’s runModel API endpoint, providing the model ID we saved from stage 1 along with the data our model needs:

   // Run SEIR custom model via Quest
   let modelResult;
   const myHeaders = new Headers();
   myHeaders.append("Content-Type", "application/json");
 
   const data = JSON.stringify({
       "modelId": modelId,
       "method": "POST",
       "payload": {
           "N": n,
           "p": socialDistanceRate,
           "p_start_day": pStartDay
       },
       "custom": true
   });
 
   const requestOptions = {
       method: 'POST',
       headers: myHeaders,
       body: data,
       redirect: 'follow',
       credentials: 'include'
   };
 
   fetch(`${sisenseUrl}/api/v1/quest/runModel`, requestOptions)

A few notes about the endpoint: 

  • The modelId and Sisense url are constants that are defined at the beginning of the full action function (attached). Those constants should be adjusted to your environment and to the model you created in the previous step.
  • The request’s body should be a stringified object that contains the model ID, a payload object (which contains all of the parameters we’d like our model to receive), and 2 hardcoded values: custom: true, method: post
  • If you intend to embed the Sisense BloX widget in your own website using Sisense JS, make sure to include credentials in the request using the credentials: ‘include’ property.
  • If we were trying to communicate with any external URL, we would have to open CORS, but since Quest’s API is internal, there is no need.

Stage 3: Plotting the model results on the target widget

Once the model results are resolved, we can use them as we please. In this particular case, I manipulated another widget in the dashboard, and added 2 additional series, based on the model’s result. You can adjust this flow to your own needs by using the result in any other way.

Step 3: Creating a basic Sisense BloX Widget

Once the model and action have been created, we turned to the tool that will activate them: the Sisense BloX widget itself. To activate the custom action we have created, a user will have to click a respective action button, and that should be the element we add first.

In this example, I added the action inside an ActionSet element, as it makes it very easy to control the button’s style and location inside the Sisense BloX card. We then included all of the parameters that our action expects as properties of the data object. Our model will require the parameters n, socialDistanceRate and pStartDay, while the processing and plotting of the models result require the parameters widget id and series color.

Set the parameters’ values to either reflect the value of a widget panel (i.e. the parameter n), or to a hardcoded default value:

{
   "type": "ActionSet",
   "class": "update-model-button",
   "actions": [
       {
           "type": "SEIR",
           "title": "Apply",
           "data": {
               "widgetId": "5ea16f579e97a3002de5a31d",
               "color": "#000000",
               "n": "{value: Population}",
               "socialDistanceRate": 1,
               "pStartDay": 10
           }
       }
   ],
   "style": {
       "paddingBottom": "0",
       "marginRight": "15px",
       "display": "none"
   }
}

For every parameter that you would like to make dynamic and dictate by user input, create a Text input element. To enable this input field to feed the actions with its value, make sure to give it an id property whose value represents the path of the respective attribute in the action’s payload.

{
   "type": "Input.Text",
   "id": "data.socialDistanceRate",
   "placeholder": "0-1",
   "defaultValue": "0"
}

For the sake of convenience, I wrapped each input in a Container element and I recommend you do it, as well. Finally, design and style your Sisense BloX widget to complement your dashboard.

Step 4: Kicking Sisense BloX up a notch

We now have an operational Sisense BloX widget whose custom action can trigger a custom quest model and plot its result on the target widget. At this point, we could style the Sisense BloX widget to our liking and be finished.

However, asking users to manually change the values of the social distance rate, or the number of days until social distance was applied in an input field was cumbersome and didn’t give the slick experience we were looking for.

Since those 2 parameters are numeric ranges, it was natural to use sliders for them.

However, sliders are not considered inputs in Sisense BloX, and therefore, invoked actions do not collect their values. To overcome this issue and take the slider values into account, we implemented the Auto Slider solution, as well as additional CSS, to give it a Sisense-app look and feel.

Building better advanced analytic apps

The SEIR app was a bold experiment not just in helping save lives via social distancing, but in pushing what the Sisense data and analytics platform was capable of. Sisense BloX puts actions and insights together and allows for an unparalleled level of customization for both visuals and functionality. The Sisense Quest add-on gives you greater flexibility to use advanced analytics in a variety of ways, supercharging your insights and allowing you to get more out of your data.

These are just a few ways you can use Sisense to do amazing things with your data. We hope the how-to elements of this article get your imagination going and help you build boldly. Be sure to jump into our active builder community to see and hear about the exciting projects that other builders are working on and get feedback on your own projects. There’s nothing we can’t do when we work together, from flattening the curve to building amazing new data and analytics products.

Sisense for Cloud Data Teams

Adi Lewenstein has spent almost a decade in the analytics and BI space as a BI consultant in Sisense’s CS department and as a growth hacker in Sisense Labs. She has spoken at numerous industry events and today serves as a full stack developer in Sisense’s AI R&D team, implementing the AI-driven capabilities she has once desired as a user.

Tags: | | |