Skip to main content

Case Study 3: Dashboard for Showcasing Different Data Models

In this case study, we will be using HydroLang, HydroCompute, and the HydroRTC libraries to create a dashboard that connects all different kind of data.

Objectives

We will be doing the following with each of the libraries:

  • Obtain data and extract it using the HydroRTC.
  • Give the data into the HydroCompute to create heavy computing on the client-side statistical modelling.
  • Showcase the results of these data using HydroLang's visualization modules.

Data Preparation

For this project, we will be interfacing with an HDF5 file that contains gridded data, obtain a time series from the file through the server-side functionalities implemented in the HydroRTC library.

First, create a connection mechanism to the server as we have done in the previous case study by declaring a server instance. The body of our application will be modified by adding a chart div so we can visualize the results from the compute pipeline as follows:

<body>
<div id="map"></div>
<div id="overlay">
<div id="content">
<div id="retrieved-data"></div>
<div id="result-graph"></div>
//Visualize graph
<div id="stats-table"></div>
<button id="download-raw-btn">Download Data</button>
<button id="download-simulationRes-btn">
Download Simulation Results</button
>//Attach the simulation results
</div>
</div>
</body>

Setting up the Pipeline

Let's start by defining what we will want to observe from the retrieved data. In particular, since we are talking about time series information, it would be good to see how forecasting models and moving averages work with the retrived information.

Define the functions that we want to run as follows:

let jsFuns = ["expoMovingAverage_js", "simpleMovingAverage_js"];
let cFuns1 = ["_monteCarlo_c", "_arima_autoParams"];
let cFuns2 = [
"_arima_autoParams",
"_linear_detrend",
"_monteCarlo_c",
"_linear_detrend",
];

We will run the first two sets of functions in parallel, while the last one will run sequentially trailing down results.

For doing this, let's create new function that will use the downloaded data as inputs for all the simulations.

async function computeRun(site, data) {
//Removing the date values and leaving only the results
data = data[1].slice(1);

//resetting the result spaces in the engine
compute.availableData = [];
compute.engineResults = {};
compute.instanceRun = 0;

//saving the results inside the compute library
compute.data({ id: site, data });
let jsFuns = ["expoMovingAverage_js", "simpleMovingAverage_js"];
let cFuns1 = ['_monteCarlo_c', '_arima_autoParams'];
let cFuns2 = ['_linear_detrend', '_arima_autoParams', '_monteCarlo_c'];
//...
}

Running the Simulation

Inside the computeRun function, let's run the different simulations as follows:

async function computeRun(site, data) {
//...
compute.setEngine("wasm");

await compute.run({
functions: cFuns1,
});

await compute.run({
functions: cFuns2,
dependencies: true,
});

compute.setEngine("javascript");

await compute.run({
functions: jsFuns,
});

//...
}
Note

For more information on how the derivation of these methods, please take a look into the documentation of HydroCompute.

async function computeRun(site, data) {
//Result holders
let return_Values = [];
let return_Names = [];

//Retrieving each of the simulation runs
let results1 = compute.results("Simulation_1")[0];
let results2 = compute.results("Simulation_2")[0];
let results3 = compute.results("Simulation_3")[0];

//cleaning up some Infinity, NaN, and null values
for (let i = 0; i < results1.functions.length; i++) {
return_Values.push(compute.utils.cleanArray(results1.results[i]));
return_Names.push(results1.functions[i]);
}

//Same for results 2 and 3

return [return_Values, return_Names];
}

Visualizing Results

We need to call the newly created function inside the retrieveValues function and attach the results to the graph and download button.

async function retrieveValues(site) {
//We add a new button
let button2 = document.getElementById("download-simulationRes-btn");

//...

//After the results have been downloaded, we call the computeRun function
let [results, fun_names] = await computeRun(site, await usgs_data);

//Reattach the date values to the result array
results.unshift(usgs_data[0]);

//Graph the results
hydro.visualize.draw({
params: { type: "chart", id: "result-graph" },
args: { names: fun_names },
data: results,
});

//...

//Attach the values from the simulations to the button for donwloading
button2.removeAttribute("hidden");
button2.addEventListener("click", () => {
hydro.data.download({ args: { type: "CSV" }, data: results });
});
showOverlay();
}