diff --git a/MATScommon b/MATScommon
index c04c364196..68f74446ef 160000
--- a/MATScommon
+++ b/MATScommon
@@ -1 +1 @@
-Subproject commit c04c364196da61db6bc409fbec4b6c5be922fc67
+Subproject commit 68f74446ef39d830ac7568e84af77ea5b6115f1b
diff --git a/METexpress b/METexpress
index 140bd86257..e87f0609c2 160000
--- a/METexpress
+++ b/METexpress
@@ -1 +1 @@
-Subproject commit 140bd86257330c3f21b327420a3b50a6f78e044a
+Subproject commit e87f0609c2f7bd4286cec77a53f01fb9c871a910
diff --git a/apps/anomalycor/.eslintrc.json b/apps/anomalycor/.eslintrc.json
index 8b795b7df7..79d49c5bb6 100644
--- a/apps/anomalycor/.eslintrc.json
+++ b/apps/anomalycor/.eslintrc.json
@@ -28,22 +28,6 @@
"space-before-function-paren": "off",
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
- "prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
- "no-undef": "warn",
- "no-plusplus": "warn",
- "vars-on-top": "warn",
- "no-var": "warn",
- "block-scoped-var": "warn",
- "no-loop-func": "warn",
- "no-unused-vars": "warn",
- "prefer-destructuring": "warn",
- "no-param-reassign": "warn",
- "camelcase": "warn",
- "no-redeclare": "warn"
+ "prefer-arrow-callback": "off"
}
}
diff --git a/apps/anomalycor/client/main.js b/apps/anomalycor/client/main.js
index a87407a1f4..ecd922b6a2 100644
--- a/apps/anomalycor/client/main.js
+++ b/apps/anomalycor/client/main.js
@@ -2,6 +2,7 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+// eslint-disable-next-line no-unused-vars
import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common";
import "@fortawesome/fontawesome-free";
import "@fortawesome/fontawesome-free/css/all.css";
diff --git a/apps/anomalycor/server/dataFunctions/data_contour.js b/apps/anomalycor/server/dataFunctions/data_contour.js
index ab4b97af0a..02d22d7033 100644
--- a/apps/anomalycor/server/dataFunctions/data_contour.js
+++ b/apps/anomalycor/server/dataFunctions/data_contour.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContour = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,60 +23,75 @@ dataContour = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: true,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
- const totalProcessingStart = moment();
+
+ const curves = JSON.parse(JSON.stringify(plotParams.curves));
+ if (curves.length > 1) {
+ throw new Error("INFO: There must only be one added curve.");
+ }
+
+ const axisMap = Object.create(null);
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- const curves = JSON.parse(JSON.stringify(plotParams.curves));
- if (curves.length > 1) {
- throw new Error("INFO: There must only be one added curve.");
- }
- const dataset = [];
- const axisMap = Object.create(null);
- // initialize variables specific to the curve
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- const regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${model}_anomcorr_${region} as m0`;
+
const { variable } = curve;
const variableClause = `and m0.variable = '${variable}'`;
+
let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
- let levelClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimeStr =
curve["valid-time"] === matsTypes.InputTypes.unused
? "both"
: curve["valid-time"];
- validTimeClause = matsCollections["valid-time"].findOne(
+ [validTimeClause] = matsCollections["valid-time"].findOne(
{ name: "valid-time" },
{ optionsMap: 1 }
- ).optionsMap[validTimeStr][0];
+ ).optionsMap[validTimeStr];
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const statisticClause =
+ "avg(m0.wacorr/100) as stat, " +
+ "stddev(m0.wacorr/100) as stdev, " +
+ "group_concat(unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, ';', m0.level, ';', m0.wacorr / 100 " +
+ "order by unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, m0.level) as sub_data, " +
+ "count(m0.wacorr) as N0";
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -86,104 +102,118 @@ dataContour = function (plotParams, plotFunction) {
dateString = "unix_timestamp(m0.valid_date)+3600*m0.valid_hour";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
+
+ let levelClause = "";
if (xAxisParam !== "Pressure level" && yAxisParam !== "Pressure level") {
const levels = curve.level === undefined ? [] : curve.level;
- if (levels.length > 0 && levels !== matsTypes.InputTypes.unused) {
+ if (levels.length !== 0 && levels !== matsTypes.InputTypes.unused) {
levelClause = `and m0.level IN(${levels})`;
}
}
- const statisticClause =
- "avg(m0.wacorr/100) as stat, " +
- "stddev(m0.wacorr/100) as stdev, " +
- "group_concat(unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, ';', m0.level, ';', m0.wacorr / 100 " +
- "order by unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, m0.level) as sub_data, " +
- "count(m0.wacorr) as N0";
- const statType = "ACC";
- curve.statistic = "Correlation";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+
+ const queryTableClause = `from ${model}_anomcorr_${region} as m0`;
// For contours, this functions as the colorbar label.
- curve.unitKey = curve.statistic;
+ const statType = "ACC";
+ const axisKey = "Correlation";
+ curve.statistic = axisKey;
+ curve.unitKey = axisKey;
let d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{variableClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{levelClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
-
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{variableClause}}", variableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{levelClause}}", levelClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- "Anomaly Correlation"
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{variableClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{levelClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
+
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{variableClause}}", variableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{levelClause}}", levelClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ "Anomaly Correlation"
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
- }
- if (!dataFoundForCurve) {
- // we found no data for any curves so don't bother proceeding
- throw new Error("INFO: No valid data for any curves.");
- }
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
+ // this is NOT an error just a no data condition
+ dataFoundForCurve = false;
+ } else {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ }
- const postQueryStartMoment = moment();
+ if (!dataFoundForCurve) {
+ // we found no data for any curves so don't bother proceeding
+ throw new Error("INFO: No valid data for any curves.");
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
+ }
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
diff --git a/apps/anomalycor/server/dataFunctions/data_contour_diff.js b/apps/anomalycor/server/dataFunctions/data_contour_diff.js
index faaf06b5ef..1e62ca8735 100644
--- a/apps/anomalycor/server/dataFunctions/data_contour_diff.js
+++ b/apps/anomalycor/server/dataFunctions/data_contour_diff.js
@@ -14,6 +14,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContourDiff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -24,64 +25,80 @@ dataContourDiff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: true,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
let dataNotFoundForAnyCurve = false;
+
+ let curves = JSON.parse(JSON.stringify(plotParams.curves));
+ const curvesLength = curves.length;
+ if (curvesLength !== 2) {
+ throw new Error("INFO: There must be two added curves.");
+ }
+
+ const axisMap = Object.create(null);
const showSignificance = plotParams.significance !== "none";
- const totalProcessingStart = moment();
+
+ let statType;
+
+ let statement = "";
+ let error = "";
+ let dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- let curves = JSON.parse(JSON.stringify(plotParams.curves));
- const curvesLength = curves.length;
- if (curvesLength !== 2) {
- throw new Error("INFO: There must be two added curves.");
- }
- let dataset = [];
- const axisMap = Object.create(null);
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${model}_anomcorr_${region} as m0`;
+
const { variable } = curve;
const variableClause = `and m0.variable = '${variable}'`;
+
let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
- let levelClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimeStr =
curve["valid-time"] === matsTypes.InputTypes.unused
? "both"
: curve["valid-time"];
- validTimeClause = matsCollections["valid-time"].findOne(
+ [validTimeClause] = matsCollections["valid-time"].findOne(
{ name: "valid-time" },
{ optionsMap: 1 }
- ).optionsMap[validTimeStr][0];
+ ).optionsMap[validTimeStr];
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const statisticClause =
+ "avg(m0.wacorr/100) as stat, " +
+ "stddev(m0.wacorr/100) as stdev, " +
+ "group_concat(unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, ';', m0.level, ';', m0.wacorr / 100 " +
+ "order by unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, m0.level) as sub_data, " +
+ "count(m0.wacorr) as N0";
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -92,100 +109,111 @@ dataContourDiff = function (plotParams, plotFunction) {
dateString = "unix_timestamp(m0.valid_date)+3600*m0.valid_hour";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
+
+ let levelClause = "";
if (xAxisParam !== "Pressure level" && yAxisParam !== "Pressure level") {
const levels = curve.level === undefined ? [] : curve.level;
- if (levels.length > 0 && levels !== matsTypes.InputTypes.unused) {
+ if (levels.length !== 0 && levels !== matsTypes.InputTypes.unused) {
levelClause = `and m0.level IN(${levels})`;
}
}
- const statisticClause =
- "avg(m0.wacorr/100) as stat, " +
- "stddev(m0.wacorr/100) as stdev, " +
- "group_concat(unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, ';', m0.level, ';', m0.wacorr / 100 " +
- "order by unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, m0.level) as sub_data, " +
- "count(m0.wacorr) as N0";
- var statType = "ACC";
- curve.statistic = "Correlation";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+
+ const queryTableClause = `from ${model}_anomcorr_${region} as m0`;
// For contours, this functions as the colorbar label.
- curves[curveIndex].unitKey = curve.statistic;
+ statType = "ACC";
+ const axisKey = "Correlation";
+ curve.statistic = axisKey;
+ curve.unitKey = axisKey;
- var d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{variableClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{levelClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
+ let d;
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{variableClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{levelClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{variableClause}}", variableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{levelClause}}", levelClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{variableClause}}", variableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{levelClause}}", levelClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- "Anomaly Correlation"
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ "Anomaly Correlation"
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
- dataNotFoundForAnyCurve = true;
- }
- const postQueryStartMoment = moment();
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ dataNotFoundForAnyCurve = true;
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
+ }
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
@@ -233,8 +261,9 @@ dataContourDiff = function (plotParams, plotFunction) {
"Anomaly Correlation",
statType === "ctc"
);
- plotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
- curves = plotParams.curves;
+ const newPlotParams = plotParams;
+ newPlotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
+ curves = newPlotParams.curves;
dataset[0].name = matsPlotUtils.getCurveText(
matsTypes.PlotTypes.contourDiff,
curves[0]
@@ -250,7 +279,7 @@ dataContourDiff = function (plotParams, plotFunction) {
const result = matsDataProcessUtils.processDataContour(
dataset,
curveInfoParams,
- plotParams,
+ newPlotParams,
bookkeepingParams
);
plotFunction(result);
diff --git a/apps/anomalycor/server/dataFunctions/data_dieoff.js b/apps/anomalycor/server/dataFunctions/data_dieoff.js
index 3c2a9830ac..e4086867ae 100644
--- a/apps/anomalycor/server/dataFunctions/data_dieoff.js
+++ b/apps/anomalycor/server/dataFunctions/data_dieoff.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDieoff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,61 +24,82 @@ dataDieoff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: true,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [100];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${model}_anomcorr_${region} as m0`;
+
const { variable } = curve;
const variableClause = `and m0.variable = '${variable}'`;
+
let validTimeClause = "";
- var utcCycleStart;
+
let utcCycleStartClause = "";
+ let utcCycleStart;
+
const forecastLengthStr = curve["dieoff-type"];
const forecastLengthOptionsMap = matsCollections["dieoff-type"].findOne(
{ name: "dieoff-type" },
{ optionsMap: 1 }
).optionsMap;
const forecastLength = forecastLengthOptionsMap[forecastLengthStr][0];
+
+ const statisticClause =
+ "avg(m0.wacorr/100) as stat, " +
+ "count(m0.wacorr) as N0, " +
+ "group_concat(unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, ';', m0.level, ';', m0.wacorr / 100 " +
+ "order by unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, m0.level) as sub_data";
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
- var dateClause;
+ let dateClause;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+
+ const queryTableClause = `from ${model}_anomcorr_${region} as m0`;
+
if (forecastLength === matsTypes.ForecastTypes.dieoff) {
const validTimeStr =
curve["valid-time"] === matsTypes.InputTypes.unused
? "both"
: curve["valid-time"];
- validTimeClause = matsCollections["valid-time"].findOne(
+ [validTimeClause] = matsCollections["valid-time"].findOne(
{ name: "valid-time" },
{ optionsMap: 1 }
- ).optionsMap[validTimeStr][0];
+ ).optionsMap[validTimeStr];
dateClause = `and unix_timestamp(m0.valid_date)+3600*m0.valid_hour >= '${fromSecs}' and unix_timestamp(m0.valid_date)+3600*m0.valid_hour <= '${toSecs}' `;
} else if (forecastLength === matsTypes.ForecastTypes.utcCycle) {
utcCycleStart =
@@ -89,67 +111,64 @@ dataDieoff = function (plotParams, plotFunction) {
} else {
dateClause = `and unix_timestamp(m0.valid_date)+3600*m0.valid_hour-m0.fcst_len*3600 = ${fromSecs}`;
}
+
let levelClause = "";
const levels = curve.level === undefined ? [] : curve.level;
if (levels.length !== 0 && levels !== matsTypes.InputTypes.unused) {
levelClause = `and m0.level IN(${levels})`;
}
- const statisticClause =
- "avg(m0.wacorr/100) as stat, " +
- "count(m0.wacorr) as N0, " +
- "group_concat(unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, ';', m0.level, ';', m0.wacorr / 100 " +
- "order by unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, m0.level) as sub_data";
- var statType = "ACC";
- curves[curveIndex].statistic = "Correlation";
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ statType = "ACC";
const axisKey = "Correlation";
+ curves[curveIndex].statistic = axisKey;
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.fcst_len as fcst_lead, " +
- "count(distinct unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as N_times, " +
- "min(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as min_secs, " +
- "max(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{variableClause}} " +
- "{{validTimeClause}} " +
- "{{utcCycleStartClause}} " +
- "{{levelClause}} " +
- "group by fcst_lead " +
- "order by fcst_lead" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{variableClause}}", variableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{levelClause}}", levelClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.fcst_len as fcst_lead, " +
+ "count(distinct unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as N_times, " +
+ "min(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as min_secs, " +
+ "max(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{variableClause}} " +
+ "{{validTimeClause}} " +
+ "{{utcCycleStartClause}} " +
+ "{{levelClause}} " +
+ "group by fcst_lead " +
+ "order by fcst_lead" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{variableClause}}", variableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{levelClause}}", levelClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
"Anomaly Correlation"
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -165,6 +184,7 @@ dataDieoff = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -179,7 +199,6 @@ dataDieoff = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -204,6 +223,7 @@ dataDieoff = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/anomalycor/server/dataFunctions/data_histogram.js b/apps/anomalycor/server/dataFunctions/data_histogram.js
index 74affb5d88..41aaa3498b 100644
--- a/apps/anomalycor/server/dataFunctions/data_histogram.js
+++ b/apps/anomalycor/server/dataFunctions/data_histogram.js
@@ -11,6 +11,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataHistogram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -21,43 +22,43 @@ dataHistogram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: true,
};
- const alreadyMatched = false;
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
const dataFoundForCurve = [];
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+ const alreadyMatched = false;
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
+
+ const axisMap = Object.create(null);
+ let statType;
+
+ let statement = "";
+ let error = "";
const dataset = [];
const allReturnedSubStats = [];
const allReturnedSubSecs = [];
const allReturnedSubLevs = [];
- const axisMap = Object.create(null);
// process user bin customizations
const binParams = matsDataUtils.setHistogramParameters(plotParams);
const { yAxisFormat } = binParams;
const { binNum } = binParams;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
dataFoundForCurve[curveIndex] = true;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${model}_anomcorr_${region} as m0`;
+
const { variable } = curve;
const variableClause = `and m0.variable = '${variable}'`;
+
const validTimeStr =
curve["valid-time"] === matsTypes.InputTypes.unused
? "both"
@@ -66,28 +67,43 @@ dataHistogram = function (plotParams, plotFunction) {
{ name: "valid-time" },
{ optionsMap: 1 }
).optionsMap[validTimeStr][0];
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
+
+ const statisticClause =
+ "avg(m0.wacorr/100) as stat, " +
+ "count(m0.wacorr) as N0, " +
+ "group_concat(unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, ';', m0.level, ';', m0.wacorr / 100 " +
+ "order by unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, m0.level) as sub_data";
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
const dateClause = `and unix_timestamp(m0.valid_date)+3600*m0.valid_hour >= ${fromSecs} and unix_timestamp(m0.valid_date)+3600*m0.valid_hour <= ${toSecs}`;
+
let levelClause = "";
const levels = curve.level === undefined ? [] : curve.level;
if (levels.length !== 0 && levels !== matsTypes.InputTypes.unused) {
levelClause = `and m0.level IN(${levels})`;
}
- const statisticClause =
- "avg(m0.wacorr/100) as stat, " +
- "count(m0.wacorr) as N0, " +
- "group_concat(unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, ';', m0.level, ';', m0.wacorr / 100 " +
- "order by unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, m0.level) as sub_data";
- var statType = "ACC";
- curves[curveIndex].statistic = "Correlation";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+
+ const queryTableClause = `from ${model}_anomcorr_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ statType = "ACC";
+ curves[curveIndex].statistic = "Correlation";
let axisKey = yAxisFormat;
if (yAxisFormat === "Relative frequency") {
axisKey += " (x100)";
@@ -95,48 +111,48 @@ dataHistogram = function (plotParams, plotFunction) {
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
curves[curveIndex].binNum = binNum; // stash the binNum to use it later for bar chart options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select unix_timestamp(m0.valid_date)+3600*m0.valid_hour as avtime, " +
- "count(distinct unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as N_times, " +
- "min(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as min_secs, " +
- "max(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{variableClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{levelClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{variableClause}}", variableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{levelClause}}", levelClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select unix_timestamp(m0.valid_date)+3600*m0.valid_hour as avtime, " +
+ "count(distinct unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as N_times, " +
+ "min(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as min_secs, " +
+ "max(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{variableClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{levelClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{variableClause}}", variableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{levelClause}}", levelClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
"Anomaly Correlation"
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -155,6 +171,7 @@ dataHistogram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/anomalycor/server/dataFunctions/data_profile.js b/apps/anomalycor/server/dataFunctions/data_profile.js
index 60cc13b1c6..1b77bb4f90 100644
--- a/apps/anomalycor/server/dataFunctions/data_profile.js
+++ b/apps/anomalycor/server/dataFunctions/data_profile.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataProfile = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,38 +24,39 @@ dataProfile = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: true,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
const idealValues = [100];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${model}_anomcorr_${region} as m0`;
+
const { variable } = curve;
const variableClause = `and m0.variable = '${variable}'`;
+
const validTimeStr =
curve["valid-time"] === matsTypes.InputTypes.unused
? "both"
@@ -63,66 +65,80 @@ dataProfile = function (plotParams, plotFunction) {
{ name: "valid-time" },
{ optionsMap: 1 }
).optionsMap[validTimeStr][0];
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and unix_timestamp(m0.valid_date)+3600*m0.valid_hour >= ${fromSecs} and unix_timestamp(m0.valid_date)+3600*m0.valid_hour <= ${toSecs}`;
+
const statisticClause =
"avg(m0.wacorr/100) as stat, " +
"count(m0.wacorr) as N0, " +
"group_concat(unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, ';', m0.level, ';', m0.wacorr / 100 " +
"order by unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, m0.level) as sub_data";
- var statType = "ACC";
- curves[curveIndex].statistic = "Correlation";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and unix_timestamp(m0.valid_date)+3600*m0.valid_hour >= ${fromSecs} and unix_timestamp(m0.valid_date)+3600*m0.valid_hour <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+
+ const queryTableClause = `from ${model}_anomcorr_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ statType = "ACC";
const axisKey = "Correlation";
+ curves[curveIndex].statistic = axisKey;
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.level as avVal, " +
- "count(distinct unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as N_times, " +
- "min(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as min_secs, " +
- "max(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{variableClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by avVal " +
- "order by avVal" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{variableClause}}", variableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.level as avVal, " +
+ "count(distinct unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as N_times, " +
+ "min(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as min_secs, " +
+ "max(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{variableClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avVal " +
+ "order by avVal" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{variableClause}}", variableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
"Anomaly Correlation"
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -138,6 +154,7 @@ dataProfile = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -152,7 +169,6 @@ dataProfile = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -177,6 +193,7 @@ dataProfile = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.y.length;
const annotation =
mean === undefined
diff --git a/apps/anomalycor/server/dataFunctions/data_series.js b/apps/anomalycor/server/dataFunctions/data_series.js
index 1a61a3cedd..9a156a60cb 100644
--- a/apps/anomalycor/server/dataFunctions/data_series.js
+++ b/apps/anomalycor/server/dataFunctions/data_series.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSeries = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,42 +24,44 @@ dataSeries = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: true,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [100];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${model}_anomcorr_${region} as m0`;
+
const { variable } = curve;
const variableClause = `and m0.variable = '${variable}'`;
+
const validTimeStr =
curve["valid-time"] === matsTypes.InputTypes.unused
? "both"
@@ -69,77 +72,91 @@ dataSeries = function (plotParams, plotFunction) {
{ name: "valid-time" },
{ optionsMap: 1 }
).optionsMap[validTimeStr][0];
+
let forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateClause = `and unix_timestamp(m0.valid_date)+3600*m0.valid_hour >= ${fromSecs} and unix_timestamp(m0.valid_date)+3600*m0.valid_hour <= ${toSecs}`;
+
+ const statisticClause =
+ "avg(m0.wacorr/100) as stat, " +
+ "count(m0.wacorr) as N0, " +
+ "group_concat(unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, ';', m0.level, ';', m0.wacorr / 100 " +
+ "order by unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, m0.level) as sub_data";
+
const averageStr = curve.average;
const averageOptionsMap = matsCollections.average.findOne(
{ name: "average" },
{ optionsMap: 1 }
).optionsMap;
const average = averageOptionsMap[averageStr][0];
+
+ const dateClause = `and unix_timestamp(m0.valid_date)+3600*m0.valid_hour >= ${fromSecs} and unix_timestamp(m0.valid_date)+3600*m0.valid_hour <= ${toSecs}`;
+
let levelClause = "";
const levels = curve.level === undefined ? [] : curve.level;
if (levels.length !== 0 && levels !== matsTypes.InputTypes.unused) {
levelClause = `and m0.level IN(${levels})`;
}
- const statisticClause =
- "avg(m0.wacorr/100) as stat, " +
- "count(m0.wacorr) as N0, " +
- "group_concat(unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, ';', m0.level, ';', m0.wacorr / 100 " +
- "order by unix_timestamp(m0.valid_date) + 3600 * m0.valid_hour, m0.level) as sub_data";
- var statType = "ACC";
- curves[curveIndex].statistic = "Correlation";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+
+ const queryTableClause = `from ${model}_anomcorr_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ statType = "ACC";
const axisKey = "Correlation";
+ curves[curveIndex].statistic = axisKey;
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select {{average}} as avtime, " +
- "count(distinct unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as N_times, " +
- "min(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as min_secs, " +
- "max(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{variableClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{levelClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "select {{average}} as avtime, " +
+ "count(distinct unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as N_times, " +
+ "min(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as min_secs, " +
+ "max(unix_timestamp(m0.valid_date)+3600*m0.valid_hour) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{variableClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{levelClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
- statement = statement.replace("{{average}}", average);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{variableClause}}", variableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{levelClause}}", levelClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
+ statement = statement.replace("{{average}}", average);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{variableClause}}", variableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{levelClause}}", levelClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
- // math is done on forecastLength later on -- set all analyses to 0
- if (forecastLength === "-99") {
- forecastLength = "0";
- }
+ // math is done on forecastLength later on -- set all analyses to 0
+ if (forecastLength === "-99") {
+ forecastLength = "0";
+ }
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBTimeSeries(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
model,
forecastLength,
@@ -151,7 +168,9 @@ dataSeries = function (plotParams, plotFunction) {
appParams,
false
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -167,6 +186,7 @@ dataSeries = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -181,7 +201,6 @@ dataSeries = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -206,6 +225,7 @@ dataSeries = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/anomalycor/server/main.js b/apps/anomalycor/server/main.js
index 2d3759b666..656689800a 100644
--- a/apps/anomalycor/server/main.js
+++ b/apps/anomalycor/server/main.js
@@ -4,7 +4,9 @@
import { Meteor } from "meteor/meteor";
import { mysql } from "meteor/pcel:mysql";
+import { moment } from "meteor/momentjs:moment";
import {
+ matsMethods,
matsTypes,
matsCollections,
matsDataUtils,
@@ -323,89 +325,82 @@ const doCurveParams = function () {
const params = matsCollections.CurveParamsInfo.find({
curve_params: { $exists: true },
}).fetch()[0].curve_params;
- for (let cp = 0; cp < params.length; cp++) {
+ for (let cp = 0; cp < params.length; cp += 1) {
matsCollections[params[cp]].remove({});
}
}
+
const modelOptionsMap = {};
let modelDateRangeMap = {};
const regionModelOptionsMap = {};
const forecastLengthOptionsMap = {};
const levelOptionsMap = {};
const variableModelOptionsMap = {};
- const masterRegionValuesMap = {};
+ const allRegionValuesMap = {};
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- metadataPool,
+ metadataPool, // eslint-disable-line no-undef
"select id,description from region_descriptions;"
);
- let masterRegDescription;
- let masterId;
- for (var j = 0; j < rows.length; j++) {
- masterRegDescription = rows[j].description.trim();
- masterId = rows[j].id;
- masterRegionValuesMap[masterId] = masterRegDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allRegionValuesMap[rows[j].id] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select model,regions,display_text,fcst_lens,levels,variable,mindate,maxdate from regions_per_model_mats_all_categories order by display_category, display_order;"
);
- for (let i = 0; i < rows.length; i++) {
- const model_value = rows[i].model.trim();
+ for (let i = 0; i < rows.length; i += 1) {
+ const modelValue = rows[i].model.trim();
const model = rows[i].display_text.trim();
- modelOptionsMap[model] = [model_value];
+ modelOptionsMap[model] = [modelValue];
const rowMinDate = moment.utc(rows[i].mindate * 1000).format("MM/DD/YYYY HH:mm");
const rowMaxDate = moment.utc(rows[i].maxdate * 1000).format("MM/DD/YYYY HH:mm");
- modelDateRangeMap[model] = { minDate: rowMinDate, maxDate: rowMaxDate };
+ modelDateRangeMap[model] = {
+ minDate: rowMinDate,
+ maxDate: rowMaxDate,
+ };
const forecastLengths = rows[i].fcst_lens;
- const forecastLengthArr = forecastLengths
+ forecastLengthOptionsMap[model] = forecastLengths
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (var j = 0; j < forecastLengthArr.length; j++) {
- forecastLengthArr[j] = forecastLengthArr[j].replace(/'|\[|\]/g, "");
- }
- forecastLengthOptionsMap[model] = forecastLengthArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (fhr) {
+ return fhr.replace(/'|\[|\]/g, "");
+ });
const { levels } = rows[i];
- const levelArr = levels
+ levelOptionsMap[model] = levels
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (var j = 0; j < levelArr.length; j++) {
- levelArr[j] = levelArr[j].replace(/'|\[|\]/g, "");
- }
- levelOptionsMap[model] = levelArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (level) {
+ return level.replace(/'|\[|\]/g, "");
+ });
const variables = rows[i].variable;
- const variableArr = variables
+ variableModelOptionsMap[model] = variables
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (var j = 0; j < variableArr.length; j++) {
- variableArr[j] = variableArr[j].replace(/'|\[|\]/g, "");
- }
- variableModelOptionsMap[model] = variableArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (variable) {
+ return variable.replace(/'|\[|\]/g, "");
+ });
const { regions } = rows[i];
- const regionsArrRaw = regions
+ regionModelOptionsMap[model] = regions
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const regionsArr = [];
- var dummyRegion;
- for (var j = 0; j < regionsArrRaw.length; j++) {
- dummyRegion = regionsArrRaw[j].replace(/'|\[|\]/g, "");
- regionsArr.push(masterRegionValuesMap[dummyRegion]);
- }
- regionModelOptionsMap[model] = regionsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (region) {
+ return allRegionValuesMap[region.replace(/'|\[|\]/g, "")];
+ });
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
if (matsCollections.label.findOne({ name: "label" }) === undefined) {
@@ -450,7 +445,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["data-source"].findOne({ name: "data-source" });
+ const currentParam = matsCollections["data-source"].findOne({
+ name: "data-source",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap) ||
!matsDataUtils.areObjectsEqual(currentParam.dates, modelDateRangeMap)
@@ -476,7 +473,7 @@ const doCurveParams = function () {
type: matsTypes.InputTypes.select,
optionsMap: regionModelOptionsMap,
options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]],
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
superiorNames: ["data-source"],
controlButtonCovered: true,
unique: false,
@@ -488,10 +485,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.region.findOne({ name: "region" });
+ const currentParam = matsCollections.region.findOne({ name: "region" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, regionModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterRegionValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allRegionValuesMap)
) {
// have to reload region data
matsCollections.region.update(
@@ -499,7 +496,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: regionModelOptionsMap,
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]],
default: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]][0],
},
@@ -547,7 +544,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["forecast-length"].findOne({
+ const currentParam = matsCollections["forecast-length"].findOne({
name: "forecast-length",
});
if (
@@ -734,7 +731,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.level.findOne({ name: "level" });
+ const currentParam = matsCollections.level.findOne({ name: "level" });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, levelOptionsMap)) {
// have to reload level data
matsCollections.level.update(
@@ -799,7 +796,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["curve-dates"].findOne({ name: "curve-dates" });
+ const currentParam = matsCollections["curve-dates"].findOne({
+ name: "curve-dates",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.startDate, minDate) ||
!matsDataUtils.areObjectsEqual(currentParam.stopDate, maxDate) ||
@@ -1046,7 +1045,8 @@ const doPlotGraph = function () {
Meteor.startup(function () {
matsCollections.Databases.remove({});
if (matsCollections.Databases.find({}).count() < 0) {
- console.log(
+ // eslint-disable-next-line no-console
+ console.warn(
"main startup: corrupted Databases collection: dropping Databases collection"
);
matsCollections.Databases.drop();
@@ -1063,7 +1063,7 @@ Meteor.startup(function () {
databases = Meteor.settings.private.databases;
}
if (databases !== null && databases !== undefined && Array.isArray(databases)) {
- for (let di = 0; di < databases.length; di++) {
+ for (let di = 0; di < databases.length; di += 1) {
matsCollections.Databases.insert(databases[di]);
}
}
@@ -1090,6 +1090,7 @@ Meteor.startup(function () {
);
if (cbConnection) {
// global cbScorecardSettingsPool
+ // eslint-disable-next-line no-undef
cbScorecardSettingsPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1116,6 +1117,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (metadataSettings) {
+ // eslint-disable-next-line no-undef
metadataPool = mysql.createPool(metadataSettings);
allPools.push({ pool: "metadataPool", role: matsTypes.DatabaseRoles.META_DATA });
}
@@ -1136,6 +1138,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (sumSettings) {
+ // eslint-disable-next-line no-undef
sumPool = mysql.createPool(sumSettings);
allPools.push({ pool: "sumPool", role: matsTypes.DatabaseRoles.SUMS_DATA });
}
@@ -1152,7 +1155,7 @@ Meteor.startup(function () {
appType: matsTypes.AppTypes.mats,
});
} catch (error) {
- console.log(error.message);
+ throw new Error(error.message);
}
});
@@ -1160,6 +1163,7 @@ Meteor.startup(function () {
// These are application specific mongo data - like curve params
// The appSpecificResetRoutines object is a special name,
// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way.
+// eslint-disable-next-line no-undef
appSpecificResetRoutines = [
doPlotGraph,
doCurveParams,
diff --git a/apps/cb-metar/.eslintrc.json b/apps/cb-metar/.eslintrc.json
index 5aab474ac1..b7e4dd3a3d 100644
--- a/apps/cb-metar/.eslintrc.json
+++ b/apps/cb-metar/.eslintrc.json
@@ -14,6 +14,8 @@
"settings": {
"import/resolver": "meteor"
},
+ // ignore directory with Gopa's experimental tests
+ "ignorePatterns": ["test"],
"rules": {
"prettier/prettier": "error",
"react/jsx-filename-extension": "off",
@@ -29,27 +31,6 @@
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
"prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
- "no-undef": "warn",
- "no-plusplus": "warn",
- "vars-on-top": "warn",
- "no-var": "warn",
- "block-scoped-var": "warn",
- "no-loop-func": "warn",
- "no-unused-vars": "warn",
- "no-console": "warn",
- "prefer-destructuring": "warn",
- "no-param-reassign": "warn",
- "camelcase": "warn",
- "no-redeclare": "warn",
- "no-shadow": "warn",
- "no-await-in-loop": "warn",
- "no-continue": "warn",
- "global-require": "warn",
- "no-use-before-define": "warn"
+ "no-await-in-loop": "warn"
}
}
diff --git a/apps/cb-metar/client/main.js b/apps/cb-metar/client/main.js
index a87407a1f4..ecd922b6a2 100644
--- a/apps/cb-metar/client/main.js
+++ b/apps/cb-metar/client/main.js
@@ -2,6 +2,7 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+// eslint-disable-next-line no-unused-vars
import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common";
import "@fortawesome/fontawesome-free";
import "@fortawesome/fontawesome-free/css/all.css";
diff --git a/apps/cb-metar/server/dataFunctions/data_contour.js b/apps/cb-metar/server/dataFunctions/data_contour.js
index ed5ab3abf8..c5955931a1 100644
--- a/apps/cb-metar/server/dataFunctions/data_contour.js
+++ b/apps/cb-metar/server/dataFunctions/data_contour.js
@@ -2,6 +2,8 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+/* global cbPool, Assets */
+
import {
matsCollections,
matsTypes,
@@ -12,6 +14,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContour = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
diff --git a/apps/cb-metar/server/dataFunctions/data_contour_diff.js b/apps/cb-metar/server/dataFunctions/data_contour_diff.js
index ab584f9683..536d9553d0 100644
--- a/apps/cb-metar/server/dataFunctions/data_contour_diff.js
+++ b/apps/cb-metar/server/dataFunctions/data_contour_diff.js
@@ -2,6 +2,8 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+/* global cbPool, Assets */
+
import {
matsCollections,
matsTypes,
@@ -14,6 +16,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContourDiff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -27,7 +30,6 @@ dataContourDiff = function (plotParams, plotFunction) {
const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
let dataNotFoundForAnyCurve = false;
let curves = JSON.parse(JSON.stringify(plotParams.curves));
@@ -219,10 +221,7 @@ dataContourDiff = function (plotParams, plotFunction) {
}
if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
// this is an error returned by the mysql database
error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
throw new Error(error);
diff --git a/apps/cb-metar/server/dataFunctions/data_dailymodelcycle.js b/apps/cb-metar/server/dataFunctions/data_dailymodelcycle.js
index 1e8aec8754..74d57275d6 100644
--- a/apps/cb-metar/server/dataFunctions/data_dailymodelcycle.js
+++ b/apps/cb-metar/server/dataFunctions/data_dailymodelcycle.js
@@ -2,6 +2,8 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+/* global cbPool, Assets */
+
import {
matsCollections,
matsTypes,
@@ -14,6 +16,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDailyModelCycle = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
diff --git a/apps/cb-metar/server/dataFunctions/data_dieoff.js b/apps/cb-metar/server/dataFunctions/data_dieoff.js
index d19e469280..421749f012 100644
--- a/apps/cb-metar/server/dataFunctions/data_dieoff.js
+++ b/apps/cb-metar/server/dataFunctions/data_dieoff.js
@@ -2,6 +2,8 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+/* global cbPool, Assets */
+
import {
matsCollections,
matsTypes,
@@ -14,6 +16,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDieoff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -178,8 +181,8 @@ dataDieoff = function (plotParams, plotFunction) {
if (regionType === "Predefined region") {
statement = cbPool.trfmSQLForDbTarget(queryTemplate);
} else {
- statement = "Station plot -- no one query.";
// send to matsMiddle
+ statement = "Station plot -- no one query.";
const tss = new matsMiddleDieoff.MatsMiddleDieoff(cbPool);
rows = tss.processStationQuery(
variable,
diff --git a/apps/cb-metar/server/dataFunctions/data_histogram.js b/apps/cb-metar/server/dataFunctions/data_histogram.js
index 0d38633d11..a67412ecde 100644
--- a/apps/cb-metar/server/dataFunctions/data_histogram.js
+++ b/apps/cb-metar/server/dataFunctions/data_histogram.js
@@ -2,6 +2,8 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+/* global cbPool, Assets */
+
import {
matsCollections,
matsTypes,
@@ -11,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataHistogram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
diff --git a/apps/cb-metar/server/dataFunctions/data_map.js b/apps/cb-metar/server/dataFunctions/data_map.js
index f728fc453f..c57f9f4538 100644
--- a/apps/cb-metar/server/dataFunctions/data_map.js
+++ b/apps/cb-metar/server/dataFunctions/data_map.js
@@ -2,6 +2,8 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+/* global cbPool */
+
import {
matsCollections,
matsTypes,
@@ -13,6 +15,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataMap = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
diff --git a/apps/cb-metar/server/dataFunctions/data_perfDiagram.js b/apps/cb-metar/server/dataFunctions/data_perfDiagram.js
index 433697a0c8..2cade5551e 100644
--- a/apps/cb-metar/server/dataFunctions/data_perfDiagram.js
+++ b/apps/cb-metar/server/dataFunctions/data_perfDiagram.js
@@ -2,6 +2,8 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+/* global cbPool, Assets */
+
import {
matsCollections,
matsTypes,
@@ -12,6 +14,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataPerformanceDiagram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
diff --git a/apps/cb-metar/server/dataFunctions/data_series.js b/apps/cb-metar/server/dataFunctions/data_series.js
index 8a309a6c71..9789002bc6 100644
--- a/apps/cb-metar/server/dataFunctions/data_series.js
+++ b/apps/cb-metar/server/dataFunctions/data_series.js
@@ -2,6 +2,8 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+/* global cbPool, Assets */
+
import {
matsCollections,
matsTypes,
@@ -14,6 +16,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSeries = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -148,7 +151,7 @@ dataSeries = function (plotParams, plotFunction) {
const startMoment = moment();
let finishMoment;
try {
- // math is done on forecastLength later on -= 1 set all analyses to 0
+ // math is done on forecastLength later on -- set all analyses to 0
if (forecastLength === "-99") {
forecastLength = "0";
}
diff --git a/apps/cb-metar/server/dataFunctions/data_threshold.js b/apps/cb-metar/server/dataFunctions/data_threshold.js
index f1b2c87e3b..ad1c84bf5a 100644
--- a/apps/cb-metar/server/dataFunctions/data_threshold.js
+++ b/apps/cb-metar/server/dataFunctions/data_threshold.js
@@ -2,6 +2,8 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+/* global cbPool, Assets */
+
import {
matsCollections,
matsTypes,
@@ -13,6 +15,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataThreshold = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -60,7 +63,7 @@ dataThreshold = function (plotParams, plotFunction) {
const allThresholdsStr = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
);
- for (let tidx = 0; tidx < allThresholdsStr.length; tidx++) {
+ for (let tidx = 0; tidx < allThresholdsStr.length; tidx += 1) {
allThresholdsStr[tidx] = allThresholdsStr[tidx].replace(/_/g, ".");
}
const allThresholds = allThresholdsStr.sort(function (a, b) {
diff --git a/apps/cb-metar/server/dataFunctions/data_validtime.js b/apps/cb-metar/server/dataFunctions/data_validtime.js
index e833a1e858..35cc56fd51 100644
--- a/apps/cb-metar/server/dataFunctions/data_validtime.js
+++ b/apps/cb-metar/server/dataFunctions/data_validtime.js
@@ -2,6 +2,8 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+/* global cbPool, Assets */
+
import {
matsCollections,
matsTypes,
@@ -14,6 +16,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataValidTime = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
diff --git a/apps/cb-metar/server/main.js b/apps/cb-metar/server/main.js
index 4d7eb61ce8..306b0cd605 100644
--- a/apps/cb-metar/server/main.js
+++ b/apps/cb-metar/server/main.js
@@ -337,49 +337,48 @@ const doCurveParams = async function () {
const sitesLocationMap = [];
const forecastLengthOptionsMap = {};
const thresholdsModelOptionsMap = {};
- const masterRegionValuesMap = {};
- const masterThresholdValuesMap = {};
+ const allRegionValuesMap = {};
+ const allThresholdValuesMap = {};
try {
+ // eslint-disable-next-line no-undef
const queryStr = cbPool.trfmSQLForDbTarget(
'select name, description from {{vxDBTARGET}} where type="MD" and docType="region" and version = "V01" and subset="COMMON"'
);
+ // eslint-disable-next-line no-undef
const rows = await cbPool.queryCB(queryStr);
if (rows.includes("queryCB ERROR: ")) {
// have this local try catch fail properly if the metadata isn't there
throw new Error(rows);
}
- let masterRegDescription;
- let masterShortName;
+
for (let j = 0; j < rows.length; j += 1) {
- masterRegDescription = rows[j].description.trim();
- masterShortName = rows[j].name.trim();
- masterRegionValuesMap[masterShortName] = masterRegDescription;
+ allRegionValuesMap[rows[j].name.trim()] = rows[j].description.trim();
}
} catch (err) {
throw new Error(err.message);
}
- let didx;
try {
- for (didx = 0; didx < variables.length; didx += 1) {
+ for (let didx = 0; didx < variables.length; didx += 1) {
const variable = variables[didx];
- masterThresholdValuesMap[variable] = {};
+ allThresholdValuesMap[variable] = {};
+ // eslint-disable-next-line no-undef
const queryStr = cbPool.trfmSQLForDbTarget(
- // `select raw thresholdDescriptions.${variable.toLowerCase()} from {{vxDBTARGET}} where type="MD" and docType="matsAux" and subset="COMMON" and version="V01"`
- `select raw thresholdDescriptions.ceiling from {{vxDBTARGET}} where type="MD" and docType="matsAux" and subset="COMMON" and version="V01"`
+ `select raw thresholdDescriptions.${variable.toLowerCase()} from {{vxDBTARGET}} where type="MD" and docType="matsAux" and subset="COMMON" and version="V01"`
+ // `select raw thresholdDescriptions.ceiling from {{vxDBTARGET}} where type="MD" and docType="matsAux" and subset="COMMON" and version="V01"`
);
+ // eslint-disable-next-line no-undef
const rows = await cbPool.queryCB(queryStr);
if (rows.includes("queryCB ERROR: ")) {
// have this local try catch fail properly if the metadata isn't there
throw new Error(rows);
}
- let jsonFriendlyTrsh;
- for (let j = 0; j < Object.keys(rows[0]).length; j += 1) {
- const masterDescription = rows[0][Object.keys(rows[0])[j]].trim();
- const masterTrsh = Object.keys(rows[0])[j].trim();
- jsonFriendlyTrsh = masterTrsh.replace(/\./g, "_");
- masterThresholdValuesMap[variable][jsonFriendlyTrsh] = masterDescription;
+ const allThresholds = Object.keys(rows[0]);
+ for (let j = 0; j < allThresholds.length; j += 1) {
+ // The replace here is because JSON doesn't like dots in the middle of keys
+ allThresholdValuesMap[variable][allThresholds[j].trim().replace(/\./g, "_")] =
+ rows[0][allThresholds[j]].trim();
}
}
} catch (err) {
@@ -387,7 +386,7 @@ const doCurveParams = async function () {
}
try {
- for (didx = 0; didx < variables.length; didx += 1) {
+ for (let didx = 0; didx < variables.length; didx += 1) {
const variable = variables[didx];
modelOptionsMap[variable] = {};
modelDateRangeMap[variable] = {};
@@ -395,12 +394,14 @@ const doCurveParams = async function () {
thresholdsModelOptionsMap[variable] = {};
regionModelOptionsMap[variable] = {};
+ // eslint-disable-next-line no-undef
const queryStr = cbPool.trfmSQLForDbTarget(
"select model, displayText, mindate, maxdate, fcstLens, " +
"regions, thresholds " +
`from {{vxDBTARGET}} where type="MD" and docType="matsGui" and subset="COMMON" and version="V01" and app="${variableMetadataDocs[variable]}" and numrecs>0 ` +
"order by displayCategory, displayOrder"
);
+ // eslint-disable-next-line no-undef
const rows = await cbPool.queryCB(queryStr);
if (rows.includes("queryCB ERROR: ")) {
@@ -426,24 +427,20 @@ const doCurveParams = async function () {
forecastLengthOptionsMap[variable][model] = rows[i].fcstLens.map(String);
// we want the full threshold descriptions in thresholdsModelOptionsMap, not just the thresholds
- rows[i].thresholds.sort(function (a, b) {
- return Number(a) - Number(b);
+ const { thresholds } = rows[i];
+ thresholdsModelOptionsMap[variable][model] = thresholds
+ .sort(function (a, b) {
+ return Number(a) - Number(b);
+ })
+ .map(function (threshold) {
+ return allThresholdValuesMap[variable][threshold.replace(/\./g, "_")];
+ });
+
+ // we want the full region descriptions in thresholdsModelOptionsMap, not just the regions
+ const { regions } = rows[i];
+ regionModelOptionsMap[variable][model] = regions.map(function (region) {
+ return allRegionValuesMap[region];
});
- const thresholdArr = [];
- for (let t = 0; t < rows[i].thresholds.length; t += 1) {
- thresholdArr.push(
- masterThresholdValuesMap[variable][
- rows[i].thresholds[t].replace(/\./g, "_")
- ]
- );
- }
- thresholdsModelOptionsMap[variable][model] = thresholdArr;
-
- const regionsArr = [];
- for (let ri = 0; ri < rows[i].regions.length; ri += 1) {
- regionsArr.push(masterRegionValuesMap[rows[i].regions[ri]]);
- }
- regionModelOptionsMap[variable][model] = regionsArr;
}
}
} catch (err) {
@@ -452,7 +449,9 @@ const doCurveParams = async function () {
try {
matsCollections.SiteMap.remove({});
+ // eslint-disable-next-line no-undef
let rows = await cbPool.queryCB(
+ // eslint-disable-next-line no-undef
cbPool.trfmSQLForDbTarget(
'select meta().id, {{vxCOLLECTION}}.* from {{vxDBTARGET}} where type="MD" and docType="station" and version = "V01" and subset="{{vxCOLLECTION}}";'
)
@@ -463,34 +462,38 @@ const doCurveParams = async function () {
}
rows = rows.sort((a, b) => (a.name > b.name ? 1 : -1));
for (let i = 0; i < rows.length; i += 1) {
- const siteId = rows[i].id;
const siteName = rows[i].name === undefined ? "unknown" : rows[i].name;
const siteDescription =
rows[i].description === undefined ? "unknown" : rows[i].description;
- const siteLat = rows[i].geo === undefined ? undefined : rows[i].geo[0].lat;
- const siteLon = rows[i].geo === undefined ? undefined : rows[i].geo[0].lon;
- const siteElev = rows[i].geo === undefined ? "unknown" : rows[i].geo[0].elev;
- if (siteLat >= 90 || siteLat <= -90) continue; // there's one station right at the south pole that the map doesn't know how to render at all
- siteOptionsMap[siteName] = [siteId];
-
- const point = [siteLat, siteLon];
- const obj = {
- name: siteName,
- origName: siteName,
- point,
- elevation: siteElev,
- options: {
- title: siteDescription,
- color: "red",
- size: 5,
- network: "METAR",
- peerOption: siteName,
- id: siteId,
- highLightColor: "blue",
- },
- };
- sitesLocationMap.push(obj);
- matsCollections.SiteMap.insert({ siteName, siteId });
+ const siteId = rows[i].id;
+ const siteLat = rows[i].geo === undefined ? -90 : Number(rows[i].geo[0].lat);
+ const siteLon = rows[i].geo === undefined ? 0 : Number(rows[i].geo[0].lon);
+ const siteElev = rows[i].geo === undefined ? 0 : rows[i].geo[0].elev;
+
+ // There's one station right at the south pole that the map doesn't know how to render at all, so exclude it.
+ // Also exclude stations with missing data
+ if (siteLat < 90 && siteLat > -90) {
+ siteOptionsMap[siteName] = [siteId];
+
+ const point = [siteLat, siteLon];
+ const obj = {
+ name: siteName,
+ origName: siteName,
+ point,
+ elevation: siteElev,
+ options: {
+ title: siteDescription,
+ color: "red",
+ size: 5,
+ network: "METAR",
+ peerOption: siteName,
+ id: siteId,
+ highLightColor: "blue",
+ },
+ };
+ sitesLocationMap.push(obj);
+ matsCollections.SiteMap.insert({ siteName, siteId });
+ }
}
} catch (err) {
throw new Error(err.message);
@@ -620,7 +623,7 @@ const doCurveParams = async function () {
regionModelOptionsMap[variables[0]][
Object.keys(regionModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -638,7 +641,7 @@ const doCurveParams = async function () {
const currentParam = matsCollections.region.findOne({ name: "region" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, regionModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterRegionValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allRegionValuesMap)
) {
// have to reload region data
matsCollections.region.update(
@@ -646,7 +649,7 @@ const doCurveParams = async function () {
{
$set: {
optionsMap: regionModelOptionsMap,
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
options:
regionModelOptionsMap[variables[0]][
Object.keys(regionModelOptionsMap[variables[0]])[0]
@@ -723,7 +726,7 @@ const doCurveParams = async function () {
thresholdsModelOptionsMap[variables[0]][
Object.keys(thresholdsModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterThresholdValuesMap,
+ valuesMap: allThresholdValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -744,7 +747,7 @@ const doCurveParams = async function () {
currentParam.optionsMap,
thresholdsModelOptionsMap
) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterThresholdValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allThresholdValuesMap)
) {
// have to reload threshold data
matsCollections.threshold.update(
@@ -752,7 +755,7 @@ const doCurveParams = async function () {
{
$set: {
optionsMap: thresholdsModelOptionsMap,
- valuesMap: masterThresholdValuesMap,
+ valuesMap: allThresholdValuesMap,
options:
thresholdsModelOptionsMap[variables[0]][
Object.keys(thresholdsModelOptionsMap[variables[0]])[0]
@@ -1073,14 +1076,14 @@ const doCurveParams = async function () {
}
// determine date defaults for dates and curveDates
- modelDateRangeMap = matsCollections.variable.findOne(
- { name: "variable" },
- { dates: 1 }
- ).dates;
const defaultDataSource = matsCollections["data-source"].findOne(
{ name: "data-source" },
{ default: 1 }
).default;
+ modelDateRangeMap = matsCollections.variable.findOne(
+ { name: "variable" },
+ { dates: 1 }
+ ).dates;
minDate = modelDateRangeMap[variables[0]][defaultDataSource].minDate;
maxDate = modelDateRangeMap[variables[0]][defaultDataSource].maxDate;
@@ -1516,6 +1519,7 @@ const doPlotGraph = function () {
Meteor.startup(function () {
matsCollections.Databases.remove({});
if (matsCollections.Databases.find({}).count() < 0) {
+ // eslint-disable-next-line no-console
console.warn(
"main startup: corrupted Databases collection: dropping Databases collection"
);
@@ -1541,6 +1545,7 @@ Meteor.startup(function () {
// create list of all pools
const allPools = [];
+
// connect to the couchbase cluster
const cbConnection = matsCollections.Databases.findOne(
{
@@ -1560,6 +1565,7 @@ Meteor.startup(function () {
// the cluster and bucket are intended to be global
if (cbConnection) {
+ // eslint-disable-next-line no-undef
cbPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1592,7 +1598,7 @@ Meteor.startup(function () {
dbType: matsTypes.DbTypes.couchbase,
});
} catch (error) {
- console.log(error.message);
+ throw new Error(error.message);
}
});
@@ -1600,6 +1606,7 @@ Meteor.startup(function () {
// These are application specific mongo data - like curve params
// The appSpecificResetRoutines object is a special name,
// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way.
+// eslint-disable-next-line no-undef
appSpecificResetRoutines = [
doPlotGraph,
doCurveParams,
diff --git a/apps/ceil-vis/.eslintrc.json b/apps/ceil-vis/.eslintrc.json
index e5e813ea94..79d49c5bb6 100644
--- a/apps/ceil-vis/.eslintrc.json
+++ b/apps/ceil-vis/.eslintrc.json
@@ -28,23 +28,6 @@
"space-before-function-paren": "off",
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
- "prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
- "no-undef": "warn",
- "no-plusplus": "warn",
- "vars-on-top": "warn",
- "no-var": "warn",
- "block-scoped-var": "warn",
- "no-loop-func": "warn",
- "no-unused-vars": "warn",
- "prefer-destructuring": "warn",
- "no-param-reassign": "warn",
- "camelcase": "warn",
- "no-redeclare": "warn",
- "no-shadow": "warn"
+ "prefer-arrow-callback": "off"
}
}
diff --git a/apps/ceil-vis/client/main.js b/apps/ceil-vis/client/main.js
index 0a7a17ea3b..ecd922b6a2 100644
--- a/apps/ceil-vis/client/main.js
+++ b/apps/ceil-vis/client/main.js
@@ -2,4 +2,8 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+// eslint-disable-next-line no-unused-vars
import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common";
+import "@fortawesome/fontawesome-free";
+import "@fortawesome/fontawesome-free/css/all.css";
+import "@fortawesome/fontawesome-free/js/all.js";
diff --git a/apps/ceil-vis/server/dataFunctions/data_contour.js b/apps/ceil-vis/server/dataFunctions/data_contour.js
index 7ee6688d8f..954284e670 100644
--- a/apps/ceil-vis/server/dataFunctions/data_contour.js
+++ b/apps/ceil-vis/server/dataFunctions/data_contour.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContour = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,50 +23,53 @@ dataContour = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
- const totalProcessingStart = moment();
+
+ const curves = JSON.parse(JSON.stringify(plotParams.curves));
+ if (curves.length > 1) {
+ throw new Error("INFO: There must only be one added curve.");
+ }
+
+ const axisMap = Object.create(null);
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- const curves = JSON.parse(JSON.stringify(plotParams.curves));
- if (curves.length > 1) {
- throw new Error("INFO: There must only be one added curve.");
- }
- const dataset = [];
- const axisMap = Object.create(null);
- // initialize variables specific to the curve
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" }).optionsMap[
variable
];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- const regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
let thresholdClause = "";
- let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") {
const thresholdStr = curve.threshold;
+ if (thresholdStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s threshold is undefined. Please assign it a value.`
+ );
+ }
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -76,16 +80,36 @@ dataContour = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold}`;
}
+
+ let validTimeClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
- validTimeClause = `and m0.time%(24*3600)/3600 IN(${validTimes})`;
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
+ validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -96,95 +120,105 @@ dataContour = function (plotParams, plotFunction) {
dateString = "m0.time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
// For contours, this functions as the colorbar label.
const statType = statisticOptionsMap[statisticSelect][0];
- curve.unitKey = statisticOptionsMap[statisticSelect][1];
+ [, curve.unitKey] = statisticOptionsMap[statisticSelect];
let d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
-
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
+
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
- }
- if (!dataFoundForCurve) {
- // we found no data for any curves so don't bother proceeding
- throw new Error("INFO: No valid data for any curves.");
- }
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
+ // this is NOT an error just a no data condition
+ dataFoundForCurve = false;
+ } else {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ }
- const postQueryStartMoment = moment();
+ if (!dataFoundForCurve) {
+ // we found no data for any curves so don't bother proceeding
+ throw new Error("INFO: No valid data for any curves.");
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
+ }
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
diff --git a/apps/ceil-vis/server/dataFunctions/data_contour_diff.js b/apps/ceil-vis/server/dataFunctions/data_contour_diff.js
index f6e4c1ee4d..f89b252d66 100644
--- a/apps/ceil-vis/server/dataFunctions/data_contour_diff.js
+++ b/apps/ceil-vis/server/dataFunctions/data_contour_diff.js
@@ -14,6 +14,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContourDiff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -24,53 +25,58 @@ dataContourDiff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
let dataNotFoundForAnyCurve = false;
+
+ let curves = JSON.parse(JSON.stringify(plotParams.curves));
+ const curvesLength = curves.length;
+ if (curvesLength !== 2) {
+ throw new Error("INFO: There must be two added curves.");
+ }
+
+ const axisMap = Object.create(null);
const showSignificance = plotParams.significance !== "none";
- const totalProcessingStart = moment();
+
+ let statType;
+ let statisticSelect;
+
+ let statement = "";
+ let error = "";
+ let dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- let curves = JSON.parse(JSON.stringify(plotParams.curves));
- const curvesLength = curves.length;
- if (curvesLength !== 2) {
- throw new Error("INFO: There must be two added curves.");
- }
- let dataset = [];
- const axisMap = Object.create(null);
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
let thresholdClause = "";
- let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") {
- var thresholdStr = curve.threshold;
+ const thresholdStr = curve.threshold;
+ if (thresholdStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s threshold is undefined. Please assign it a value.`
+ );
+ }
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -81,16 +87,36 @@ dataContourDiff = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold}`;
}
+
+ let validTimeClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
- validTimeClause = `and m0.time%(24*3600)/3600 IN(${validTimes})`;
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
+ validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -101,91 +127,98 @@ dataContourDiff = function (plotParams, plotFunction) {
dateString = "m0.time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- var statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
// For contours, this functions as the colorbar label.
- var statType = statisticOptionsMap[statisticSelect][0];
- curves[curveIndex].unitKey = statisticOptionsMap[statisticSelect][1];
+ [statType] = statisticOptionsMap[statisticSelect];
+ [, curve.unitKey] = statisticOptionsMap[statisticSelect];
- var d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
+ let d;
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
- dataNotFoundForAnyCurve = true;
- }
- const postQueryStartMoment = moment();
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ dataNotFoundForAnyCurve = true;
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
+ }
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
@@ -234,8 +267,9 @@ dataContourDiff = function (plotParams, plotFunction) {
statType === "ctc",
statType === "scalar"
);
- plotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
- curves = plotParams.curves;
+ const newPlotParams = plotParams;
+ newPlotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
+ curves = newPlotParams.curves;
dataset[0].name = matsPlotUtils.getCurveText(
matsTypes.PlotTypes.contourDiff,
curves[0]
@@ -251,7 +285,7 @@ dataContourDiff = function (plotParams, plotFunction) {
const result = matsDataProcessUtils.processDataContour(
dataset,
curveInfoParams,
- plotParams,
+ newPlotParams,
bookkeepingParams
);
plotFunction(result);
diff --git a/apps/ceil-vis/server/dataFunctions/data_dailymodelcycle.js b/apps/ceil-vis/server/dataFunctions/data_dailymodelcycle.js
index 1cb5c65caf..7d21f9f653 100644
--- a/apps/ceil-vis/server/dataFunctions/data_dailymodelcycle.js
+++ b/apps/ceil-vis/server/dataFunctions/data_dailymodelcycle.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDailyModelCycle = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,37 +24,48 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
let queryTableClause = "";
- var thresholdStr = curve.threshold;
+
+ let thresholdClause = "";
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -62,7 +74,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
key
] === thresholdStr
);
- let thresholdClause = "";
+
if (curve["utc-cycle-start"].length !== 1) {
throw new Error(
"INFO: Please select exactly one UTC Cycle Init Hour for this plot type."
@@ -71,24 +83,24 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
const utcCycleStart = Number(curve["utc-cycle-start"][0]);
utcCycleStarts[curveIndex] = utcCycleStart;
const utcCycleStartClause = `and floor(((m0.time+1800) - m0.fcst_len*3600)%(24*3600)/3600) IN(${utcCycleStart})`;
+
const forecastLengthClause = "and m0.fcst_len < 24";
- var dateClause;
- let siteDateClause = "";
- let siteMatchClause = "";
- let sitesClause = "";
- const siteMap = matsCollections.StationMap.findOne(
- { name: "stations" },
- { optionsMap: 1 }
- ).optionsMap;
+
+ let statisticClause;
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap;
- var statisticClause;
+
+ let dateClause;
+ let siteDateClause = "";
+ let siteMatchClause = "";
+ let sitesClause = "";
+
const regionType = curve["region-type"];
if (regionType === "Predefined region") {
- var regionStr = curve.region;
+ const regionStr = curve.region;
const region = Object.keys(
matsCollections.region.findOne({ name: "region" }).valuesMap
).find(
@@ -116,16 +128,17 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
statisticClause = statisticClause.replace(/m0\.ceil/g, "m0.vis100");
statisticClause = statisticClause.replace(/o\.ceil/g, "o.vis100");
}
+
+ const siteMap = matsCollections.StationMap.findOne(
+ { name: "stations" },
+ { optionsMap: 1 }
+ ).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- var thisSite;
- var thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.madis_id in('${querySites.join("','")}')`;
} else {
throw new Error(
@@ -136,11 +149,12 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
siteMatchClause = "and m0.madis_id = o.madis_id and m0.time = o.time ";
}
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -148,52 +162,52 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select ceil(3600*floor((m0.time+1800)/3600)) as avtime, " +
- "count(distinct ceil(3600*floor((m0.time+1800)/3600))) as N_times, " +
- "min(ceil(3600*floor((m0.time+1800)/3600))) as min_secs, " +
- "max(ceil(3600*floor((m0.time+1800)/3600))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{utcCycleStartClause}} " +
- "{{thresholdClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select ceil(3600*floor((m0.time+1800)/3600)) as avtime, " +
+ "count(distinct ceil(3600*floor((m0.time+1800)/3600))) as N_times, " +
+ "min(ceil(3600*floor((m0.time+1800)/3600))) as min_secs, " +
+ "max(ceil(3600*floor((m0.time+1800)/3600))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{utcCycleStartClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -209,6 +223,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -223,7 +238,6 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -248,6 +262,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ceil-vis/server/dataFunctions/data_dieoff.js b/apps/ceil-vis/server/dataFunctions/data_dieoff.js
index b67e8e19e2..cd9c532da5 100644
--- a/apps/ceil-vis/server/dataFunctions/data_dieoff.js
+++ b/apps/ceil-vis/server/dataFunctions/data_dieoff.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDieoff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,34 +24,44 @@ dataDieoff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
let queryTableClause = "";
- var thresholdStr = curve.threshold;
+
+ let thresholdClause = "";
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -59,38 +70,39 @@ dataDieoff = function (plotParams, plotFunction) {
key
] === thresholdStr
);
- let thresholdClause = "";
- var validTimes;
+
let validTimeClause = "";
- var utcCycleStart;
+ let validTimes;
+
let utcCycleStartClause = "";
+ let utcCycleStart;
+
const forecastLengthStr = curve["dieoff-type"];
const forecastLengthOptionsMap = matsCollections["dieoff-type"].findOne(
{ name: "dieoff-type" },
{ optionsMap: 1 }
).optionsMap;
const forecastLength = forecastLengthOptionsMap[forecastLengthStr][0];
- const forecastLengthClause = "";
+
+ let statisticClause;
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
- var dateClause;
+
+ let dateClause;
let siteDateClause = "";
let siteMatchClause = "";
let sitesClause = "";
- const siteMap = matsCollections.StationMap.findOne(
- { name: "stations" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- var statisticClause;
+
const regionType = curve["region-type"];
if (regionType === "Predefined region") {
- var regionStr = curve.region;
+ const regionStr = curve.region;
const region = Object.keys(
matsCollections.region.findOne({ name: "region" }).valuesMap
).find(
@@ -118,16 +130,17 @@ dataDieoff = function (plotParams, plotFunction) {
statisticClause = statisticClause.replace(/m0\.ceil/g, "m0.vis100");
statisticClause = statisticClause.replace(/o\.ceil/g, "o.vis100");
}
+
+ const siteMap = matsCollections.StationMap.findOne(
+ { name: "stations" },
+ { optionsMap: 1 }
+ ).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- var thisSite;
- var thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.madis_id in('${querySites.join("','")}')`;
} else {
throw new Error(
@@ -138,6 +151,7 @@ dataDieoff = function (plotParams, plotFunction) {
siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
siteMatchClause = "and m0.madis_id = o.madis_id and m0.time = o.time ";
}
+
if (forecastLength === matsTypes.ForecastTypes.dieoff) {
validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
@@ -157,11 +171,12 @@ dataDieoff = function (plotParams, plotFunction) {
} else {
dateClause = `and m0.time-m0.fcst_len*3600 = ${fromSecs}`;
}
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -169,54 +184,52 @@ dataDieoff = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.fcst_len as fcst_lead, " +
- "count(distinct ceil(3600*floor((m0.time+1800)/3600))) as N_times, " +
- "min(ceil(3600*floor((m0.time+1800)/3600))) as min_secs, " +
- "max(ceil(3600*floor((m0.time+1800)/3600))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{utcCycleStartClause}} " +
- "group by fcst_lead " +
- "order by fcst_lead" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.fcst_len as fcst_lead, " +
+ "count(distinct ceil(3600*floor((m0.time+1800)/3600))) as N_times, " +
+ "min(ceil(3600*floor((m0.time+1800)/3600))) as min_secs, " +
+ "max(ceil(3600*floor((m0.time+1800)/3600))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{utcCycleStartClause}} " +
+ "group by fcst_lead " +
+ "order by fcst_lead" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -232,6 +245,7 @@ dataDieoff = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -246,7 +260,6 @@ dataDieoff = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -271,6 +284,7 @@ dataDieoff = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ceil-vis/server/dataFunctions/data_histogram.js b/apps/ceil-vis/server/dataFunctions/data_histogram.js
index 4bc7a94ca3..adef84110c 100644
--- a/apps/ceil-vis/server/dataFunctions/data_histogram.js
+++ b/apps/ceil-vis/server/dataFunctions/data_histogram.js
@@ -11,6 +11,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataHistogram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -21,44 +22,45 @@ dataHistogram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
- const alreadyMatched = false;
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
const dataFoundForCurve = [];
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+ const alreadyMatched = false;
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
+
+ const axisMap = Object.create(null);
+ let statType;
+ let varUnits;
+
+ let statement = "";
+ let error = "";
const dataset = [];
const allReturnedSubStats = [];
const allReturnedSubSecs = [];
- const axisMap = Object.create(null);
// process user bin customizations
const binParams = matsDataUtils.setHistogramParameters(plotParams);
const { yAxisFormat } = binParams;
const { binNum } = binParams;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
dataFoundForCurve[curveIndex] = true;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -68,17 +70,16 @@ dataHistogram = function (plotParams, plotFunction) {
] === thresholdStr
);
const thresholdClause = `and m0.trsh = ${threshold}`;
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
}
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -86,12 +87,27 @@ dataHistogram = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
- var varUnits = statisticOptionsMap[statisticSelect][1];
+ [statType] = statisticOptionsMap[statisticSelect];
+ [, varUnits] = statisticOptionsMap[statisticSelect];
let axisKey = yAxisFormat;
if (yAxisFormat === "Relative frequency") {
axisKey += " (x100)";
@@ -99,46 +115,46 @@ dataHistogram = function (plotParams, plotFunction) {
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
curves[curveIndex].binNum = binNum; // stash the binNum to use it later for bar chart options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.time as avtime, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.time as avtime, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -156,6 +172,7 @@ dataHistogram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/ceil-vis/server/dataFunctions/data_map.js b/apps/ceil-vis/server/dataFunctions/data_map.js
index 478d5c02f1..69e6b197a5 100644
--- a/apps/ceil-vis/server/dataFunctions/data_map.js
+++ b/apps/ceil-vis/server/dataFunctions/data_map.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataMap = function (plotParams, plotFunction) {
const appParams = {
plotType: matsTypes.PlotTypes.map,
@@ -21,20 +22,28 @@ dataMap = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
- const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
+
const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+ const dataRequests = {}; // used to store data queries
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
if (curves.length > 1) {
throw new Error("INFO: There must only be one added curve.");
}
+
+ let statement = "";
+ let error = "";
const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" }).optionsMap[
variable
@@ -44,11 +53,7 @@ dataMap = function (plotParams, plotFunction) {
const obsTable =
modelTable.includes("ret_") || modelTable.includes("Ret_") ? "obs_retro" : "obs";
const queryTableClause = `from ${databaseRef.modelDB}.${obsTable} as o, ${databaseRef.modelDB}.${modelTable} as m0 `;
- let sitesClause = "";
- const siteMap = matsCollections.StationMap.findOne(
- { name: "stations" },
- { optionsMap: 1 }
- ).optionsMap;
+
const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
@@ -58,13 +63,16 @@ dataMap = function (plotParams, plotFunction) {
key
] === thresholdStr
);
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time+1800)%(24*3600)/3600) IN(${validTimes})`;
}
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
+
const { statistic } = curve;
let statisticClause =
"sum(if((m0.ceil < {{threshold}}) and (o.ceil < {{threshold}}),1,0)) as hit, sum(if((m0.ceil < {{threshold}}) and NOT (o.ceil < {{threshold}}),1,0)) as fa, " +
@@ -77,16 +85,19 @@ dataMap = function (plotParams, plotFunction) {
statisticClause = statisticClause.replace(/m0\.ceil/g, "m0.vis100");
statisticClause = statisticClause.replace(/o\.ceil/g, "o.vis100");
}
+
+ let sitesClause = "";
+
+ const siteMap = matsCollections.StationMap.findOne(
+ { name: "stations" },
+ { optionsMap: 1 }
+ ).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- let thisSite;
- let thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.madis_id in('${querySites.join("','")}')`;
} else {
throw new Error(
@@ -97,85 +108,105 @@ dataMap = function (plotParams, plotFunction) {
const siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
const siteMatchClause = "and m0.madis_id = o.madis_id and m0.time = o.time";
- let statement =
- "select m0.madis_id as sta_id, " +
- "count(distinct ceil(3600*floor((m0.time+1800)/3600))) as N_times, " +
- "min(ceil(3600*floor((m0.time+1800)/3600))) as min_secs, " +
- "max(ceil(3600*floor((m0.time+1800)/3600))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by sta_id " +
- "order by N0" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- dataRequests[label] = statement;
-
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBMapCTC(
- sumPool,
- statement,
- modelTable,
- statistic,
- siteMap,
- appParams
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.length,
- };
- // get the data back from the query
- var d = queryResult.data;
- var dPurple = queryResult.dataPurple;
- var dPurpleBlue = queryResult.dataPurpleBlue;
- var dBlue = queryResult.dataBlue;
- var dBlueGreen = queryResult.dataBlueGreen;
- var dGreen = queryResult.dataGreen;
- var dGreenYellow = queryResult.dataGreenYellow;
- var dYellow = queryResult.dataYellow;
- var dOrange = queryResult.dataOrange;
- var dOrangeRed = queryResult.dataOrangeRed;
- var dRed = queryResult.dataRed;
- var { valueLimits } = queryResult;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ let d;
+ let dPurple;
+ let dPurpleBlue;
+ let dBlue;
+ let dBlueGreen;
+ let dGreen;
+ let dGreenYellow;
+ let dYellow;
+ let dOrange;
+ let dOrangeRed;
+ let dRed;
+ let valueLimits;
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "select m0.madis_id as sta_id, " +
+ "count(distinct ceil(3600*floor((m0.time+1800)/3600))) as N_times, " +
+ "min(ceil(3600*floor((m0.time+1800)/3600))) as min_secs, " +
+ "max(ceil(3600*floor((m0.time+1800)/3600))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by sta_id " +
+ "order by N0" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ dataRequests[label] = statement;
+
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBMapCTC(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ modelTable,
+ statistic,
+ siteMap,
+ appParams
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = "Station plot -- no one query.";
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ dPurple = queryResult.dataPurple;
+ dPurpleBlue = queryResult.dataPurpleBlue;
+ dBlue = queryResult.dataBlue;
+ dBlueGreen = queryResult.dataBlueGreen;
+ dGreen = queryResult.dataGreen;
+ dGreenYellow = queryResult.dataGreenYellow;
+ dYellow = queryResult.dataYellow;
+ dOrange = queryResult.dataOrange;
+ dOrangeRed = queryResult.dataOrangeRed;
+ dRed = queryResult.dataRed;
+ valueLimits = queryResult.valueLimits;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
+ }
+
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
}
+ } else {
+ // this is a difference curve -- not supported for maps
+ throw new Error(
+ "INFO: Difference curves are not supported for maps, as there is only one curve."
+ );
}
+ const postQueryStartMoment = moment();
let cOptions = matsDataCurveOpsUtils.generateCTCMapCurveOptions(curve, d, appParams); // generate map with site data
dataset.push(cOptions);
@@ -303,6 +334,15 @@ dataMap = function (plotParams, plotFunction) {
); // generate red text layer
dataset.push(cOptions);
+ const postQueryFinishMoment = moment();
+ dataRequests[`post data retrieval (query) process time - ${label}`] = {
+ begin: postQueryStartMoment.format(),
+ finish: postQueryFinishMoment.format(),
+ duration: `${moment
+ .duration(postQueryFinishMoment.diff(postQueryStartMoment))
+ .asSeconds()} seconds`,
+ };
+
const resultOptions = matsDataPlotOpsUtils.generateMapPlotOptions(true);
const totalProcessingFinish = moment();
dataRequests["total retrieval and processing time for curve set"] = {
diff --git a/apps/ceil-vis/server/dataFunctions/data_perfDiagram.js b/apps/ceil-vis/server/dataFunctions/data_perfDiagram.js
index 0023dfc36f..8b167a1434 100644
--- a/apps/ceil-vis/server/dataFunctions/data_perfDiagram.js
+++ b/apps/ceil-vis/server/dataFunctions/data_perfDiagram.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataPerformanceDiagram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,52 +23,47 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statType;
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const binParam = curve["bin-parameter"];
const binClause = matsCollections["bin-parameter"].findOne({
name: "bin-parameter",
}).optionsMap[binParam];
- var { variable } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
let thresholdClause = "";
- let validTimeClause = "";
- let forecastLengthClause = "";
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let dateString = "";
- let dateClause = "";
if (binParam !== "Threshold") {
- var thresholdStr = curve.threshold;
+ const thresholdStr = curve.threshold;
if (thresholdStr === undefined) {
throw new Error(
`INFO: ${label}'s threshold is undefined. Please assign it a value.`
@@ -83,12 +79,16 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold}`;
}
+
+ let validTimeClause = "";
if (binParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
- validTimeClause = `and m0.time%(24*3600)/3600 IN(${validTimes})`;
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
+ validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (binParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
if (forecastLength === undefined) {
@@ -98,62 +98,79 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
}
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const statisticSelect = "PerformanceDiagram";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ let dateString = "";
+ let dateClause = "";
if (binParam === "Init Date") {
dateString = "m0.time-m0.fcst_len*3600";
} else {
dateString = "m0.time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const statisticSelect = "PerformanceDiagram";
- var statType = "ctc";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// variable + statistic (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ statType = "ctc";
curves[curveIndex].axisKey = statisticSelect; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{binClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "((sum(m0.yy)+0.00)/sum(m0.yy+m0.ny)) as pod, ((sum(m0.yn)+0.00)/sum(m0.yn+m0.yy)) as far, " +
- "sum(m0.yy+m0.ny) as oy_all, sum(m0.yn+m0.nn) as on_all, group_concat(m0.time, ';', m0.yy, ';', " +
- "m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0 " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by binVal " +
- "order by binVal" +
- ";";
-
- statement = statement.replace("{{binClause}}", binClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "{{binClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "((sum(m0.yy)+0.00)/sum(m0.yy+m0.ny)) as pod, ((sum(m0.yn)+0.00)/sum(m0.yn+m0.yy)) as far, " +
+ "sum(m0.yy+m0.ny) as oy_all, sum(m0.yn+m0.nn) as on_all, group_concat(m0.time, ';', m0.yy, ';', " +
+ "m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0 " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by binVal " +
+ "order by binVal" +
+ ";";
+
+ statement = statement.replace("{{binClause}}", binClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBPerformanceDiagram(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -169,6 +186,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -183,7 +201,6 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -191,7 +208,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
ymax = ymax > d.ymax ? ymax : d.ymax;
}
} else {
- // this is a difference curve -- not supported for ROC plots
+ // this is a difference curve -- not supported for performance diagrams
throw new Error(
"INFO: Difference curves are not supported for performance diagrams, as they do not feature consistent x or y values across all curves."
);
@@ -199,6 +216,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ceil-vis/server/dataFunctions/data_series.js b/apps/ceil-vis/server/dataFunctions/data_series.js
index 4dc9470a8d..a9ab761d0d 100644
--- a/apps/ceil-vis/server/dataFunctions/data_series.js
+++ b/apps/ceil-vis/server/dataFunctions/data_series.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSeries = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,37 +24,48 @@ dataSeries = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
let queryTableClause = "";
- var thresholdStr = curve.threshold;
+
+ let thresholdClause = "";
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -62,31 +74,38 @@ dataSeries = function (plotParams, plotFunction) {
key
] === thresholdStr
);
- let thresholdClause = "";
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time+1800)%(24*3600)/3600) IN(${validTimes})`;
}
+
let forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- var dateClause;
- let siteDateClause = "";
- let siteMatchClause = "";
- let sitesClause = "";
- const siteMap = matsCollections.StationMap.findOne(
- { name: "stations" },
- { optionsMap: 1 }
- ).optionsMap;
+
+ let statisticClause;
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap;
- var statisticClause;
+
+ const averageStr = curve.average;
+ const averageOptionsMap = matsCollections.average.findOne(
+ { name: "average" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const average = averageOptionsMap[averageStr][0];
+
+ let dateClause;
+ let siteDateClause = "";
+ let siteMatchClause = "";
+ let sitesClause = "";
+
const regionType = curve["region-type"];
if (regionType === "Predefined region") {
- var regionStr = curve.region;
+ const regionStr = curve.region;
const region = Object.keys(
matsCollections.region.findOne({ name: "region" }).valuesMap
).find(
@@ -114,16 +133,17 @@ dataSeries = function (plotParams, plotFunction) {
statisticClause = statisticClause.replace(/m0\.ceil/g, "m0.vis100");
statisticClause = statisticClause.replace(/o\.ceil/g, "o.vis100");
}
+
+ const siteMap = matsCollections.StationMap.findOne(
+ { name: "stations" },
+ { optionsMap: 1 }
+ ).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- var thisSite;
- var thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.madis_id in('${querySites.join("','")}')`;
} else {
throw new Error(
@@ -134,17 +154,12 @@ dataSeries = function (plotParams, plotFunction) {
siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
siteMatchClause = "and m0.madis_id = o.madis_id and m0.time = o.time ";
}
- const averageStr = curve.average;
- const averageOptionsMap = matsCollections.average.findOne(
- { name: "average" },
- { optionsMap: 1 }
- ).optionsMap;
- const average = averageOptionsMap[averageStr][0];
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -152,53 +167,51 @@ dataSeries = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select {{average}} as avtime, " +
- "count(distinct ceil(3600*floor((m0.time+1800)/3600))) as N_times, " +
- "min(ceil(3600*floor((m0.time+1800)/3600))) as min_secs, " +
- "max(ceil(3600*floor((m0.time+1800)/3600))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "select {{average}} as avtime, " +
+ "count(distinct ceil(3600*floor((m0.time+1800)/3600))) as N_times, " +
+ "min(ceil(3600*floor((m0.time+1800)/3600))) as min_secs, " +
+ "max(ceil(3600*floor((m0.time+1800)/3600))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
- statement = statement.replace("{{average}}", average);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- dataRequests[label] = statement;
+ statement = statement.replace("{{average}}", average);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ dataRequests[label] = statement;
- // math is done on forecastLength later on -- set all analyses to 0
- if (forecastLength === "-99") {
- forecastLength = "0";
- }
+ // math is done on forecastLength later on -- set all analyses to 0
+ if (forecastLength === "-99") {
+ forecastLength = "0";
+ }
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBTimeSeries(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
model,
forecastLength,
@@ -210,7 +223,9 @@ dataSeries = function (plotParams, plotFunction) {
appParams,
false
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -226,6 +241,7 @@ dataSeries = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -240,7 +256,6 @@ dataSeries = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -265,6 +280,7 @@ dataSeries = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ceil-vis/server/dataFunctions/data_threshold.js b/apps/ceil-vis/server/dataFunctions/data_threshold.js
index 737226b47e..f0aac94918 100644
--- a/apps/ceil-vis/server/dataFunctions/data_threshold.js
+++ b/apps/ceil-vis/server/dataFunctions/data_threshold.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataThreshold = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,51 +24,50 @@ dataThreshold = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
}
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -75,11 +75,26 @@ dataThreshold = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -87,44 +102,44 @@ dataThreshold = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.trsh/100 as thresh, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by thresh " +
- "order by thresh" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.trsh/100 as thresh, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by thresh " +
+ "order by thresh" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -140,6 +155,7 @@ dataThreshold = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -154,7 +170,6 @@ dataThreshold = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -179,6 +194,7 @@ dataThreshold = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ceil-vis/server/dataFunctions/data_validtime.js b/apps/ceil-vis/server/dataFunctions/data_validtime.js
index 05cb8e2365..2a5d68437c 100644
--- a/apps/ceil-vis/server/dataFunctions/data_validtime.js
+++ b/apps/ceil-vis/server/dataFunctions/data_validtime.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataValidTime = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,34 +24,44 @@ dataValidTime = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
let queryTableClause = "";
- var thresholdStr = curve.threshold;
+
+ let thresholdClause = "";
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -59,29 +70,29 @@ dataValidTime = function (plotParams, plotFunction) {
key
] === thresholdStr
);
- let thresholdClause = "";
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
+
+ let statisticClause;
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
- var dateClause;
+
+ let dateClause;
let siteDateClause = "";
let siteMatchClause = "";
let sitesClause = "";
- const siteMap = matsCollections.StationMap.findOne(
- { name: "stations" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- var statisticClause;
+
const regionType = curve["region-type"];
if (regionType === "Predefined region") {
- var regionStr = curve.region;
+ const regionStr = curve.region;
const region = Object.keys(
matsCollections.region.findOne({ name: "region" }).valuesMap
).find(
@@ -109,16 +120,17 @@ dataValidTime = function (plotParams, plotFunction) {
statisticClause = statisticClause.replace(/m0\.ceil/g, "m0.vis100");
statisticClause = statisticClause.replace(/o\.ceil/g, "o.vis100");
}
+
+ const siteMap = matsCollections.StationMap.findOne(
+ { name: "stations" },
+ { optionsMap: 1 }
+ ).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- var thisSite;
- var thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.madis_id in('${querySites.join("','")}')`;
} else {
throw new Error(
@@ -129,11 +141,12 @@ dataValidTime = function (plotParams, plotFunction) {
siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
siteMatchClause = "and m0.madis_id = o.madis_id and m0.time = o.time ";
}
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -141,50 +154,50 @@ dataValidTime = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select floor((m0.time+1800)%(24*3600)/3600) as hr_of_day, " +
- "count(distinct ceil(3600*floor((m0.time+1800)/3600))) as N_times, " +
- "min(ceil(3600*floor((m0.time+1800)/3600))) as min_secs, " +
- "max(ceil(3600*floor((m0.time+1800)/3600))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{thresholdClause}} " +
- "{{forecastLengthClause}} " +
- "group by hr_of_day " +
- "order by hr_of_day" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select floor((m0.time+1800)%(24*3600)/3600) as hr_of_day, " +
+ "count(distinct ceil(3600*floor((m0.time+1800)/3600))) as N_times, " +
+ "min(ceil(3600*floor((m0.time+1800)/3600))) as min_secs, " +
+ "max(ceil(3600*floor((m0.time+1800)/3600))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by hr_of_day " +
+ "order by hr_of_day" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -200,6 +213,7 @@ dataValidTime = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -214,7 +228,6 @@ dataValidTime = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -239,6 +252,7 @@ dataValidTime = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ceil-vis/server/main.js b/apps/ceil-vis/server/main.js
index 2145a1482a..9ee7b4dcd3 100644
--- a/apps/ceil-vis/server/main.js
+++ b/apps/ceil-vis/server/main.js
@@ -4,7 +4,9 @@
import { Meteor } from "meteor/meteor";
import { mysql } from "meteor/pcel:mysql";
+import { moment } from "meteor/momentjs:moment";
import {
+ matsMethods,
matsTypes,
matsCollections,
matsDataUtils,
@@ -327,7 +329,7 @@ const doCurveParams = function () {
const params = matsCollections.CurveParamsInfo.find({
curve_params: { $exists: true },
}).fetch()[0].curve_params;
- for (let cp = 0; cp < params.length; cp++) {
+ for (let cp = 0; cp < params.length; cp += 1) {
matsCollections[params[cp]].remove({});
}
}
@@ -339,67 +341,56 @@ const doCurveParams = function () {
const sitesLocationMap = [];
const forecastLengthOptionsMap = {};
const thresholdsModelOptionsMap = {};
- const masterRegionValuesMap = {};
- const masterThresholdValuesMap = {};
+ const allRegionValuesMap = {};
+ const allThresholdValuesMap = {};
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- metadataPool,
+ metadataPool, // eslint-disable-line no-undef
"select short_name,description from region_descriptions;"
);
- let masterRegDescription;
- let masterShortName;
- for (var j = 0; j < rows.length; j++) {
- masterRegDescription = rows[j].description.trim();
- masterShortName = rows[j].short_name.trim();
- masterRegionValuesMap[masterShortName] = masterRegDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allRegionValuesMap[rows[j].short_name.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
- let rows;
- let didx;
-
try {
- for (didx = 0; didx < variables.length; didx++) {
- masterThresholdValuesMap[variables[didx]] = {};
- rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ for (let didx = 0; didx < variables.length; didx += 1) {
+ allThresholdValuesMap[variables[didx]] = {};
+ const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
+ sumPool, // eslint-disable-line no-undef
`select trsh,description from ${
variableDBNames[variables[didx]].modelDB
}.threshold_descriptions;`
);
- var masterDescription;
- var masterTrsh;
- for (var j = 0; j < rows.length; j++) {
- masterDescription = rows[j].description.trim();
- masterTrsh = rows[j].trsh.trim();
- masterThresholdValuesMap[variables[didx]][masterTrsh] = masterDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allThresholdValuesMap[variables[didx]][rows[j].trsh.trim()] =
+ rows[j].description.trim();
}
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
- for (didx = 0; didx < variables.length; didx++) {
- modelOptionsMap[variables[didx]] = {};
- modelDateRangeMap[variables[didx]] = {};
- forecastLengthOptionsMap[variables[didx]] = {};
- thresholdsModelOptionsMap[variables[didx]] = {};
- regionModelOptionsMap[variables[didx]] = {};
-
- rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
- `select model,regions,display_text,fcst_lens,trsh,mindate,maxdate from ${
- variableDBNames[variables[didx]].sumsDB
- }.regions_per_model_mats_all_categories order by display_category, display_order;`
+ for (let didx = 0; didx < variables.length; didx += 1) {
+ const variable = variables[didx];
+ modelOptionsMap[variable] = {};
+ modelDateRangeMap[variable] = {};
+ forecastLengthOptionsMap[variable] = {};
+ thresholdsModelOptionsMap[variable] = {};
+ regionModelOptionsMap[variable] = {};
+
+ const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
+ sumPool, // eslint-disable-line no-undef
+ `select model,regions,display_text,fcst_lens,trsh,mindate,maxdate from ${variableDBNames[variable].sumsDB}.regions_per_model_mats_all_categories order by display_category, display_order;`
);
- for (var i = 0; i < rows.length; i++) {
- const model_value = rows[i].model.trim();
+ for (let i = 0; i < rows.length; i += 1) {
+ const modelValue = rows[i].model.trim();
const model = rows[i].display_text.trim();
- modelOptionsMap[variables[didx]][model] = [model_value];
+ modelOptionsMap[variable][model] = [modelValue];
const rowMinDate = moment
.utc(rows[i].mindate * 1000)
@@ -407,86 +398,82 @@ const doCurveParams = function () {
const rowMaxDate = moment
.utc(rows[i].maxdate * 1000)
.format("MM/DD/YYYY HH:mm");
- modelDateRangeMap[variables[didx]][model] = {
+ modelDateRangeMap[variable][model] = {
minDate: rowMinDate,
maxDate: rowMaxDate,
};
const forecastLengths = rows[i].fcst_lens;
- const forecastLengthArr = forecastLengths
+ forecastLengthOptionsMap[variable][model] = forecastLengths
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (var j = 0; j < forecastLengthArr.length; j++) {
- forecastLengthArr[j] = forecastLengthArr[j].replace(/'|\[|\]/g, "");
- }
- forecastLengthOptionsMap[variables[didx]][model] = forecastLengthArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (fhr) {
+ return fhr.replace(/'|\[|\]/g, "");
+ });
const thresholds = rows[i].trsh;
- const thresholdsArrRaw = thresholds
+ thresholdsModelOptionsMap[variable][model] = thresholds
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const thresholdsArr = [];
- var dummyThresh;
- for (var j = 0; j < thresholdsArrRaw.length; j++) {
- dummyThresh = thresholdsArrRaw[j].replace(/'|\[|\]/g, "");
- thresholdsArr.push(masterThresholdValuesMap[variables[didx]][dummyThresh]);
- }
- thresholdsModelOptionsMap[variables[didx]][model] = thresholdsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (threshold) {
+ return allThresholdValuesMap[variable][threshold.replace(/'|\[|\]/g, "")];
+ });
const { regions } = rows[i];
- const regionsArrRaw = regions
+ regionModelOptionsMap[variable][model] = regions
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const regionsArr = [];
- var dummyRegion;
- for (var j = 0; j < regionsArrRaw.length; j++) {
- dummyRegion = regionsArrRaw[j].replace(/'|\[|\]/g, "");
- regionsArr.push(masterRegionValuesMap[dummyRegion]);
- }
- regionModelOptionsMap[variables[didx]][model] = regionsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (region) {
+ return allRegionValuesMap[region.replace(/'|\[|\]/g, "")];
+ });
}
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
matsCollections.SiteMap.remove({});
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select madis_id,name,lat,lon,elev,description from madis3.metars_mats_global where lat > -16380 and lat < 16380 and lon > -32760 and lon < 32760 order by name;"
);
- for (var i = 0; i < rows.length; i++) {
- const site_name = rows[i].name;
- const site_description = rows[i].description;
- const site_id = rows[i].madis_id;
- const site_lat = rows[i].lat / 182;
- const site_lon = rows[i].lon / 182;
- const site_elev = rows[i].elev;
- siteOptionsMap[site_name] = [site_id];
-
- const point = [site_lat, site_lon];
- const obj = {
- name: site_name,
- origName: site_name,
- point,
- elevation: site_elev,
- options: {
- title: site_description,
- color: "red",
- size: 5,
- network: "METAR",
- peerOption: site_name,
- id: site_id,
- highLightColor: "blue",
- },
- };
- sitesLocationMap.push(obj);
-
- matsCollections.SiteMap.insert({ siteName: site_name, siteId: site_id });
+ for (let i = 0; i < rows.length; i += 1) {
+ const siteName = rows[i].name === undefined ? "unknown" : rows[i].name;
+ const siteDescription =
+ rows[i].description === undefined ? "unknown" : rows[i].description;
+ const siteId = rows[i].madis_id;
+ const siteLat = rows[i].lat === undefined ? -90 : rows[i].lat / 182;
+ const siteLon = rows[i].lon === undefined ? 0 : rows[i].lon / 182;
+ const siteElev = rows[i].elev === undefined ? 0 : rows[i].elev;
+
+ // There's one station right at the south pole that the map doesn't know how to render at all, so exclude it.
+ // Also exclude stations with missing data
+ if (siteLat < 90 && siteLat > -90) {
+ siteOptionsMap[siteName] = [siteId];
+
+ const point = [siteLat, siteLon];
+ const obj = {
+ name: siteName,
+ origName: siteName,
+ point,
+ elevation: siteElev,
+ options: {
+ title: siteDescription,
+ color: "red",
+ size: 5,
+ network: "METAR",
+ peerOption: siteName,
+ id: siteId,
+ highLightColor: "blue",
+ },
+ };
+ sitesLocationMap.push(obj);
+ matsCollections.SiteMap.insert({ siteName, siteId });
+ }
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
matsCollections.StationMap.remove({});
@@ -530,7 +517,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.variable.findOne({ name: "variable" });
+ const currentParam = matsCollections.variable.findOne({ name: "variable" });
if (!matsDataUtils.areObjectsEqual(currentParam.dates, modelDateRangeMap)) {
// have to reload variable data
matsCollections.variable.update(
@@ -587,7 +574,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["data-source"].findOne({ name: "data-source" });
+ const currentParam = matsCollections["data-source"].findOne({
+ name: "data-source",
+ });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap)) {
// have to reload model data
matsCollections["data-source"].update(
@@ -612,7 +601,7 @@ const doCurveParams = function () {
regionModelOptionsMap[variables[0]][
Object.keys(regionModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -627,10 +616,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.region.findOne({ name: "region" });
+ const currentParam = matsCollections.region.findOne({ name: "region" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, regionModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterRegionValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allRegionValuesMap)
) {
// have to reload region data
matsCollections.region.update(
@@ -638,7 +627,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: regionModelOptionsMap,
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
options:
regionModelOptionsMap[variables[0]][
Object.keys(regionModelOptionsMap[variables[0]])[0]
@@ -715,7 +704,7 @@ const doCurveParams = function () {
thresholdsModelOptionsMap[variables[0]][
Object.keys(thresholdsModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterThresholdValuesMap,
+ valuesMap: allThresholdValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -730,13 +719,13 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.threshold.findOne({ name: "threshold" });
+ const currentParam = matsCollections.threshold.findOne({ name: "threshold" });
if (
!matsDataUtils.areObjectsEqual(
currentParam.optionsMap,
thresholdsModelOptionsMap
) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterThresholdValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allThresholdValuesMap)
) {
// have to reload threshold data
matsCollections.threshold.update(
@@ -744,7 +733,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: thresholdsModelOptionsMap,
- valuesMap: masterThresholdValuesMap,
+ valuesMap: allThresholdValuesMap,
options:
thresholdsModelOptionsMap[variables[0]][
Object.keys(thresholdsModelOptionsMap[variables[0]])[0]
@@ -784,7 +773,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["forecast-length"].findOne({
+ const currentParam = matsCollections["forecast-length"].findOne({
name: "forecast-length",
});
if (
@@ -1053,18 +1042,14 @@ const doCurveParams = function () {
}
// determine date defaults for dates and curveDates
- const defaultDb = matsCollections.variable.findOne(
- { name: "variable" },
+ const defaultDataSource = matsCollections["data-source"].findOne(
+ { name: "data-source" },
{ default: 1 }
).default;
modelDateRangeMap = matsCollections.variable.findOne(
{ name: "variable" },
{ dates: 1 }
).dates;
- const defaultDataSource = matsCollections["data-source"].findOne(
- { name: "data-source" },
- { default: 1 }
- ).default;
minDate = modelDateRangeMap[variables[0]][defaultDataSource].minDate;
maxDate = modelDateRangeMap[variables[0]][defaultDataSource].maxDate;
@@ -1105,7 +1090,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["curve-dates"].findOne({ name: "curve-dates" });
+ const currentParam = matsCollections["curve-dates"].findOne({
+ name: "curve-dates",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.startDate, minDate) ||
!matsDataUtils.areObjectsEqual(currentParam.stopDate, maxDate) ||
@@ -1498,7 +1485,8 @@ const doPlotGraph = function () {
Meteor.startup(function () {
matsCollections.Databases.remove({});
if (matsCollections.Databases.find({}).count() < 0) {
- console.log(
+ // eslint-disable-next-line no-console
+ console.warn(
"main startup: corrupted Databases collection: dropping Databases collection"
);
matsCollections.Databases.drop();
@@ -1515,7 +1503,7 @@ Meteor.startup(function () {
databases = Meteor.settings.private.databases;
}
if (databases !== null && databases !== undefined && Array.isArray(databases)) {
- for (let di = 0; di < databases.length; di++) {
+ for (let di = 0; di < databases.length; di += 1) {
matsCollections.Databases.insert(databases[di]);
}
}
@@ -1542,6 +1530,7 @@ Meteor.startup(function () {
);
if (cbConnection) {
// global cbScorecardSettingsPool
+ // eslint-disable-next-line no-undef
cbScorecardSettingsPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1568,6 +1557,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (metadataSettings) {
+ // eslint-disable-next-line no-undef
metadataPool = mysql.createPool(metadataSettings);
allPools.push({ pool: "metadataPool", role: matsTypes.DatabaseRoles.META_DATA });
}
@@ -1588,6 +1578,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (sumSettings) {
+ // eslint-disable-next-line no-undef
sumPool = mysql.createPool(sumSettings);
allPools.push({ pool: "sumPool", role: matsTypes.DatabaseRoles.SUMS_DATA });
}
@@ -1596,7 +1587,7 @@ Meteor.startup(function () {
const mdr = new matsTypes.MetaDataDBRecord("metadataPool", "mats_common", [
"region_descriptions",
]);
- for (let didx = 0; didx < variables.length; didx++) {
+ for (let didx = 0; didx < variables.length; didx += 1) {
mdr.addRecord("sumPool", variableDBNames[variables[didx]].modelDB, [
"threshold_descriptions",
]);
@@ -1611,7 +1602,7 @@ Meteor.startup(function () {
appType: matsTypes.AppTypes.mats,
});
} catch (error) {
- console.log(error.message);
+ throw new Error(error.message);
}
});
@@ -1619,6 +1610,7 @@ Meteor.startup(function () {
// These are application specific mongo data - like curve params
// The appSpecificResetRoutines object is a special name,
// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way.
+// eslint-disable-next-line no-undef
appSpecificResetRoutines = [
doPlotGraph,
doCurveParams,
diff --git a/apps/ceil-vis15/.eslintrc.json b/apps/ceil-vis15/.eslintrc.json
index e5e813ea94..79d49c5bb6 100644
--- a/apps/ceil-vis15/.eslintrc.json
+++ b/apps/ceil-vis15/.eslintrc.json
@@ -28,23 +28,6 @@
"space-before-function-paren": "off",
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
- "prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
- "no-undef": "warn",
- "no-plusplus": "warn",
- "vars-on-top": "warn",
- "no-var": "warn",
- "block-scoped-var": "warn",
- "no-loop-func": "warn",
- "no-unused-vars": "warn",
- "prefer-destructuring": "warn",
- "no-param-reassign": "warn",
- "camelcase": "warn",
- "no-redeclare": "warn",
- "no-shadow": "warn"
+ "prefer-arrow-callback": "off"
}
}
diff --git a/apps/ceil-vis15/client/main.js b/apps/ceil-vis15/client/main.js
index a87407a1f4..ecd922b6a2 100644
--- a/apps/ceil-vis15/client/main.js
+++ b/apps/ceil-vis15/client/main.js
@@ -2,6 +2,7 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+// eslint-disable-next-line no-unused-vars
import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common";
import "@fortawesome/fontawesome-free";
import "@fortawesome/fontawesome-free/css/all.css";
diff --git a/apps/ceil-vis15/server/dataFunctions/data_contour.js b/apps/ceil-vis15/server/dataFunctions/data_contour.js
index 9ebf0bd5a8..b5524ec99d 100644
--- a/apps/ceil-vis15/server/dataFunctions/data_contour.js
+++ b/apps/ceil-vis15/server/dataFunctions/data_contour.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContour = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,62 +23,53 @@ dataContour = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
- const totalProcessingStart = moment();
+
+ const curves = JSON.parse(JSON.stringify(plotParams.curves));
+ if (curves.length > 1) {
+ throw new Error("INFO: There must only be one added curve.");
+ }
+
+ const axisMap = Object.create(null);
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- const curves = JSON.parse(JSON.stringify(plotParams.curves));
- if (curves.length > 1) {
- throw new Error("INFO: There must only be one added curve.");
- }
- const dataset = [];
- const axisMap = Object.create(null);
- // initialize variables specific to the curve
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" }).optionsMap[
variable
];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- const regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
let thresholdClause = "";
- let truthClause = "";
- if (variable === "15 Minute Visibility") {
- const truthStr = curve.truth;
- const truth = Object.keys(
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
- truthStr
- );
- truthClause = `and m0.truth = '${truth}'`;
- }
- let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") {
const thresholdStr = curve.threshold;
+ if (thresholdStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s threshold is undefined. Please assign it a value.`
+ );
+ }
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -88,18 +80,52 @@ dataContour = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold}`;
}
+
+ let validTimeClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time)%(24*3600)/900)/4 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = Number(curve["forecast-length"]);
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
const forecastHour = Math.floor(forecastLength);
const forecastMinute = (forecastLength - forecastHour) * 60;
forecastLengthClause = `and m0.fcst_len = ${forecastHour} and m0.fcst_min = ${forecastMinute}`;
}
+
+ let truthClause = "";
+ let truth;
+ if (variable === "15 Minute Visibility") {
+ const truthStr = curve.truth;
+ truth = Object.keys(
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
+ truthStr
+ );
+ truthClause = `and m0.truth = '${truth}'`;
+ }
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -110,97 +136,107 @@ dataContour = function (plotParams, plotFunction) {
dateString = "m0.time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
// For contours, this functions as the colorbar label.
const statType = statisticOptionsMap[statisticSelect][0];
- curve.unitKey = statisticOptionsMap[statisticSelect][1];
+ [, curve.unitKey] = statisticOptionsMap[statisticSelect];
let d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{truthClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
-
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{truthClause}}", truthClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{truthClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
+
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{truthClause}}", truthClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
- }
- if (!dataFoundForCurve) {
- // we found no data for any curves so don't bother proceeding
- throw new Error("INFO: No valid data for any curves.");
- }
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
+ // this is NOT an error just a no data condition
+ dataFoundForCurve = false;
+ } else {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ }
- const postQueryStartMoment = moment();
+ if (!dataFoundForCurve) {
+ // we found no data for any curves so don't bother proceeding
+ throw new Error("INFO: No valid data for any curves.");
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
+ }
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
diff --git a/apps/ceil-vis15/server/dataFunctions/data_contour_diff.js b/apps/ceil-vis15/server/dataFunctions/data_contour_diff.js
index cfd0a22887..bc08ac35c4 100644
--- a/apps/ceil-vis15/server/dataFunctions/data_contour_diff.js
+++ b/apps/ceil-vis15/server/dataFunctions/data_contour_diff.js
@@ -14,6 +14,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContourDiff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -24,65 +25,58 @@ dataContourDiff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
let dataNotFoundForAnyCurve = false;
+
+ let curves = JSON.parse(JSON.stringify(plotParams.curves));
+ const curvesLength = curves.length;
+ if (curvesLength !== 2) {
+ throw new Error("INFO: There must be two added curves.");
+ }
+
+ const axisMap = Object.create(null);
const showSignificance = plotParams.significance !== "none";
- const totalProcessingStart = moment();
+
+ let statType;
+ let statisticSelect;
+
+ let statement = "";
+ let error = "";
+ let dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- let curves = JSON.parse(JSON.stringify(plotParams.curves));
- const curvesLength = curves.length;
- if (curvesLength !== 2) {
- throw new Error("INFO: There must be two added curves.");
- }
- let dataset = [];
- const axisMap = Object.create(null);
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
let thresholdClause = "";
- let truthClause = "";
- if (variable === "15 Minute Visibility") {
- var truthStr = curve.truth;
- const truth = Object.keys(
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
- truthStr
- );
- truthClause = `and m0.truth = '${truth}'`;
- }
- let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") {
- var thresholdStr = curve.threshold;
+ const thresholdStr = curve.threshold;
+ if (thresholdStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s threshold is undefined. Please assign it a value.`
+ );
+ }
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -93,18 +87,52 @@ dataContourDiff = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold}`;
}
+
+ let validTimeClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time)%(24*3600)/900)/4 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = Number(curve["forecast-length"]);
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
const forecastHour = Math.floor(forecastLength);
const forecastMinute = (forecastLength - forecastHour) * 60;
forecastLengthClause = `and m0.fcst_len = ${forecastHour} and m0.fcst_min = ${forecastMinute}`;
}
+
+ let truthClause = "";
+ let truth;
+ if (variable === "15 Minute Visibility") {
+ const truthStr = curve.truth;
+ truth = Object.keys(
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
+ truthStr
+ );
+ truthClause = `and m0.truth = '${truth}'`;
+ }
+
+ statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -115,93 +143,100 @@ dataContourDiff = function (plotParams, plotFunction) {
dateString = "m0.time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- var statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
// For contours, this functions as the colorbar label.
- var statType = statisticOptionsMap[statisticSelect][0];
- curves[curveIndex].unitKey = statisticOptionsMap[statisticSelect][1];
+ [statType] = statisticOptionsMap[statisticSelect];
+ [, curve.unitKey] = statisticOptionsMap[statisticSelect];
- var d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{truthClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
+ let d;
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{truthClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{truthClause}}", truthClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{truthClause}}", truthClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
- dataNotFoundForAnyCurve = true;
- }
- const postQueryStartMoment = moment();
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ dataNotFoundForAnyCurve = true;
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
+ }
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
@@ -250,8 +285,9 @@ dataContourDiff = function (plotParams, plotFunction) {
statType === "ctc",
statType === "scalar"
);
- plotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
- curves = plotParams.curves;
+ const newPlotParams = plotParams;
+ newPlotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
+ curves = newPlotParams.curves;
dataset[0].name = matsPlotUtils.getCurveText(
matsTypes.PlotTypes.contourDiff,
curves[0]
@@ -267,7 +303,7 @@ dataContourDiff = function (plotParams, plotFunction) {
const result = matsDataProcessUtils.processDataContour(
dataset,
curveInfoParams,
- plotParams,
+ newPlotParams,
bookkeepingParams
);
plotFunction(result);
diff --git a/apps/ceil-vis15/server/dataFunctions/data_dailymodelcycle.js b/apps/ceil-vis15/server/dataFunctions/data_dailymodelcycle.js
index dd4255e2a2..846a0e074c 100644
--- a/apps/ceil-vis15/server/dataFunctions/data_dailymodelcycle.js
+++ b/apps/ceil-vis15/server/dataFunctions/data_dailymodelcycle.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDailyModelCycle = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,48 +24,48 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
let queryTableClause = "";
- let truthClause = "";
- if (variable === "15 Minute Visibility") {
- var truthStr = curve.truth;
- var truth = Object.keys(
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
- truthStr
- );
- }
- var thresholdStr = curve.threshold;
+
+ let thresholdClause = "";
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -73,7 +74,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
key
] === thresholdStr
);
- let thresholdClause = "";
+
if (curve["utc-cycle-start"].length !== 1) {
throw new Error(
"INFO: Please select exactly one UTC Cycle Init Hour for this plot type."
@@ -82,24 +83,36 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
const utcCycleStart = Number(curve["utc-cycle-start"][0]);
utcCycleStarts[curveIndex] = utcCycleStart;
const utcCycleStartClause = `and floor(((m0.time+450) - (m0.fcst_len*60+m0.fcst_min)*60)%(24*3600)/900)/4 IN(${utcCycleStart})`;
+
const forecastLengthClause = "and m0.fcst_len < 24";
- var dateClause;
- let siteDateClause = "";
- let siteMatchClause = "";
- let sitesClause = "";
- const siteMap = matsCollections.StationMap.findOne(
- { name: "stations" },
- { optionsMap: 1 }
- ).optionsMap;
+
+ let truthClause = "";
+ let truth;
+ if (variable === "15 Minute Visibility") {
+ const truthStr = curve.truth;
+ truth = Object.keys(
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
+ truthStr
+ );
+ }
+ let statisticClause;
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap;
- var statisticClause;
+
+ let dateClause;
+ let siteDateClause = "";
+ let siteMatchClause = "";
+ let sitesClause = "";
+
const regionType = curve["region-type"];
if (regionType === "Predefined region") {
- var regionStr = curve.region;
+ const regionStr = curve.region;
const region = Object.keys(
matsCollections.region.findOne({ name: "region" }).valuesMap
).find(
@@ -135,16 +148,17 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
truthClause = "and o.vis_std < 2.4";
}
}
+
+ const siteMap = matsCollections.StationMap.findOne(
+ { name: "stations" },
+ { optionsMap: 1 }
+ ).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- var thisSite;
- var thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.madis_id in('${querySites.join("','")}')`;
} else {
throw new Error(
@@ -155,11 +169,12 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
siteDateClause = `and o.time >= ${fromSecs} - 300 and o.time <= ${toSecs} + 300`;
siteMatchClause = "and m0.madis_id = o.madis_id and m0.time = o.time ";
}
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -167,57 +182,57 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select ceil(900*floor((m0.time+450)/900)) as avtime, " +
- "count(distinct ceil(900*floor((m0.time+450)/900))) as N_times, " +
- "min(ceil(900*floor((m0.time+450)/900))) as min_secs, " +
- "max(ceil(900*floor((m0.time+450)/900))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{utcCycleStartClause}} " +
- "{{thresholdClause}} " +
- "{{forecastLengthClause}} " +
- "{{truthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{truthClause}}", truthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- if (variable.includes("Visibility")) {
- statement = statement.replace(/o\.time/g, "o.valid_time");
- }
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select ceil(900*floor((m0.time+450)/900)) as avtime, " +
+ "count(distinct ceil(900*floor((m0.time+450)/900))) as N_times, " +
+ "min(ceil(900*floor((m0.time+450)/900))) as min_secs, " +
+ "max(ceil(900*floor((m0.time+450)/900))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{utcCycleStartClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{truthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{truthClause}}", truthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ if (variable.includes("Visibility")) {
+ statement = statement.replace(/o\.time/g, "o.valid_time");
+ }
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -233,6 +248,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -247,7 +263,6 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -272,6 +287,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ceil-vis15/server/dataFunctions/data_dieoff.js b/apps/ceil-vis15/server/dataFunctions/data_dieoff.js
index 62f1842e35..9365e12363 100644
--- a/apps/ceil-vis15/server/dataFunctions/data_dieoff.js
+++ b/apps/ceil-vis15/server/dataFunctions/data_dieoff.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDieoff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,45 +24,44 @@ dataDieoff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
let queryTableClause = "";
- let truthClause = "";
- if (variable === "15 Minute Visibility") {
- var truthStr = curve.truth;
- var truth = Object.keys(
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
- truthStr
- );
- }
- var thresholdStr = curve.threshold;
+
+ let thresholdClause = "";
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -70,38 +70,52 @@ dataDieoff = function (plotParams, plotFunction) {
key
] === thresholdStr
);
- let thresholdClause = "";
- var validTimes;
+
let validTimeClause = "";
- var utcCycleStart;
+ let validTimes;
+
let utcCycleStartClause = "";
+ let utcCycleStart;
+
const forecastLengthStr = curve["dieoff-type"];
const forecastLengthOptionsMap = matsCollections["dieoff-type"].findOne(
{ name: "dieoff-type" },
{ optionsMap: 1 }
).optionsMap;
const forecastLength = forecastLengthOptionsMap[forecastLengthStr][0];
- const forecastLengthClause = "";
+
+ let truthClause = "";
+ let truth;
+ if (variable === "15 Minute Visibility") {
+ const truthStr = curve.truth;
+ truth = Object.keys(
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
+ truthStr
+ );
+ }
+
+ let statisticClause;
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
- var dateClause;
+
+ let dateClause;
let siteDateClause = "";
let siteMatchClause = "";
let sitesClause = "";
- const siteMap = matsCollections.StationMap.findOne(
- { name: "stations" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- var statisticClause;
+
const regionType = curve["region-type"];
if (regionType === "Predefined region") {
- var regionStr = curve.region;
+ const regionStr = curve.region;
const region = Object.keys(
matsCollections.region.findOne({ name: "region" }).valuesMap
).find(
@@ -137,16 +151,17 @@ dataDieoff = function (plotParams, plotFunction) {
truthClause = "and o.vis_std < 2.4";
}
}
+
+ const siteMap = matsCollections.StationMap.findOne(
+ { name: "stations" },
+ { optionsMap: 1 }
+ ).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- var thisSite;
- var thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.madis_id in('${querySites.join("','")}')`;
} else {
throw new Error(
@@ -157,6 +172,7 @@ dataDieoff = function (plotParams, plotFunction) {
siteDateClause = `and o.time >= ${fromSecs} - 300 and o.time <= ${toSecs} + 300`;
siteMatchClause = "and m0.madis_id = o.madis_id and m0.time = o.time ";
}
+
if (forecastLength === matsTypes.ForecastTypes.dieoff) {
validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
@@ -176,11 +192,12 @@ dataDieoff = function (plotParams, plotFunction) {
} else {
dateClause = `and m0.time-(m0.fcst_len*60+m0.fcst_min)*60 = ${fromSecs}`;
}
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -188,59 +205,57 @@ dataDieoff = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.fcst_len + (m0.fcst_min/60) as fcst_lead, " +
- "count(distinct ceil(900*floor((m0.time+450)/900))) as N_times, " +
- "min(ceil(900*floor((m0.time+450)/900))) as min_secs, " +
- "max(ceil(900*floor((m0.time+450)/900))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{utcCycleStartClause}} " +
- "{{truthClause}} " +
- "group by fcst_lead " +
- "order by fcst_lead" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{truthClause}}", truthClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- if (variable.includes("Visibility")) {
- statement = statement.replace(/o\.time/g, "o.valid_time");
- }
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.fcst_len + (m0.fcst_min/60) as fcst_lead, " +
+ "count(distinct ceil(900*floor((m0.time+450)/900))) as N_times, " +
+ "min(ceil(900*floor((m0.time+450)/900))) as min_secs, " +
+ "max(ceil(900*floor((m0.time+450)/900))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{utcCycleStartClause}} " +
+ "{{truthClause}} " +
+ "group by fcst_lead " +
+ "order by fcst_lead" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{truthClause}}", truthClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ if (variable.includes("Visibility")) {
+ statement = statement.replace(/o\.time/g, "o.valid_time");
+ }
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -256,6 +271,7 @@ dataDieoff = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -270,7 +286,6 @@ dataDieoff = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -295,6 +310,7 @@ dataDieoff = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ceil-vis15/server/dataFunctions/data_histogram.js b/apps/ceil-vis15/server/dataFunctions/data_histogram.js
index 0eba5ab67f..db7bb094da 100644
--- a/apps/ceil-vis15/server/dataFunctions/data_histogram.js
+++ b/apps/ceil-vis15/server/dataFunctions/data_histogram.js
@@ -11,6 +11,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataHistogram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -21,44 +22,45 @@ dataHistogram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
- const alreadyMatched = false;
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
const dataFoundForCurve = [];
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+ const alreadyMatched = false;
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
+
+ const axisMap = Object.create(null);
+ let statType;
+ let varUnits;
+
+ let statement = "";
+ let error = "";
const dataset = [];
const allReturnedSubStats = [];
const allReturnedSubSecs = [];
- const axisMap = Object.create(null);
// process user bin customizations
const binParams = matsDataUtils.setHistogramParameters(plotParams);
const { yAxisFormat } = binParams;
const { binNum } = binParams;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
dataFoundForCurve[curveIndex] = true;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -68,10 +70,23 @@ dataHistogram = function (plotParams, plotFunction) {
] === thresholdStr
);
const thresholdClause = `and m0.trsh = ${threshold}`;
+
+ let validTimeClause = "";
+ const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
+ validTimeClause = `and floor((m0.time)%(24*3600)/900)/4 IN(${validTimes})`;
+ }
+
+ const forecastLength = Number(curve["forecast-length"]);
+ const forecastHour = Math.floor(forecastLength);
+ const forecastMinute = (forecastLength - forecastHour) * 60;
+ const forecastLengthClause = `and m0.fcst_len = ${forecastLength} and m0.fcst_min = ${forecastMinute}`;
+
let truthClause = "";
+ let truth;
if (variable === "15 Minute Visibility") {
- var truthStr = curve.truth;
- const truth = Object.keys(
+ const truthStr = curve.truth;
+ truth = Object.keys(
matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
).find(
(key) =>
@@ -80,19 +95,7 @@ dataHistogram = function (plotParams, plotFunction) {
);
truthClause = `and m0.truth = '${truth}'`;
}
- let validTimeClause = "";
- const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
- validTimeClause = `and floor((m0.time)%(24*3600)/900)/4 IN(${validTimes})`;
- }
- const forecastLength = Number(curve["forecast-length"]);
- const forecastHour = Math.floor(forecastLength);
- const forecastMinute = (forecastLength - forecastHour) * 60;
- const forecastLengthClause = `and m0.fcst_len = ${forecastLength} and m0.fcst_min = ${forecastMinute}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -100,12 +103,27 @@ dataHistogram = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
- var varUnits = statisticOptionsMap[statisticSelect][1];
+ [statType] = statisticOptionsMap[statisticSelect];
+ [, varUnits] = statisticOptionsMap[statisticSelect];
let axisKey = yAxisFormat;
if (yAxisFormat === "Relative frequency") {
axisKey += " (x100)";
@@ -113,48 +131,48 @@ dataHistogram = function (plotParams, plotFunction) {
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
curves[curveIndex].binNum = binNum; // stash the binNum to use it later for bar chart options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.time as avtime, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{truthClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{truthClause}}", truthClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.time as avtime, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{truthClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{truthClause}}", truthClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -172,6 +190,7 @@ dataHistogram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/ceil-vis15/server/dataFunctions/data_map.js b/apps/ceil-vis15/server/dataFunctions/data_map.js
index e0f911c61b..6e1399dc8b 100644
--- a/apps/ceil-vis15/server/dataFunctions/data_map.js
+++ b/apps/ceil-vis15/server/dataFunctions/data_map.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataMap = function (plotParams, plotFunction) {
const appParams = {
plotType: matsTypes.PlotTypes.map,
@@ -21,20 +22,28 @@ dataMap = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
- const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
+
const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+ const dataRequests = {}; // used to store data queries
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
if (curves.length > 1) {
throw new Error("INFO: There must only be one added curve.");
}
+
+ let statement = "";
+ let error = "";
const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" }).optionsMap[
variable
@@ -44,22 +53,7 @@ dataMap = function (plotParams, plotFunction) {
const obsTable =
modelTable.includes("ret_") || modelTable.includes("Ret_") ? "obs_retro" : "obs";
const queryTableClause = `from ${databaseRef.modelDB}.${obsTable} as o, ${databaseRef.modelDB}.${modelTable} as m0 `;
- let sitesClause = "";
- const siteMap = matsCollections.StationMap.findOne(
- { name: "stations" },
- { optionsMap: 1 }
- ).optionsMap;
- let truthClause = "";
- if (variable === "15 Minute Visibility") {
- const truthStr = curve.truth;
- var truth = Object.keys(
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
- truthStr
- );
- }
+
const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
@@ -69,6 +63,7 @@ dataMap = function (plotParams, plotFunction) {
key
] === thresholdStr
);
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
@@ -78,6 +73,20 @@ dataMap = function (plotParams, plotFunction) {
const forecastHour = Math.floor(forecastLength);
const forecastMinute = (forecastLength - forecastHour) * 60;
const forecastLengthClause = `and m0.fcst_len = ${forecastLength} and m0.fcst_min = ${forecastMinute}`;
+
+ let truthClause = "";
+ let truth;
+ if (variable === "15 Minute Visibility") {
+ const truthStr = curve.truth;
+ truth = Object.keys(
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
+ truthStr
+ );
+ }
+
const { statistic } = curve;
let statisticClause =
"sum(if((m0.ceil < {{threshold}}) and (o.ceil < {{threshold}}),1,0)) as hit, sum(if((m0.ceil < {{threshold}}) and NOT (o.ceil < {{threshold}}),1,0)) as fa, " +
@@ -95,16 +104,19 @@ dataMap = function (plotParams, plotFunction) {
truthClause = "and o.vis_std < 2.4";
}
}
+
+ let sitesClause = "";
+
+ const siteMap = matsCollections.StationMap.findOne(
+ { name: "stations" },
+ { optionsMap: 1 }
+ ).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- let thisSite;
- let thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.madis_id in('${querySites.join("','")}')`;
} else {
throw new Error(
@@ -115,90 +127,110 @@ dataMap = function (plotParams, plotFunction) {
const siteDateClause = `and o.time >= ${fromSecs} - 300 and o.time <= ${toSecs} + 300`;
const siteMatchClause = "and m0.madis_id = o.madis_id and m0.time = o.time";
- let statement =
- "select m0.madis_id as sta_id, " +
- "count(distinct ceil(900*floor((m0.time+450)/900))) as N_times, " +
- "min(ceil(900*floor((m0.time+450)/900))) as min_secs, " +
- "max(ceil(900*floor((m0.time+450)/900))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{truthClause}} " +
- "group by sta_id " +
- "order by N0" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{truthClause}}", truthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- if (variable.includes("Visibility")) {
- statement = statement.replace(/o\.time/g, "o.valid_time");
- }
- dataRequests[label] = statement;
-
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBMapCTC(
- sumPool,
- statement,
- modelTable,
- statistic,
- siteMap,
- appParams
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.length,
- };
- // get the data back from the query
- var d = queryResult.data;
- var dPurple = queryResult.dataPurple;
- var dPurpleBlue = queryResult.dataPurpleBlue;
- var dBlue = queryResult.dataBlue;
- var dBlueGreen = queryResult.dataBlueGreen;
- var dGreen = queryResult.dataGreen;
- var dGreenYellow = queryResult.dataGreenYellow;
- var dYellow = queryResult.dataYellow;
- var dOrange = queryResult.dataOrange;
- var dOrangeRed = queryResult.dataOrangeRed;
- var dRed = queryResult.dataRed;
- var { valueLimits } = queryResult;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ let d;
+ let dPurple;
+ let dPurpleBlue;
+ let dBlue;
+ let dBlueGreen;
+ let dGreen;
+ let dGreenYellow;
+ let dYellow;
+ let dOrange;
+ let dOrangeRed;
+ let dRed;
+ let valueLimits;
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "select m0.madis_id as sta_id, " +
+ "count(distinct ceil(900*floor((m0.time+450)/900))) as N_times, " +
+ "min(ceil(900*floor((m0.time+450)/900))) as min_secs, " +
+ "max(ceil(900*floor((m0.time+450)/900))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{truthClause}} " +
+ "group by sta_id " +
+ "order by N0" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{truthClause}}", truthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ if (variable.includes("Visibility")) {
+ statement = statement.replace(/o\.time/g, "o.valid_time");
+ }
+ dataRequests[label] = statement;
+
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBMapCTC(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ modelTable,
+ statistic,
+ siteMap,
+ appParams
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = "Station plot -- no one query.";
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ dPurple = queryResult.dataPurple;
+ dPurpleBlue = queryResult.dataPurpleBlue;
+ dBlue = queryResult.dataBlue;
+ dBlueGreen = queryResult.dataBlueGreen;
+ dGreen = queryResult.dataGreen;
+ dGreenYellow = queryResult.dataGreenYellow;
+ dYellow = queryResult.dataYellow;
+ dOrange = queryResult.dataOrange;
+ dOrangeRed = queryResult.dataOrangeRed;
+ dRed = queryResult.dataRed;
+ valueLimits = queryResult.valueLimits;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
+
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ }
+ } else {
+ // this is a difference curve -- not supported for maps
+ throw new Error(
+ "INFO: Difference curves are not supported for maps, as there is only one curve."
+ );
}
+ const postQueryStartMoment = moment();
let cOptions = matsDataCurveOpsUtils.generateCTCMapCurveOptions(curve, d, appParams); // generate map with site data
dataset.push(cOptions);
@@ -326,6 +358,15 @@ dataMap = function (plotParams, plotFunction) {
); // generate red text layer
dataset.push(cOptions);
+ const postQueryFinishMoment = moment();
+ dataRequests[`post data retrieval (query) process time - ${label}`] = {
+ begin: postQueryStartMoment.format(),
+ finish: postQueryFinishMoment.format(),
+ duration: `${moment
+ .duration(postQueryFinishMoment.diff(postQueryStartMoment))
+ .asSeconds()} seconds`,
+ };
+
const resultOptions = matsDataPlotOpsUtils.generateMapPlotOptions(true);
const totalProcessingFinish = moment();
dataRequests["total retrieval and processing time for curve set"] = {
diff --git a/apps/ceil-vis15/server/dataFunctions/data_perfDiagram.js b/apps/ceil-vis15/server/dataFunctions/data_perfDiagram.js
index ce583912cd..e04a267013 100644
--- a/apps/ceil-vis15/server/dataFunctions/data_perfDiagram.js
+++ b/apps/ceil-vis15/server/dataFunctions/data_perfDiagram.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataPerformanceDiagram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,64 +23,47 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statType;
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const binParam = curve["bin-parameter"];
const binClause = matsCollections["bin-parameter"].findOne({
name: "bin-parameter",
}).optionsMap[binParam];
- var { variable } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
let thresholdClause = "";
- let truthClause = "";
- if (variable === "15 Minute Visibility") {
- var truthStr = curve.truth;
- const truth = Object.keys(
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
- truthStr
- );
- truthClause = `and m0.truth = '${truth}'`;
- }
- let validTimeClause = "";
- let forecastLengthClause = "";
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let dateString = "";
- let dateClause = "";
if (binParam !== "Threshold") {
- var thresholdStr = curve.threshold;
+ const thresholdStr = curve.threshold;
if (thresholdStr === undefined) {
throw new Error(
`INFO: ${label}'s threshold is undefined. Please assign it a value.`
@@ -95,12 +79,16 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold}`;
}
+
+ let validTimeClause = "";
if (binParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time)%(24*3600)/900)/4 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (binParam !== "Fcst lead time") {
const forecastLength = Number(curve["forecast-length"]);
const forecastHour = Math.floor(forecastLength);
@@ -112,64 +100,95 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
}
forecastLengthClause = `and m0.fcst_len = ${forecastLength} and m0.fcst_min = ${forecastMinute}`;
}
+
+ let truthClause = "";
+ let truth;
+ if (variable === "15 Minute Visibility") {
+ const truthStr = curve.truth;
+ truth = Object.keys(
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
+ truthStr
+ );
+ truthClause = `and m0.truth = '${truth}'`;
+ }
+
+ const statisticSelect = "PerformanceDiagram";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ let dateString = "";
+ let dateClause = "";
if (binParam === "Init Date") {
dateString = "m0.time-(m0.fcst_len*3600+m0.fcst_min*60)";
} else {
dateString = "m0.time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const statisticSelect = "PerformanceDiagram";
- var statType = "ctc";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// variable + statistic (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ statType = "ctc";
curves[curveIndex].axisKey = statisticSelect; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{binClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "((sum(m0.yy)+0.00)/sum(m0.yy+m0.ny)) as pod, ((sum(m0.yn)+0.00)/sum(m0.yn+m0.yy)) as far, " +
- "sum(m0.yy+m0.ny) as oy_all, sum(m0.yn+m0.nn) as on_all, group_concat(m0.time, ';', m0.yy, ';', " +
- "m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0 " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{truthClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by binVal " +
- "order by binVal" +
- ";";
-
- statement = statement.replace("{{binClause}}", binClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{truthClause}}", truthClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "{{binClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "((sum(m0.yy)+0.00)/sum(m0.yy+m0.ny)) as pod, ((sum(m0.yn)+0.00)/sum(m0.yn+m0.yy)) as far, " +
+ "sum(m0.yy+m0.ny) as oy_all, sum(m0.yn+m0.nn) as on_all, group_concat(m0.time, ';', m0.yy, ';', " +
+ "m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0 " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{truthClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by binVal " +
+ "order by binVal" +
+ ";";
+
+ statement = statement.replace("{{binClause}}", binClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{truthClause}}", truthClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBPerformanceDiagram(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -185,6 +204,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -199,7 +219,6 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -207,7 +226,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
ymax = ymax > d.ymax ? ymax : d.ymax;
}
} else {
- // this is a difference curve -- not supported for ROC plots
+ // this is a difference curve -- not supported for performance diagrams
throw new Error(
"INFO: Difference curves are not supported for performance diagrams, as they do not feature consistent x or y values across all curves."
);
@@ -215,6 +234,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ceil-vis15/server/dataFunctions/data_series.js b/apps/ceil-vis15/server/dataFunctions/data_series.js
index 6373583fbd..a9b57bba58 100644
--- a/apps/ceil-vis15/server/dataFunctions/data_series.js
+++ b/apps/ceil-vis15/server/dataFunctions/data_series.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSeries = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,48 +24,48 @@ dataSeries = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
let queryTableClause = "";
- let truthClause = "";
- if (variable === "15 Minute Visibility") {
- var truthStr = curve.truth;
- var truth = Object.keys(
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
- truthStr
- );
- }
- var thresholdStr = curve.threshold;
+
+ let thresholdClause = "";
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -73,33 +74,53 @@ dataSeries = function (plotParams, plotFunction) {
key
] === thresholdStr
);
- let thresholdClause = "";
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time+450)%(24*3600)/900)/4 IN(${validTimes})`;
}
+
let forecastLength = Number(curve["forecast-length"]);
const forecastHour = Math.floor(forecastLength);
const forecastMinute = (forecastLength - forecastHour) * 60;
const forecastLengthClause = `and m0.fcst_len = ${forecastLength} and m0.fcst_min = ${forecastMinute}`;
- var dateClause;
- let siteDateClause = "";
- let siteMatchClause = "";
- let sitesClause = "";
- const siteMap = matsCollections.StationMap.findOne(
- { name: "stations" },
- { optionsMap: 1 }
- ).optionsMap;
+
+ let truthClause = "";
+ let truth;
+ if (variable === "15 Minute Visibility") {
+ const truthStr = curve.truth;
+ truth = Object.keys(
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
+ truthStr
+ );
+ }
+
+ let statisticClause;
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap;
- var statisticClause;
+
+ const averageStr = curve.average;
+ const averageOptionsMap = matsCollections.average.findOne(
+ { name: "average" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const average = averageOptionsMap[averageStr][0];
+
+ let dateClause;
+ let siteDateClause = "";
+ let siteMatchClause = "";
+ let sitesClause = "";
+
const regionType = curve["region-type"];
if (regionType === "Predefined region") {
- var regionStr = curve.region;
+ const regionStr = curve.region;
const region = Object.keys(
matsCollections.region.findOne({ name: "region" }).valuesMap
).find(
@@ -135,16 +156,17 @@ dataSeries = function (plotParams, plotFunction) {
truthClause = "and o.vis_std < 2.4";
}
}
+
+ const siteMap = matsCollections.StationMap.findOne(
+ { name: "stations" },
+ { optionsMap: 1 }
+ ).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- var thisSite;
- var thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.madis_id in('${querySites.join("','")}')`;
} else {
throw new Error(
@@ -155,17 +177,12 @@ dataSeries = function (plotParams, plotFunction) {
siteDateClause = `and o.time >= ${fromSecs} - 300 and o.time <= ${toSecs} + 300`;
siteMatchClause = "and m0.madis_id = o.madis_id and m0.time = o.time ";
}
- const averageStr = curve.average;
- const averageOptionsMap = matsCollections.average.findOne(
- { name: "average" },
- { optionsMap: 1 }
- ).optionsMap;
- const average = averageOptionsMap[averageStr][0];
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -173,58 +190,56 @@ dataSeries = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select {{average}} as avtime, " +
- "count(distinct ceil(900*floor((m0.time+450)/900))) as N_times, " +
- "min(ceil(900*floor((m0.time+450)/900))) as min_secs, " +
- "max(ceil(900*floor((m0.time+450)/900))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{truthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "select {{average}} as avtime, " +
+ "count(distinct ceil(900*floor((m0.time+450)/900))) as N_times, " +
+ "min(ceil(900*floor((m0.time+450)/900))) as min_secs, " +
+ "max(ceil(900*floor((m0.time+450)/900))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{truthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
- statement = statement.replace("{{average}}", average);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{truthClause}}", truthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- if (variable.includes("Visibility")) {
- statement = statement.replace(/o\.time/g, "o.valid_time");
- }
- dataRequests[label] = statement;
+ statement = statement.replace("{{average}}", average);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{truthClause}}", truthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ if (variable.includes("Visibility")) {
+ statement = statement.replace(/o\.time/g, "o.valid_time");
+ }
+ dataRequests[label] = statement;
- // math is done on forecastLength later on -- set all analyses to 0
- if (forecastLength === "-99") {
- forecastLength = "0";
- }
+ // math is done on forecastLength later on -- set all analyses to 0
+ if (forecastLength === "-99") {
+ forecastLength = "0";
+ }
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBTimeSeries(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
model,
forecastLength,
@@ -236,7 +251,9 @@ dataSeries = function (plotParams, plotFunction) {
appParams,
false
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -252,6 +269,7 @@ dataSeries = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -266,7 +284,6 @@ dataSeries = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -291,6 +308,7 @@ dataSeries = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ceil-vis15/server/dataFunctions/data_threshold.js b/apps/ceil-vis15/server/dataFunctions/data_threshold.js
index 9e4a14c5bb..57e3aa6610 100644
--- a/apps/ceil-vis15/server/dataFunctions/data_threshold.js
+++ b/apps/ceil-vis15/server/dataFunctions/data_threshold.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataThreshold = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,44 +24,57 @@ dataThreshold = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
+ let validTimeClause = "";
+ const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
+ validTimeClause = `and floor((m0.time)%(24*3600)/900)/4 IN(${validTimes})`;
+ }
+
+ const forecastLength = Number(curve["forecast-length"]);
+ const forecastHour = Math.floor(forecastLength);
+ const forecastMinute = (forecastLength - forecastHour) * 60;
+ const forecastLengthClause = `and m0.fcst_len = ${forecastLength} and m0.fcst_min = ${forecastMinute}`;
+
let truthClause = "";
+ let truth;
if (variable === "15 Minute Visibility") {
- var truthStr = curve.truth;
- const truth = Object.keys(
+ const truthStr = curve.truth;
+ truth = Object.keys(
matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
).find(
(key) =>
@@ -69,19 +83,7 @@ dataThreshold = function (plotParams, plotFunction) {
);
truthClause = `and m0.truth = '${truth}'`;
}
- let validTimeClause = "";
- const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
- validTimeClause = `and floor((m0.time)%(24*3600)/900)/4 IN(${validTimes})`;
- }
- const forecastLength = Number(curve["forecast-length"]);
- const forecastHour = Math.floor(forecastLength);
- const forecastMinute = (forecastLength - forecastHour) * 60;
- const forecastLengthClause = `and m0.fcst_len = ${forecastLength} and m0.fcst_min = ${forecastMinute}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -89,11 +91,26 @@ dataThreshold = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef.sumsDB}.${model}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -101,46 +118,46 @@ dataThreshold = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.trsh/100 as thresh, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{truthClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by thresh " +
- "order by thresh" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{truthClause}}", truthClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.trsh/100 as thresh, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{truthClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by thresh " +
+ "order by thresh" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{truthClause}}", truthClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -156,6 +173,7 @@ dataThreshold = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -170,7 +188,6 @@ dataThreshold = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -195,6 +212,7 @@ dataThreshold = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ceil-vis15/server/dataFunctions/data_validtime.js b/apps/ceil-vis15/server/dataFunctions/data_validtime.js
index 0c8fe6f098..05ae590be1 100644
--- a/apps/ceil-vis15/server/dataFunctions/data_validtime.js
+++ b/apps/ceil-vis15/server/dataFunctions/data_validtime.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataValidTime = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,45 +24,44 @@ dataValidTime = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
let queryTableClause = "";
- let truthClause = "";
- if (variable === "15 Minute Visibility") {
- var truthStr = curve.truth;
- var truth = Object.keys(
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
- truthStr
- );
- }
- var thresholdStr = curve.threshold;
+
+ let thresholdClause = "";
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -70,31 +70,44 @@ dataValidTime = function (plotParams, plotFunction) {
key
] === thresholdStr
);
- let thresholdClause = "";
+
const forecastLength = Number(curve["forecast-length"]);
const forecastHour = Math.floor(forecastLength);
const forecastMinute = (forecastLength - forecastHour) * 60;
const forecastLengthClause = `and m0.fcst_len = ${forecastLength} and m0.fcst_min = ${forecastMinute}`;
+
+ let truthClause = "";
+ let truth;
+ if (variable === "15 Minute Visibility") {
+ const truthStr = curve.truth;
+ truth = Object.keys(
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[variable][key] ===
+ truthStr
+ );
+ }
+
+ let statisticClause;
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
- var dateClause;
+
+ let dateClause;
let siteDateClause = "";
let siteMatchClause = "";
let sitesClause = "";
- const siteMap = matsCollections.StationMap.findOne(
- { name: "stations" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- var statisticClause;
+
const regionType = curve["region-type"];
if (regionType === "Predefined region") {
- var regionStr = curve.region;
+ const regionStr = curve.region;
const region = Object.keys(
matsCollections.region.findOne({ name: "region" }).valuesMap
).find(
@@ -130,16 +143,17 @@ dataValidTime = function (plotParams, plotFunction) {
truthClause = "and o.vis_std < 2.4";
}
}
+
+ const siteMap = matsCollections.StationMap.findOne(
+ { name: "stations" },
+ { optionsMap: 1 }
+ ).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- var thisSite;
- var thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.madis_id in('${querySites.join("','")}')`;
} else {
throw new Error(
@@ -150,11 +164,12 @@ dataValidTime = function (plotParams, plotFunction) {
siteDateClause = `and o.time >= ${fromSecs} - 300 and o.time <= ${toSecs} + 300`;
siteMatchClause = "and m0.madis_id = o.madis_id and m0.time = o.time ";
}
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -162,55 +177,55 @@ dataValidTime = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select floor((m0.time+450)%(24*3600)/900)/4 as hr_of_day, " +
- "count(distinct ceil(900*floor((m0.time+450)/900))) as N_times, " +
- "min(ceil(900*floor((m0.time+450)/900))) as min_secs, " +
- "max(ceil(900*floor((m0.time+450)/900))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{thresholdClause}} " +
- "{{forecastLengthClause}} " +
- "{{truthClause}} " +
- "group by hr_of_day " +
- "order by hr_of_day" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{truthClause}}", truthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- if (variable.includes("Visibility")) {
- statement = statement.replace(/o\.time/g, "o.valid_time");
- }
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select floor((m0.time+450)%(24*3600)/900)/4 as hr_of_day, " +
+ "count(distinct ceil(900*floor((m0.time+450)/900))) as N_times, " +
+ "min(ceil(900*floor((m0.time+450)/900))) as min_secs, " +
+ "max(ceil(900*floor((m0.time+450)/900))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{truthClause}} " +
+ "group by hr_of_day " +
+ "order by hr_of_day" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{truthClause}}", truthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ if (variable.includes("Visibility")) {
+ statement = statement.replace(/o\.time/g, "o.valid_time");
+ }
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -226,6 +241,7 @@ dataValidTime = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -240,7 +256,6 @@ dataValidTime = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -265,6 +280,7 @@ dataValidTime = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ceil-vis15/server/main.js b/apps/ceil-vis15/server/main.js
index 213cf6484f..8244262664 100644
--- a/apps/ceil-vis15/server/main.js
+++ b/apps/ceil-vis15/server/main.js
@@ -4,7 +4,9 @@
import { Meteor } from "meteor/meteor";
import { mysql } from "meteor/pcel:mysql";
+import { moment } from "meteor/momentjs:moment";
import {
+ matsMethods,
matsTypes,
matsCollections,
matsDataUtils,
@@ -329,7 +331,7 @@ const doCurveParams = function () {
const params = matsCollections.CurveParamsInfo.find({
curve_params: { $exists: true },
}).fetch()[0].curve_params;
- for (let cp = 0; cp < params.length; cp++) {
+ for (let cp = 0; cp < params.length; cp += 1) {
matsCollections[params[cp]].remove({});
}
}
@@ -342,103 +344,88 @@ const doCurveParams = function () {
const forecastLengthOptionsMap = {};
const thresholdsModelOptionsMap = {};
const truthsModelOptionsMap = {};
- const masterRegionValuesMap = {};
- const masterThresholdValuesMap = {};
- const masterTruthValuesMap = {};
+ const allRegionValuesMap = {};
+ const allThresholdValuesMap = {};
+ const allTruthValuesMap = {};
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- metadataPool,
+ metadataPool, // eslint-disable-line no-undef
"select short_name,description from region_descriptions;"
);
- let masterRegDescription;
- let masterShortName;
- for (var j = 0; j < rows.length; j++) {
- masterRegDescription = rows[j].description.trim();
- masterShortName = rows[j].short_name.trim();
- masterRegionValuesMap[masterShortName] = masterRegDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allRegionValuesMap[rows[j].short_name.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
- let rows;
- let didx;
-
try {
- for (didx = 0; didx < variables.length; didx++) {
- masterThresholdValuesMap[variables[didx]] = {};
- rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ for (let didx = 0; didx < variables.length; didx += 1) {
+ allThresholdValuesMap[variables[didx]] = {};
+ const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
+ sumPool, // eslint-disable-line no-undef
`select trsh,description from ${
variableDBNames[variables[didx]].modelDB
}.threshold_descriptions;`
);
- var masterDescription;
- var masterTrsh;
- for (var j = 0; j < rows.length; j++) {
- masterDescription = rows[j].description.trim();
- masterTrsh = rows[j].trsh.trim();
- masterThresholdValuesMap[variables[didx]][masterTrsh] = masterDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allThresholdValuesMap[variables[didx]][rows[j].trsh.trim()] =
+ rows[j].description.trim();
}
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
- for (didx = 0; didx < variables.length; didx++) {
- masterTruthValuesMap[variables[didx]] = {};
+ for (let didx = 0; didx < variables.length; didx += 1) {
+ allTruthValuesMap[variables[didx]] = {};
if (variables[didx] === "15 Minute Visibility") {
- rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
+ sumPool, // eslint-disable-line no-undef
`select truth,description from ${
variableDBNames[variables[didx]].modelDB
}.truth_descriptions;`
);
- var masterDescription;
- var masterTruth;
- for (var j = 0; j < rows.length; j++) {
- masterDescription = rows[j].description.trim();
- masterTruth = rows[j].truth.trim();
- masterTruthValuesMap[variables[didx]][masterTruth] = masterDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allTruthValuesMap[variables[didx]][rows[j].truth.trim()] =
+ rows[j].description.trim();
}
} else {
- masterTruthValuesMap[variables[didx]].default = "Default truth data source";
+ allTruthValuesMap[variables[didx]].default = "Default truth data source";
}
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
- for (didx = 0; didx < variables.length; didx++) {
- modelOptionsMap[variables[didx]] = {};
- modelDateRangeMap[variables[didx]] = {};
- forecastLengthOptionsMap[variables[didx]] = {};
- thresholdsModelOptionsMap[variables[didx]] = {};
- truthsModelOptionsMap[variables[didx]] = {};
- regionModelOptionsMap[variables[didx]] = {};
-
- if (variables[didx] === "15 Minute Visibility") {
+ for (let didx = 0; didx < variables.length; didx += 1) {
+ const variable = variables[didx];
+ modelOptionsMap[variable] = {};
+ modelDateRangeMap[variable] = {};
+ forecastLengthOptionsMap[variable] = {};
+ thresholdsModelOptionsMap[variable] = {};
+ truthsModelOptionsMap[variable] = {};
+ regionModelOptionsMap[variable] = {};
+
+ let rows;
+ if (variable === "15 Minute Visibility") {
rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
- `select model,regions,display_text,fcst_lens,trsh,truth,mindate,maxdate from ${
- variableDBNames[variables[didx]].sumsDB
- }.regions_per_model_mats_all_categories order by display_category, display_order;`
+ sumPool, // eslint-disable-line no-undef
+ `select model,regions,display_text,fcst_lens,trsh,truth,mindate,maxdate from ${variableDBNames[variable].sumsDB}.regions_per_model_mats_all_categories order by display_category, display_order;`
);
} else {
rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
- `select model,regions,display_text,fcst_lens,trsh,mindate,maxdate from ${
- variableDBNames[variables[didx]].sumsDB
- }.regions_per_model_mats_all_categories order by display_category, display_order;`
+ sumPool, // eslint-disable-line no-undef
+ `select model,regions,display_text,fcst_lens,trsh,mindate,maxdate from ${variableDBNames[variable].sumsDB}.regions_per_model_mats_all_categories order by display_category, display_order;`
);
}
- for (var i = 0; i < rows.length; i++) {
- const model_value = rows[i].model.trim();
+ for (let i = 0; i < rows.length; i += 1) {
+ const modelValue = rows[i].model.trim();
const model = rows[i].display_text.trim();
- modelOptionsMap[variables[didx]][model] = [model_value];
+ modelOptionsMap[variable][model] = [modelValue];
const rowMinDate = moment
.utc(rows[i].mindate * 1000)
@@ -446,104 +433,96 @@ const doCurveParams = function () {
const rowMaxDate = moment
.utc(rows[i].maxdate * 1000)
.format("MM/DD/YYYY HH:mm");
- modelDateRangeMap[variables[didx]][model] = {
+ modelDateRangeMap[variable][model] = {
minDate: rowMinDate,
maxDate: rowMaxDate,
};
- const truthsArr = [];
if (variables[didx] === "15 Minute Visibility") {
const truths = rows[i].truth;
- const truthsArrRaw = truths
+ truthsModelOptionsMap[variables[didx]][model] = truths
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- var dummyTruth;
- for (var j = 0; j < truthsArrRaw.length; j++) {
- dummyTruth = truthsArrRaw[j].replace(/'|\[|\]/g, "");
- truthsArr.push(masterTruthValuesMap[variables[didx]][dummyTruth]);
- }
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (truth) {
+ return allTruthValuesMap[variable][truth.replace(/'|\[|\]/g, "")];
+ });
} else {
- truthsArr.push(masterTruthValuesMap[variables[didx]].default);
+ truthsModelOptionsMap[variables[didx]][model] = [
+ allTruthValuesMap[variable].default,
+ ];
}
- truthsModelOptionsMap[variables[didx]][model] = truthsArr;
const forecastLengths = rows[i].fcst_lens;
- const forecastLengthArr = forecastLengths
+ forecastLengthOptionsMap[variable][model] = forecastLengths
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (var j = 0; j < forecastLengthArr.length; j++) {
- forecastLengthArr[j] = (
- Number(forecastLengthArr[j].replace(/'|\[|\]/g, "")) / 60
- ).toString();
- }
- forecastLengthOptionsMap[variables[didx]][model] = forecastLengthArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (fhr) {
+ return Number(fhr.replace(/'|\[|\]/g, "")) / 60;
+ });
const thresholds = rows[i].trsh;
- const thresholdsArrRaw = thresholds
+ thresholdsModelOptionsMap[variable][model] = thresholds
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const thresholdsArr = [];
- var dummyThresh;
- for (var j = 0; j < thresholdsArrRaw.length; j++) {
- dummyThresh = thresholdsArrRaw[j].replace(/'|\[|\]/g, "");
- thresholdsArr.push(masterThresholdValuesMap[variables[didx]][dummyThresh]);
- }
- thresholdsModelOptionsMap[variables[didx]][model] = thresholdsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (threshold) {
+ return allThresholdValuesMap[variable][threshold.replace(/'|\[|\]/g, "")];
+ });
const { regions } = rows[i];
- const regionsArrRaw = regions
+ regionModelOptionsMap[variable][model] = regions
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const regionsArr = [];
- var dummyRegion;
- for (var j = 0; j < regionsArrRaw.length; j++) {
- dummyRegion = regionsArrRaw[j].replace(/'|\[|\]/g, "");
- regionsArr.push(masterRegionValuesMap[dummyRegion]);
- }
- regionModelOptionsMap[variables[didx]][model] = regionsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (region) {
+ return allRegionValuesMap[region.replace(/'|\[|\]/g, "")];
+ });
}
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
matsCollections.SiteMap.remove({});
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select madis_id,name,lat,lon,elev,description from madis3.metars_mats_global where lat > -16380 and lat < 16380 and lon > -32760 and lon < 32760 order by name;"
);
- for (var i = 0; i < rows.length; i++) {
- const site_name = rows[i].name;
- const site_description = rows[i].description;
- const site_id = rows[i].madis_id;
- const site_lat = rows[i].lat / 182;
- const site_lon = rows[i].lon / 182;
- const site_elev = rows[i].elev;
- siteOptionsMap[site_name] = [site_id];
-
- const point = [site_lat, site_lon];
- const obj = {
- name: site_name,
- origName: site_name,
- point,
- elevation: site_elev,
- options: {
- title: site_description,
- color: "red",
- size: 5,
- network: "METAR",
- peerOption: site_name,
- id: site_id,
- highLightColor: "blue",
- },
- };
- sitesLocationMap.push(obj);
-
- matsCollections.SiteMap.insert({ siteName: site_name, siteId: site_id });
+ for (let i = 0; i < rows.length; i += 1) {
+ const siteName = rows[i].name === undefined ? "unknown" : rows[i].name;
+ const siteDescription =
+ rows[i].description === undefined ? "unknown" : rows[i].description;
+ const siteId = rows[i].madis_id;
+ const siteLat = rows[i].lat === undefined ? -90 : rows[i].lat / 182;
+ const siteLon = rows[i].lon === undefined ? 0 : rows[i].lon / 182;
+ const siteElev = rows[i].elev === undefined ? 0 : rows[i].elev;
+
+ // There's one station right at the south pole that the map doesn't know how to render at all, so exclude it.
+ // Also exclude stations with missing data
+ if (siteLat < 90 && siteLat > -90) {
+ siteOptionsMap[siteName] = [siteId];
+
+ const point = [siteLat, siteLon];
+ const obj = {
+ name: siteName,
+ origName: siteName,
+ point,
+ elevation: siteElev,
+ options: {
+ title: siteDescription,
+ color: "red",
+ size: 5,
+ network: "METAR",
+ peerOption: siteName,
+ id: siteId,
+ highLightColor: "blue",
+ },
+ };
+ sitesLocationMap.push(obj);
+ matsCollections.SiteMap.insert({ siteName, siteId });
+ }
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
matsCollections.StationMap.remove({});
@@ -590,7 +569,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.variable.findOne({ name: "variable" });
+ const currentParam = matsCollections.variable.findOne({ name: "variable" });
if (!matsDataUtils.areObjectsEqual(currentParam.dates, modelDateRangeMap)) {
// have to reload variable data
matsCollections.variable.update(
@@ -648,7 +627,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["data-source"].findOne({ name: "data-source" });
+ const currentParam = matsCollections["data-source"].findOne({
+ name: "data-source",
+ });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap)) {
// have to reload model data
matsCollections["data-source"].update(
@@ -673,7 +654,7 @@ const doCurveParams = function () {
regionModelOptionsMap[variables[0]][
Object.keys(regionModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -688,10 +669,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.region.findOne({ name: "region" });
+ const currentParam = matsCollections.region.findOne({ name: "region" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, regionModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterRegionValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allRegionValuesMap)
) {
// have to reload region data
matsCollections.region.update(
@@ -699,7 +680,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: regionModelOptionsMap,
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
options:
regionModelOptionsMap[variables[0]][
Object.keys(regionModelOptionsMap[variables[0]])[0]
@@ -776,7 +757,7 @@ const doCurveParams = function () {
thresholdsModelOptionsMap[variables[0]][
Object.keys(thresholdsModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterThresholdValuesMap,
+ valuesMap: allThresholdValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -791,13 +772,13 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.threshold.findOne({ name: "threshold" });
+ const currentParam = matsCollections.threshold.findOne({ name: "threshold" });
if (
!matsDataUtils.areObjectsEqual(
currentParam.optionsMap,
thresholdsModelOptionsMap
) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterThresholdValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allThresholdValuesMap)
) {
// have to reload threshold data
matsCollections.threshold.update(
@@ -805,7 +786,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: thresholdsModelOptionsMap,
- valuesMap: masterThresholdValuesMap,
+ valuesMap: allThresholdValuesMap,
options:
thresholdsModelOptionsMap[variables[0]][
Object.keys(thresholdsModelOptionsMap[variables[0]])[0]
@@ -829,7 +810,7 @@ const doCurveParams = function () {
truthsModelOptionsMap[variables[0]][
Object.keys(truthsModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterTruthValuesMap,
+ valuesMap: allTruthValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -844,10 +825,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.truth.findOne({ name: "truth" });
+ const currentParam = matsCollections.truth.findOne({ name: "truth" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, truthsModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterTruthValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allTruthValuesMap)
) {
// have to reload truth data
matsCollections.truth.update(
@@ -855,7 +836,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: truthsModelOptionsMap,
- valuesMap: masterTruthValuesMap,
+ valuesMap: allTruthValuesMap,
options:
truthsModelOptionsMap[variables[0]][
Object.keys(truthsModelOptionsMap[variables[0]])[0]
@@ -895,7 +876,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["forecast-length"].findOne({
+ const currentParam = matsCollections["forecast-length"].findOne({
name: "forecast-length",
});
if (
@@ -1147,18 +1128,14 @@ const doCurveParams = function () {
}
// determine date defaults for dates and curveDates
- const defaultDb = matsCollections.variable.findOne(
- { name: "variable" },
+ const defaultDataSource = matsCollections["data-source"].findOne(
+ { name: "data-source" },
{ default: 1 }
).default;
modelDateRangeMap = matsCollections.variable.findOne(
{ name: "variable" },
{ dates: 1 }
).dates;
- const defaultDataSource = matsCollections["data-source"].findOne(
- { name: "data-source" },
- { default: 1 }
- ).default;
minDate = modelDateRangeMap[variables[0]][defaultDataSource].minDate;
maxDate = modelDateRangeMap[variables[0]][defaultDataSource].maxDate;
@@ -1199,7 +1176,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["curve-dates"].findOne({ name: "curve-dates" });
+ const currentParam = matsCollections["curve-dates"].findOne({
+ name: "curve-dates",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.startDate, minDate) ||
!matsDataUtils.areObjectsEqual(currentParam.stopDate, maxDate) ||
@@ -1612,7 +1591,8 @@ const doPlotGraph = function () {
Meteor.startup(function () {
matsCollections.Databases.remove({});
if (matsCollections.Databases.find({}).count() < 0) {
- console.log(
+ // eslint-disable-next-line no-console
+ console.warn(
"main startup: corrupted Databases collection: dropping Databases collection"
);
matsCollections.Databases.drop();
@@ -1629,7 +1609,7 @@ Meteor.startup(function () {
databases = Meteor.settings.private.databases;
}
if (databases !== null && databases !== undefined && Array.isArray(databases)) {
- for (let di = 0; di < databases.length; di++) {
+ for (let di = 0; di < databases.length; di += 1) {
matsCollections.Databases.insert(databases[di]);
}
}
@@ -1656,6 +1636,7 @@ Meteor.startup(function () {
);
if (cbConnection) {
// global cbScorecardSettingsPool
+ // eslint-disable-next-line no-undef
cbScorecardSettingsPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1682,6 +1663,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (metadataSettings) {
+ // eslint-disable-next-line no-undef
metadataPool = mysql.createPool(metadataSettings);
allPools.push({ pool: "metadataPool", role: matsTypes.DatabaseRoles.META_DATA });
}
@@ -1702,6 +1684,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (sumSettings) {
+ // eslint-disable-next-line no-undef
sumPool = mysql.createPool(sumSettings);
allPools.push({ pool: "sumPool", role: matsTypes.DatabaseRoles.SUMS_DATA });
}
@@ -1710,7 +1693,7 @@ Meteor.startup(function () {
const mdr = new matsTypes.MetaDataDBRecord("metadataPool", "mats_common", [
"region_descriptions",
]);
- for (let didx = 0; didx < variables.length; didx++) {
+ for (let didx = 0; didx < variables.length; didx += 1) {
mdr.addRecord("sumPool", variableDBNames[variables[didx]].modelDB, [
"threshold_descriptions",
]);
@@ -1725,7 +1708,7 @@ Meteor.startup(function () {
appType: matsTypes.AppTypes.mats,
});
} catch (error) {
- console.log(error.message);
+ throw new Error(error.message);
}
});
@@ -1733,6 +1716,7 @@ Meteor.startup(function () {
// These are application specific mongo data - like curve params
// The appSpecificResetRoutines object is a special name,
// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way.
+// eslint-disable-next-line no-undef
appSpecificResetRoutines = [
doPlotGraph,
doCurveParams,
diff --git a/apps/ensemble/.eslintrc.json b/apps/ensemble/.eslintrc.json
index a33ac158ff..79d49c5bb6 100644
--- a/apps/ensemble/.eslintrc.json
+++ b/apps/ensemble/.eslintrc.json
@@ -28,13 +28,6 @@
"space-before-function-paren": "off",
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
- "prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
- "no-undef": "warn",
- "no-unused-vars": "warn"
+ "prefer-arrow-callback": "off"
}
}
diff --git a/apps/ensemble/client/main.js b/apps/ensemble/client/main.js
index a87407a1f4..ecd922b6a2 100644
--- a/apps/ensemble/client/main.js
+++ b/apps/ensemble/client/main.js
@@ -2,6 +2,7 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+// eslint-disable-next-line no-unused-vars
import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common";
import "@fortawesome/fontawesome-free";
import "@fortawesome/fontawesome-free/css/all.css";
diff --git a/apps/ensemble/server/dataFunctions/data_contour.js b/apps/ensemble/server/dataFunctions/data_contour.js
index 06573192c3..9b85835a27 100644
--- a/apps/ensemble/server/dataFunctions/data_contour.js
+++ b/apps/ensemble/server/dataFunctions/data_contour.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContour = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,90 +23,91 @@ dataContour = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
- const totalProcessingStart = moment();
+
+ const curves = JSON.parse(JSON.stringify(plotParams.curves));
+ if (curves.length > 1) {
+ throw new Error("INFO: There must only be one added curve.");
+ }
+
+ const axisMap = Object.create(null);
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- const curves = JSON.parse(JSON.stringify(plotParams.curves));
- if (curves.length > 1) {
- throw new Error("INFO: There must only be one added curve.");
- }
- const dataset = [];
- const axisMap = Object.create(null);
- // initialize variables specific to the curve
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" }).optionsMap[
variable
];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- const regionStr = curve.region;
- let region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap[appParams.plotType];
- const tableStatPrefix = statisticOptionsMap[statisticSelect][2];
- const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
- const { members } = curve;
- const memberClause = `and m0.mem = ${members}`;
- const neighborhoodSize = curve["neighborhood-size"];
- const neighborhoodClause = `and m0.nhd_size = ${neighborhoodSize}`;
- let kernelClause = "";
- let probBinClause = "";
- let radiusClause = "";
- if (tableStatPrefix === "count") {
- const { kernel } = curve;
- kernelClause = `and m0.kernel = ${kernel}`;
- const probBins =
- curve["probability-bins"] === undefined ? [] : curve["probability-bins"];
- if (probBins.length !== 0 && probBins !== matsTypes.InputTypes.unused) {
- probBinClause = `and m0.prob IN(${probBins})`;
- } else {
- throw new Error("INFO: You need to select at least one probability bin.");
- }
- } else {
- const { radius } = curve;
- radiusClause = `and m0.radius = ${radius}`;
- }
+
let thresholdClause = "";
- let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") {
const { threshold } = curve;
+ if (threshold === undefined) {
+ throw new Error(
+ `INFO: ${label}'s threshold is undefined. Please assign it a value.`
+ );
+ }
thresholdClause = `and m0.trsh = ${threshold}`;
}
+
+ const { members } = curve;
+ const memberClause = `and m0.mem = ${members}`;
+
+ const neighborhoodSize = curve["neighborhood-size"];
+ const neighborhoodClause = `and m0.nhd_size = ${neighborhoodSize}`;
+
+ let validTimeClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.time%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap[appParams.plotType];
+ const [statisticClause] = statisticOptionsMap[statisticSelect];
+ const tableStatPrefix = statisticOptionsMap[statisticSelect][2];
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -116,93 +118,130 @@ dataContour = function (plotParams, plotFunction) {
dateString = "m0.time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const [statisticClause] = statisticOptionsMap[statisticSelect];
+
+ let kernelClause = "";
+ let probBinClause = "";
+ let radiusClause = "";
+ if (tableStatPrefix === "count") {
+ const { kernel } = curve;
+ kernelClause = `and m0.kernel = ${kernel}`;
+ const probBins =
+ curve["probability-bins"] === undefined ? [] : curve["probability-bins"];
+ if (probBins.length !== 0 && probBins !== matsTypes.InputTypes.unused) {
+ probBinClause = `and m0.prob IN(${probBins})`;
+ } else {
+ throw new Error("INFO: You need to select at least one probability bin.");
+ }
+ } else {
+ const { radius } = curve;
+ radiusClause = `and m0.radius = ${radius}`;
+ }
+
+ const regionStr = curve.region;
+ let region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
+
+ const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
+
// For contours, this functions as the colorbar label.
const statType = statisticOptionsMap[statisticSelect][0];
[, , , curve.unitKey] = statisticOptionsMap[statisticSelect];
let d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{memberClause}} " +
- "{{neighborhoodClause}} " +
- "{{thresholdClause}} " +
- "{{kernelClause}} " +
- "{{probBinClause}} " +
- "{{radiusClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
-
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{memberClause}}", memberClause);
- statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{kernelClause}}", kernelClause);
- statement = statement.replace("{{probBinClause}}", probBinClause);
- statement = statement.replace("{{radiusClause}}", radiusClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{memberClause}} " +
+ "{{neighborhoodClause}} " +
+ "{{thresholdClause}} " +
+ "{{kernelClause}} " +
+ "{{probBinClause}} " +
+ "{{radiusClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
+
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{memberClause}}", memberClause);
+ statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{kernelClause}}", kernelClause);
+ statement = statement.replace("{{probBinClause}}", probBinClause);
+ statement = statement.replace("{{radiusClause}}", radiusClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
+ }
+
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
+ // this is NOT an error just a no data condition
+ dataFoundForCurve = false;
+ } else {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
}
- }
- if (!dataFoundForCurve) {
- // we found no data for any curves so don't bother proceeding
- throw new Error("INFO: No valid data for any curves.");
+ if (!dataFoundForCurve) {
+ // we found no data for any curves so don't bother proceeding
+ throw new Error("INFO: No valid data for any curves.");
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
}
// set curve annotation to be the curve mean -- may be recalculated later
diff --git a/apps/ensemble/server/dataFunctions/data_contour_diff.js b/apps/ensemble/server/dataFunctions/data_contour_diff.js
index 1e7a2a04f0..40b0dc0b33 100644
--- a/apps/ensemble/server/dataFunctions/data_contour_diff.js
+++ b/apps/ensemble/server/dataFunctions/data_contour_diff.js
@@ -14,6 +14,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContourDiff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -24,95 +25,96 @@ dataContourDiff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
let dataNotFoundForAnyCurve = false;
+
+ let curves = JSON.parse(JSON.stringify(plotParams.curves));
+ const curvesLength = curves.length;
+ if (curvesLength !== 2) {
+ throw new Error("INFO: There must be two added curves.");
+ }
+
+ const axisMap = Object.create(null);
const showSignificance = plotParams.significance !== "none";
- const totalProcessingStart = moment();
+
+ let statType;
+ let statisticSelect;
+
+ let statement = "";
+ let error = "";
+ let dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- let curves = JSON.parse(JSON.stringify(plotParams.curves));
- const curvesLength = curves.length;
- if (curvesLength !== 2) {
- throw new Error("INFO: There must be two added curves.");
- }
- let statType;
- let statisticSelect;
- let dataset = [];
- const axisMap = Object.create(null);
for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- const regionStr = curve.region;
- let region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
- statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap[appParams.plotType];
- const tableStatPrefix = statisticOptionsMap[statisticSelect][2];
- const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
- const { members } = curve;
- const memberClause = `and m0.mem = ${members}`;
- const neighborhoodSize = curve["neighborhood-size"];
- const neighborhoodClause = `and m0.nhd_size = ${neighborhoodSize}`;
- let kernelClause = "";
- let probBinClause = "";
- let radiusClause = "";
- if (tableStatPrefix === "count") {
- const { kernel } = curve;
- kernelClause = `and m0.kernel = ${kernel}`;
- const probBins =
- curve["probability-bins"] === undefined ? [] : curve["probability-bins"];
- if (probBins.length !== 0 && probBins !== matsTypes.InputTypes.unused) {
- probBinClause = `and m0.prob IN(${probBins})`;
- } else {
- throw new Error("INFO: You need to select at least one probability bin.");
- }
- } else {
- const { radius } = curve;
- radiusClause = `and m0.radius = ${radius}`;
- }
+
let thresholdClause = "";
- let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") {
const { threshold } = curve;
+ if (threshold === undefined) {
+ throw new Error(
+ `INFO: ${label}'s threshold is undefined. Please assign it a value.`
+ );
+ }
thresholdClause = `and m0.trsh = ${threshold}`;
}
+
+ const { members } = curve;
+ const memberClause = `and m0.mem = ${members}`;
+
+ const neighborhoodSize = curve["neighborhood-size"];
+ const neighborhoodClause = `and m0.nhd_size = ${neighborhoodSize}`;
+
+ let validTimeClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.time%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap[appParams.plotType];
+ const [statisticClause] = statisticOptionsMap[statisticSelect];
+ const tableStatPrefix = statisticOptionsMap[statisticSelect][2];
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -123,89 +125,123 @@ dataContourDiff = function (plotParams, plotFunction) {
dateString = "m0.time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const [statisticClause] = statisticOptionsMap[statisticSelect];
+
+ let kernelClause = "";
+ let probBinClause = "";
+ let radiusClause = "";
+ if (tableStatPrefix === "count") {
+ const { kernel } = curve;
+ kernelClause = `and m0.kernel = ${kernel}`;
+ const probBins =
+ curve["probability-bins"] === undefined ? [] : curve["probability-bins"];
+ if (probBins.length !== 0 && probBins !== matsTypes.InputTypes.unused) {
+ probBinClause = `and m0.prob IN(${probBins})`;
+ } else {
+ throw new Error("INFO: You need to select at least one probability bin.");
+ }
+ } else {
+ const { radius } = curve;
+ radiusClause = `and m0.radius = ${radius}`;
+ }
+
+ const regionStr = curve.region;
+ let region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
+
+ const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
+
// For contours, this functions as the colorbar label.
[statType] = statisticOptionsMap[statisticSelect];
[, , , curve.unitKey] = statisticOptionsMap[statisticSelect];
let d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{memberClause}} " +
- "{{neighborhoodClause}} " +
- "{{thresholdClause}} " +
- "{{kernelClause}} " +
- "{{probBinClause}} " +
- "{{radiusClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{memberClause}} " +
+ "{{neighborhoodClause}} " +
+ "{{thresholdClause}} " +
+ "{{kernelClause}} " +
+ "{{probBinClause}} " +
+ "{{radiusClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{memberClause}}", memberClause);
- statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{kernelClause}}", kernelClause);
- statement = statement.replace("{{probBinClause}}", probBinClause);
- statement = statement.replace("{{radiusClause}}", radiusClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{memberClause}}", memberClause);
+ statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{kernelClause}}", kernelClause);
+ statement = statement.replace("{{probBinClause}}", probBinClause);
+ statement = statement.replace("{{radiusClause}}", radiusClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
+ }
+
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ dataNotFoundForAnyCurve = true;
}
- dataNotFoundForAnyCurve = true;
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
}
// set curve annotation to be the curve mean -- may be recalculated later
@@ -259,13 +295,9 @@ dataContourDiff = function (plotParams, plotFunction) {
statType === "ctc",
statType === "scalar"
);
-
- // make a copy of the plotParams that we can modify
- const diffPlotParams = JSON.parse(JSON.stringify(plotParams));
- diffPlotParams.curves = matsDataUtils.getDiffContourCurveParams(
- diffPlotParams.curves
- );
- curves = diffPlotParams.curves;
+ const newPlotParams = plotParams;
+ newPlotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
+ curves = newPlotParams.curves;
dataset[0].name = matsPlotUtils.getCurveText(
matsTypes.PlotTypes.contourDiff,
curves[0]
@@ -281,7 +313,7 @@ dataContourDiff = function (plotParams, plotFunction) {
const result = matsDataProcessUtils.processDataContour(
dataset,
curveInfoParams,
- diffPlotParams,
+ newPlotParams,
bookkeepingParams
);
plotFunction(result);
diff --git a/apps/ensemble/server/dataFunctions/data_dieoff.js b/apps/ensemble/server/dataFunctions/data_dieoff.js
index 96d6301276..fe415261b3 100644
--- a/apps/ensemble/server/dataFunctions/data_dieoff.js
+++ b/apps/ensemble/server/dataFunctions/data_dieoff.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDieoff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,54 +24,77 @@ dataDieoff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- let statType;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- const regionStr = curve.region;
- let region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap[appParams.plotType];
- const tableStatPrefix = statisticOptionsMap[statisticSelect][2];
- const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
+
const { threshold } = curve;
const thresholdClause = `and m0.trsh = ${threshold}`;
+
const { members } = curve;
const memberClause = `and m0.mem = ${members}`;
+
const neighborhoodSize = curve["neighborhood-size"];
const neighborhoodClause = `and m0.nhd_size = ${neighborhoodSize}`;
+
+ let validTimeClause = "";
+ let validTimes;
+
+ let utcCycleStartClause = "";
+ let utcCycleStart;
+
+ const forecastLengthClause = "";
+ const forecastLengthStr = curve["dieoff-type"];
+ const forecastLengthOptionsMap = matsCollections["dieoff-type"].findOne(
+ { name: "dieoff-type" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const forecastLength = forecastLengthOptionsMap[forecastLengthStr][0];
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap[appParams.plotType];
+ const [statisticClause] = statisticOptionsMap[statisticSelect];
+ const tableStatPrefix = statisticOptionsMap[statisticSelect][2];
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ let dateClause;
+
let kernelClause = "";
let probBinClause = "";
let radiusClause = "";
@@ -88,21 +112,18 @@ dataDieoff = function (plotParams, plotFunction) {
const { radius } = curve;
radiusClause = `and m0.radius = ${radius}`;
}
- let validTimes;
- let validTimeClause = "";
- let utcCycleStart;
- let utcCycleStartClause = "";
- const forecastLengthStr = curve["dieoff-type"];
- const forecastLengthOptionsMap = matsCollections["dieoff-type"].findOne(
- { name: "dieoff-type" },
- { optionsMap: 1 }
- ).optionsMap;
- const forecastLength = forecastLengthOptionsMap[forecastLengthStr][0];
- const forecastLengthClause = "";
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let dateClause;
+
+ const regionStr = curve.region;
+ let region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
+
+ const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
+
if (forecastLength === matsTypes.ForecastTypes.dieoff) {
validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
@@ -119,7 +140,7 @@ dataDieoff = function (plotParams, plotFunction) {
} else {
dateClause = `and m0.time-m0.fcst_len*3600 = ${fromSecs}`;
}
- const [statisticClause] = statisticOptionsMap[statisticSelect];
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
@@ -134,56 +155,56 @@ dataDieoff = function (plotParams, plotFunction) {
let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.fcst_len as fcst_lead, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{memberClause}} " +
- "{{neighborhoodClause}} " +
- "{{thresholdClause}} " +
- "{{kernelClause}} " +
- "{{probBinClause}} " +
- "{{radiusClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{utcCycleStartClause}} " +
- "group by fcst_lead " +
- "order by fcst_lead" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{memberClause}}", memberClause);
- statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{kernelClause}}", kernelClause);
- statement = statement.replace("{{probBinClause}}", probBinClause);
- statement = statement.replace("{{radiusClause}}", radiusClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
let queryResult;
const startMoment = moment();
let finishMoment;
try {
+ statement =
+ "select m0.fcst_len as fcst_lead, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{memberClause}} " +
+ "{{neighborhoodClause}} " +
+ "{{thresholdClause}} " +
+ "{{kernelClause}} " +
+ "{{probBinClause}} " +
+ "{{radiusClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{utcCycleStartClause}} " +
+ "group by fcst_lead " +
+ "order by fcst_lead" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{memberClause}}", memberClause);
+ statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{kernelClause}}", kernelClause);
+ statement = statement.replace("{{probBinClause}}", probBinClause);
+ statement = statement.replace("{{radiusClause}}", radiusClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -199,6 +220,7 @@ dataDieoff = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/ensemble/server/dataFunctions/data_gridscale_prob.js b/apps/ensemble/server/dataFunctions/data_gridscale_prob.js
index 6ddfd0c9e9..0b75edc4a2 100644
--- a/apps/ensemble/server/dataFunctions/data_gridscale_prob.js
+++ b/apps/ensemble/server/dataFunctions/data_gridscale_prob.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataGridScaleProb = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,66 +24,84 @@ dataGridScaleProb = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- let statType;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- const regionStr = curve.region;
- let region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
- const statisticSelect = "Grid Scale Count";
- const tableStatPrefix = "count";
- const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
+
const { threshold } = curve;
const thresholdClause = `and m0.trsh = ${threshold}`;
+
const { members } = curve;
const memberClause = `and m0.mem = ${members}`;
+
const neighborhoodSize = curve["neighborhood-size"];
const neighborhoodClause = `and m0.nhd_size = ${neighborhoodSize}`;
- let kernelClause = "";
- const { kernel } = curve;
- kernelClause = `and m0.kernel = ${kernel}`;
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
}
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
+
+ const statisticSelect = "Grid Scale Count";
+ const statisticClause =
+ "sum(m0.nhdfcstcount) as stat, group_concat(m0.time, ';', m0.nhdfcstcount order by m0.time) as sub_data, count(m0.nhdfcstcount) as N0";
+ const tableStatPrefix = "count";
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
- const statisticClause =
- "sum(m0.nhdfcstcount) as stat, group_concat(m0.time, ';', m0.nhdfcstcount order by m0.time) as sub_data, count(m0.nhdfcstcount) as N0";
+
+ let kernelClause = "";
+ const { kernel } = curve;
+ kernelClause = `and m0.kernel = ${kernel}`;
+
+ const regionStr = curve.region;
+ let region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
+
+ const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
@@ -93,50 +112,50 @@ dataGridScaleProb = function (plotParams, plotFunction) {
let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.prob as binValue, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{memberClause}} " +
- "{{neighborhoodClause}} " +
- "{{thresholdClause}} " +
- "{{kernelClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by binValue " +
- "order by binValue" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{memberClause}}", memberClause);
- statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{kernelClause}}", kernelClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
let queryResult;
const startMoment = moment();
let finishMoment;
try {
+ statement =
+ "select m0.prob as binValue, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{memberClause}} " +
+ "{{neighborhoodClause}} " +
+ "{{thresholdClause}} " +
+ "{{kernelClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by binValue " +
+ "order by binValue" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{memberClause}}", memberClause);
+ statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{kernelClause}}", kernelClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -152,6 +171,7 @@ dataGridScaleProb = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -224,6 +244,7 @@ dataGridScaleProb = function (plotParams, plotFunction) {
// we found no data for any curves so don't bother proceeding
throw new Error("INFO: No valid data for any curves.");
}
+
// process the data returned by the query
const curveInfoParams = {
curves,
diff --git a/apps/ensemble/server/dataFunctions/data_histogram.js b/apps/ensemble/server/dataFunctions/data_histogram.js
index f8bf5c73c7..ec871d0efc 100644
--- a/apps/ensemble/server/dataFunctions/data_histogram.js
+++ b/apps/ensemble/server/dataFunctions/data_histogram.js
@@ -11,6 +11,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataHistogram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -21,20 +22,25 @@ dataHistogram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
- const alreadyMatched = false;
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
const dataFoundForCurve = [];
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+ const alreadyMatched = false;
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
+
+ const axisMap = Object.create(null);
let statType;
let varUnits;
+
+ let statement = "";
+ let error = "";
const dataset = [];
const allReturnedSubStats = [];
const allReturnedSubSecs = [];
- const axisMap = Object.create(null);
// process user bin customizations
const binParams = matsDataUtils.setHistogramParameters(plotParams);
@@ -44,35 +50,47 @@ dataHistogram = function (plotParams, plotFunction) {
for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
dataFoundForCurve[curveIndex] = true;
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- const regionStr = curve.region;
- let region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap[appParams.plotType];
- const tableStatPrefix = statisticOptionsMap[statisticSelect][2];
- const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
+
const { threshold } = curve;
const thresholdClause = `and m0.trsh = ${threshold}`;
+
const { members } = curve;
const memberClause = `and m0.mem = ${members}`;
+
const neighborhoodSize = curve["neighborhood-size"];
const neighborhoodClause = `and m0.nhd_size = ${neighborhoodSize}`;
+
+ let validTimeClause = "";
+ const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
+ validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
+ }
+
+ const forecastLength = curve["forecast-length"];
+ const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap[appParams.plotType];
+ const [statisticClause] = statisticOptionsMap[statisticSelect];
+ const tableStatPrefix = statisticOptionsMap[statisticSelect][2];
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
let kernelClause = "";
let probBinClause = "";
let radiusClause = "";
@@ -90,18 +108,18 @@ dataHistogram = function (plotParams, plotFunction) {
const { radius } = curve;
radiusClause = `and m0.radius = ${radius}`;
}
- let validTimeClause = "";
- const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
- validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
- }
- const forecastLength = curve["forecast-length"];
- const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
- const [statisticClause] = statisticOptionsMap[statisticSelect];
+
+ const regionStr = curve.region;
+ let region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
+
+ const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
@@ -117,54 +135,54 @@ dataHistogram = function (plotParams, plotFunction) {
let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.time as avtime, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{memberClause}} " +
- "{{neighborhoodClause}} " +
- "{{thresholdClause}} " +
- "{{kernelClause}} " +
- "{{probBinClause}} " +
- "{{radiusClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{memberClause}}", memberClause);
- statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{kernelClause}}", kernelClause);
- statement = statement.replace("{{probBinClause}}", probBinClause);
- statement = statement.replace("{{radiusClause}}", radiusClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
let queryResult;
const startMoment = moment();
let finishMoment;
try {
+ statement =
+ "select m0.time as avtime, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{memberClause}} " +
+ "{{neighborhoodClause}} " +
+ "{{thresholdClause}} " +
+ "{{kernelClause}} " +
+ "{{probBinClause}} " +
+ "{{radiusClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{memberClause}}", memberClause);
+ statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{kernelClause}}", kernelClause);
+ statement = statement.replace("{{probBinClause}}", probBinClause);
+ statement = statement.replace("{{radiusClause}}", radiusClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -182,6 +200,7 @@ dataHistogram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/ensemble/server/dataFunctions/data_reliability.js b/apps/ensemble/server/dataFunctions/data_reliability.js
index 1c788a265f..6fbb4e823c 100644
--- a/apps/ensemble/server/dataFunctions/data_reliability.js
+++ b/apps/ensemble/server/dataFunctions/data_reliability.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataReliability = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,65 +23,84 @@ dataReliability = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- let statType;
- const dataset = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+ let statType;
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- const regionStr = curve.region;
- let region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
- const tableStatPrefix = "count";
- const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
+
const { threshold } = curve;
const thresholdClause = `and m0.trsh = ${threshold}`;
+
const { members } = curve;
const memberClause = `and m0.mem = ${members}`;
+
const neighborhoodSize = curve["neighborhood-size"];
const neighborhoodClause = `and m0.nhd_size = ${neighborhoodSize}`;
- let kernelClause = "";
- const { kernel } = curve;
- kernelClause = `and m0.kernel in (0, ${kernel})`;
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
}
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
const statisticClause =
"sum(m0.nhdfcstcount) as fcstcount, sum(m0.fcstcount) as rawfcstcount, sum(m0.nhdhitcount) " +
"as hitcount, group_concat(m0.time, ';', m0.nhdfcstcount, ';', " +
"m0.fcstcount, ';', m0.nhdhitcount order by m0.time) as sub_data, count(m0.nhdfcstcount) as N0";
+ const tableStatPrefix = "count";
+
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ let kernelClause = "";
+ const { kernel } = curve;
+ kernelClause = `and m0.kernel in (0, ${kernel})`;
+
+ const regionStr = curve.region;
+ let region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
+
+ const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
@@ -91,50 +111,50 @@ dataReliability = function (plotParams, plotFunction) {
let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.prob as binValue, m0.kernel, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{memberClause}} " +
- "{{neighborhoodClause}} " +
- "{{thresholdClause}} " +
- "{{kernelClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by binValue, kernel " +
- "order by binValue, kernel" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{memberClause}}", memberClause);
- statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{kernelClause}}", kernelClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
let queryResult;
const startMoment = moment();
let finishMoment;
try {
+ statement =
+ "select m0.prob as binValue, m0.kernel, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{memberClause}} " +
+ "{{neighborhoodClause}} " +
+ "{{thresholdClause}} " +
+ "{{kernelClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by binValue, kernel " +
+ "order by binValue, kernel" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{memberClause}}", memberClause);
+ statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{kernelClause}}", kernelClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBReliability(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
kernel
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -150,6 +170,7 @@ dataReliability = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/ensemble/server/dataFunctions/data_series.js b/apps/ensemble/server/dataFunctions/data_series.js
index b865047870..51c2759f85 100644
--- a/apps/ensemble/server/dataFunctions/data_series.js
+++ b/apps/ensemble/server/dataFunctions/data_series.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSeries = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,57 +24,80 @@ dataSeries = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- let statType;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- const regionStr = curve.region;
- let region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap[appParams.plotType];
- const tableStatPrefix = statisticOptionsMap[statisticSelect][2];
- const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
+
const { threshold } = curve;
const thresholdClause = `and m0.trsh = ${threshold}`;
+
const { members } = curve;
const memberClause = `and m0.mem = ${members}`;
+
const neighborhoodSize = curve["neighborhood-size"];
const neighborhoodClause = `and m0.nhd_size = ${neighborhoodSize}`;
+
+ let validTimeClause = "";
+ const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
+ validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
+ }
+
+ let forecastLength = curve["forecast-length"];
+ const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap[appParams.plotType];
+ const [statisticClause] = statisticOptionsMap[statisticSelect];
+ const tableStatPrefix = statisticOptionsMap[statisticSelect][2];
+
+ const averageStr = curve.average;
+ const averageOptionsMap = matsCollections.average.findOne(
+ { name: "average" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const average = averageOptionsMap[averageStr][0];
+
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
let kernelClause = "";
let probBinClause = "";
let radiusClause = "";
@@ -91,21 +115,18 @@ dataSeries = function (plotParams, plotFunction) {
const { radius } = curve;
radiusClause = `and m0.radius = ${radius}`;
}
- let validTimeClause = "";
- const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
- validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
- }
- let forecastLength = curve["forecast-length"];
- const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
- const averageStr = curve.average;
- const averageOptionsMap = matsCollections.average.findOne(
- { name: "average" },
- { optionsMap: 1 }
- ).optionsMap;
- const average = averageOptionsMap[averageStr][0];
- const [statisticClause] = statisticOptionsMap[statisticSelect];
+
+ const regionStr = curve.region;
+ let region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
+
+ const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
@@ -120,54 +141,53 @@ dataSeries = function (plotParams, plotFunction) {
let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select {{average}} as avtime, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{memberClause}} " +
- "{{neighborhoodClause}} " +
- "{{thresholdClause}} " +
- "{{kernelClause}} " +
- "{{probBinClause}} " +
- "{{radiusClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{average}}", average);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{memberClause}}", memberClause);
- statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{kernelClause}}", kernelClause);
- statement = statement.replace("{{probBinClause}}", probBinClause);
- statement = statement.replace("{{radiusClause}}", radiusClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
- // math is done on forecastLength later on -- set all analyses to 0
- if (forecastLength === "-99") {
- forecastLength = "0";
- }
-
let queryResult;
const startMoment = moment();
let finishMoment;
try {
+ statement =
+ "select {{average}} as avtime, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{memberClause}} " +
+ "{{neighborhoodClause}} " +
+ "{{thresholdClause}} " +
+ "{{kernelClause}} " +
+ "{{probBinClause}} " +
+ "{{radiusClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{average}}", average);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{memberClause}}", memberClause);
+ statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{kernelClause}}", kernelClause);
+ statement = statement.replace("{{probBinClause}}", probBinClause);
+ statement = statement.replace("{{radiusClause}}", radiusClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
+ // math is done on forecastLength later on -- set all analyses to 0
+ if (forecastLength === "-99") {
+ forecastLength = "0";
+ }
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBTimeSeries(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
model,
forecastLength,
@@ -179,7 +199,9 @@ dataSeries = function (plotParams, plotFunction) {
appParams,
false
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -195,6 +217,7 @@ dataSeries = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/ensemble/server/dataFunctions/data_threshold.js b/apps/ensemble/server/dataFunctions/data_threshold.js
index e99c2c94fd..fb270ad6bb 100644
--- a/apps/ensemble/server/dataFunctions/data_threshold.js
+++ b/apps/ensemble/server/dataFunctions/data_threshold.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataThreshold = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,52 +24,69 @@ dataThreshold = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- let statType;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- const regionStr = curve.region;
- let region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
+
+ const { members } = curve;
+ const memberClause = `and m0.mem = ${members}`;
+
+ const neighborhoodSize = curve["neighborhood-size"];
+ const neighborhoodClause = `and m0.nhd_size = ${neighborhoodSize}`;
+
+ let validTimeClause = "";
+ const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
+ validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
+ }
+
+ const forecastLength = curve["forecast-length"];
+ const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap[appParams.plotType];
+ const [statisticClause] = statisticOptionsMap[statisticSelect];
const tableStatPrefix = statisticOptionsMap[statisticSelect][2];
- const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
- const { members } = curve;
- const memberClause = `and m0.mem = ${members}`;
- const neighborhoodSize = curve["neighborhood-size"];
- const neighborhoodClause = `and m0.nhd_size = ${neighborhoodSize}`;
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
let kernelClause = "";
let probBinClause = "";
let radiusClause = "";
@@ -86,18 +104,18 @@ dataThreshold = function (plotParams, plotFunction) {
const { radius } = curve;
radiusClause = `and m0.radius = ${radius}`;
}
- let validTimeClause = "";
- const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
- validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
- }
- const forecastLength = curve["forecast-length"];
- const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
- const [statisticClause] = statisticOptionsMap[statisticSelect];
+
+ const regionStr = curve.region;
+ let region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
+
+ const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
@@ -112,52 +130,52 @@ dataThreshold = function (plotParams, plotFunction) {
let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.trsh as thresh, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{memberClause}} " +
- "{{neighborhoodClause}} " +
- "{{kernelClause}} " +
- "{{probBinClause}} " +
- "{{radiusClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by thresh " +
- "order by thresh" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{memberClause}}", memberClause);
- statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
- statement = statement.replace("{{kernelClause}}", kernelClause);
- statement = statement.replace("{{probBinClause}}", probBinClause);
- statement = statement.replace("{{radiusClause}}", radiusClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
let queryResult;
const startMoment = moment();
let finishMoment;
try {
+ statement =
+ "select m0.trsh as thresh, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{memberClause}} " +
+ "{{neighborhoodClause}} " +
+ "{{kernelClause}} " +
+ "{{probBinClause}} " +
+ "{{radiusClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by thresh " +
+ "order by thresh" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{memberClause}}", memberClause);
+ statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
+ statement = statement.replace("{{kernelClause}}", kernelClause);
+ statement = statement.replace("{{probBinClause}}", probBinClause);
+ statement = statement.replace("{{radiusClause}}", radiusClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -173,6 +191,7 @@ dataThreshold = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/ensemble/server/dataFunctions/data_validtime.js b/apps/ensemble/server/dataFunctions/data_validtime.js
index 48f91a1eaf..a8ad24039b 100644
--- a/apps/ensemble/server/dataFunctions/data_validtime.js
+++ b/apps/ensemble/server/dataFunctions/data_validtime.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataValidTime = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,54 +24,66 @@ dataValidTime = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- let statType;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- const regionStr = curve.region;
- let region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap[appParams.plotType];
- const tableStatPrefix = statisticOptionsMap[statisticSelect][2];
- const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
+
const { threshold } = curve;
const thresholdClause = `and m0.trsh = ${threshold}`;
+
const { members } = curve;
const memberClause = `and m0.mem = ${members}`;
+
const neighborhoodSize = curve["neighborhood-size"];
const neighborhoodClause = `and m0.nhd_size = ${neighborhoodSize}`;
+
+ const forecastLength = curve["forecast-length"];
+ const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap[appParams.plotType];
+ const [statisticClause] = statisticOptionsMap[statisticSelect];
+ const tableStatPrefix = statisticOptionsMap[statisticSelect][2];
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
let kernelClause = "";
let probBinClause = "";
let radiusClause = "";
@@ -88,13 +101,17 @@ dataValidTime = function (plotParams, plotFunction) {
const { radius } = curve;
radiusClause = `and m0.radius = ${radius}`;
}
- const forecastLength = curve["forecast-length"];
- const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
- const [statisticClause] = statisticOptionsMap[statisticSelect];
+
+ const regionStr = curve.region;
+ let region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ region = region === "Full" ? "Full_domain" : region; // this db doesn't handle the full domain the way the others do
+
+ const queryTableClause = `from ${databaseRef}.${model}_${tableStatPrefix}_${region} as m0`;
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
@@ -109,52 +126,52 @@ dataValidTime = function (plotParams, plotFunction) {
let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select floor(m0.time%(24*3600)/3600) as hr_of_day, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{memberClause}} " +
- "{{neighborhoodClause}} " +
- "{{thresholdClause}} " +
- "{{kernelClause}} " +
- "{{probBinClause}} " +
- "{{radiusClause}} " +
- "{{forecastLengthClause}} " +
- "group by hr_of_day " +
- "order by hr_of_day" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{memberClause}}", memberClause);
- statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{kernelClause}}", kernelClause);
- statement = statement.replace("{{probBinClause}}", probBinClause);
- statement = statement.replace("{{radiusClause}}", radiusClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
let queryResult;
const startMoment = moment();
let finishMoment;
try {
+ statement =
+ "select floor(m0.time%(24*3600)/3600) as hr_of_day, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{memberClause}} " +
+ "{{neighborhoodClause}} " +
+ "{{thresholdClause}} " +
+ "{{kernelClause}} " +
+ "{{probBinClause}} " +
+ "{{radiusClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by hr_of_day " +
+ "order by hr_of_day" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{memberClause}}", memberClause);
+ statement = statement.replace("{{neighborhoodClause}}", neighborhoodClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{kernelClause}}", kernelClause);
+ statement = statement.replace("{{probBinClause}}", probBinClause);
+ statement = statement.replace("{{radiusClause}}", radiusClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -170,6 +187,7 @@ dataValidTime = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/ensemble/server/main.js b/apps/ensemble/server/main.js
index 1f2ffa9b8a..7d797642ba 100644
--- a/apps/ensemble/server/main.js
+++ b/apps/ensemble/server/main.js
@@ -5,6 +5,7 @@
import { Meteor } from "meteor/meteor";
import { mysql } from "meteor/pcel:mysql";
import { moment } from "meteor/momentjs:moment";
+import { _ } from "meteor/underscore";
import {
matsMethods,
matsTypes,
@@ -328,42 +329,36 @@ const doCurveParams = function () {
const thresholdsModelOptionsMap = {};
const kernelModelOptionsMap = {};
const radiusModelOptionsMap = {};
- const masterRegionValuesMap = {};
+ const allRegionValuesMap = {};
let allKernels = [];
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- metadataPool,
+ metadataPool, // eslint-disable-line no-undef
"select short_name,description from region_descriptions;"
);
- let masterRegDescription;
- let masterShortName;
for (let j = 0; j < rows.length; j += 1) {
- masterRegDescription = rows[j].description.trim();
- masterShortName = rows[j].short_name.trim();
- masterRegionValuesMap[masterShortName] = masterRegDescription;
+ allRegionValuesMap[rows[j].short_name.trim()] = rows[j].description.trim();
}
} catch (err) {
throw new Error(err.message);
}
- let rows;
- let didx;
-
try {
- for (didx = 0; didx < variables.length; didx += 1) {
- modelOptionsMap[variables[didx]] = {};
- modelDateRangeMap[variables[didx]] = {};
- forecastLengthOptionsMap[variables[didx]] = {};
- memberModelOptionsMap[variables[didx]] = {};
- neighborhoodModelOptionsMap[variables[didx]] = {};
- thresholdsModelOptionsMap[variables[didx]] = {};
- kernelModelOptionsMap[variables[didx]] = {};
- radiusModelOptionsMap[variables[didx]] = {};
- regionModelOptionsMap[variables[didx]] = {};
+ for (let didx = 0; didx < variables.length; didx += 1) {
+ const variable = variables[didx];
+ modelOptionsMap[variable] = {};
+ modelDateRangeMap[variable] = {};
+ forecastLengthOptionsMap[variable] = {};
+ memberModelOptionsMap[variable] = {};
+ neighborhoodModelOptionsMap[variable] = {};
+ thresholdsModelOptionsMap[variable] = {};
+ kernelModelOptionsMap[variable] = {};
+ radiusModelOptionsMap[variable] = {};
+ regionModelOptionsMap[variable] = {};
- rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
+ sumPool, // eslint-disable-line no-undef
`select model,regions,display_text,fcst_lens,mems,nhd_sizes,trshs,kernels,radii,mindate,maxdate from ${
variableDBNames[variables[didx]]
}.regions_per_model_mats_all_categories order by display_category, display_order;`
@@ -371,7 +366,7 @@ const doCurveParams = function () {
for (let i = 0; i < rows.length; i += 1) {
const modelValue = rows[i].model.trim();
const model = rows[i].display_text.trim();
- modelOptionsMap[variables[didx]][model] = [modelValue];
+ modelOptionsMap[variable][model] = [modelValue];
const rowMinDate = moment
.utc(rows[i].mindate * 1000)
@@ -379,82 +374,73 @@ const doCurveParams = function () {
const rowMaxDate = moment
.utc(rows[i].maxdate * 1000)
.format("MM/DD/YYYY HH:mm");
- modelDateRangeMap[variables[didx]][model] = {
+ modelDateRangeMap[variable][model] = {
minDate: rowMinDate,
maxDate: rowMaxDate,
};
const forecastLengths = rows[i].fcst_lens;
- const forecastLengthArr = forecastLengths
+ forecastLengthOptionsMap[variable][model] = forecastLengths
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (let j = 0; j < forecastLengthArr.length; j += 1) {
- forecastLengthArr[j] = forecastLengthArr[j].replace(/'|\[|\]/g, "");
- }
- forecastLengthOptionsMap[variables[didx]][model] = forecastLengthArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (fhr) {
+ return fhr.replace(/'|\[|\]/g, "");
+ });
const { mems } = rows[i];
- const memArr = mems
+ memberModelOptionsMap[variable][model] = mems
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (let j = 0; j < memArr.length; j += 1) {
- memArr[j] = memArr[j].replace(/'|\[|\]/g, "");
- }
- memberModelOptionsMap[variables[didx]][model] = memArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (mem) {
+ return mem.replace(/'|\[|\]/g, "");
+ });
const nhdSizes = rows[i].nhd_sizes;
- const nhdSizeArr = nhdSizes
+ neighborhoodModelOptionsMap[variable][model] = nhdSizes
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (let j = 0; j < nhdSizeArr.length; j += 1) {
- nhdSizeArr[j] = nhdSizeArr[j].replace(/'|\[|\]/g, "");
- }
- neighborhoodModelOptionsMap[variables[didx]][model] = nhdSizeArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (nhdSize) {
+ return nhdSize.replace(/'|\[|\]/g, "");
+ });
const thresholds = rows[i].trshs;
- const thresholdsArr = thresholds
+ thresholdsModelOptionsMap[variable][model] = thresholds
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (let j = 0; j < thresholdsArr.length; j += 1) {
- thresholdsArr[j] = thresholdsArr[j].replace(/'|\[|\]/g, "");
- }
- thresholdsModelOptionsMap[variables[didx]][model] = thresholdsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (threshold) {
+ return threshold.replace(/'|\[|\]/g, "");
+ });
const { kernels } = rows[i];
- const kernelArr = kernels
+ kernelModelOptionsMap[variable][model] = kernels
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (let j = 0; j < kernelArr.length; j += 1) {
- kernelArr[j] = kernelArr[j].replace(/'|\[|\]/g, "");
- }
- kernelModelOptionsMap[variables[didx]][model] = kernelArr;
- allKernels = _.union(allKernels, kernelArr);
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (kernel) {
+ return kernel.replace(/'|\[|\]/g, "");
+ });
+ allKernels = _.union(allKernels, kernelModelOptionsMap[variable][model]);
const { radii } = rows[i];
- const radiusArr = radii
+ radiusModelOptionsMap[variable][model] = radii
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (let j = 0; j < radiusArr.length; j += 1) {
- radiusArr[j] = radiusArr[j].replace(/'|\[|\]/g, "");
- }
- radiusModelOptionsMap[variables[didx]][model] = radiusArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (radius) {
+ return radius.replace(/'|\[|\]/g, "");
+ });
const { regions } = rows[i];
- const regionsArrRaw = regions
+ regionModelOptionsMap[variable][model] = regions
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const regionsArr = [];
- let dummyRegion;
- for (let j = 0; j < regionsArrRaw.length; j += 1) {
- dummyRegion = regionsArrRaw[j].replace(/'|\[|\]/g, "");
- regionsArr.push(masterRegionValuesMap[dummyRegion]);
- }
- regionModelOptionsMap[variables[didx]][model] = regionsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (region) {
+ return allRegionValuesMap[region.replace(/'|\[|\]/g, "")];
+ });
}
}
} catch (err) {
throw new Error(err.message);
}
+
if (matsCollections.label.findOne({ name: "label" }) === undefined) {
matsCollections.label.insert({
name: "label",
@@ -559,7 +545,7 @@ const doCurveParams = function () {
regionModelOptionsMap[variables[0]][
Object.keys(regionModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -577,7 +563,7 @@ const doCurveParams = function () {
const currentParam = matsCollections.region.findOne({ name: "region" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, regionModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterRegionValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allRegionValuesMap)
) {
// have to reload region data
matsCollections.region.update(
@@ -585,7 +571,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: regionModelOptionsMap,
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
options:
regionModelOptionsMap[variables[0]][
Object.keys(regionModelOptionsMap[variables[0]])[0]
@@ -1103,7 +1089,7 @@ const doCurveParams = function () {
const probBinOptionsMap = {
0: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
};
- for (didx = 0; didx < allKernels.length; didx += 1) {
+ for (let didx = 0; didx < allKernels.length; didx += 1) {
probBinOptionsMap[allKernels[didx]] = [
"0",
"10",
@@ -1672,6 +1658,7 @@ const doPlotGraph = function () {
Meteor.startup(function () {
matsCollections.Databases.remove({});
if (matsCollections.Databases.find({}).count() < 0) {
+ // eslint-disable-next-line no-console
console.warn(
"main startup: corrupted Databases collection: dropping Databases collection"
);
@@ -1716,6 +1703,7 @@ Meteor.startup(function () {
);
if (cbConnection) {
// global cbScorecardSettingsPool
+ // eslint-disable-next-line no-undef
cbScorecardSettingsPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1742,6 +1730,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (metadataSettings) {
+ // eslint-disable-next-line no-undef
metadataPool = mysql.createPool(metadataSettings);
allPools.push({ pool: "metadataPool", role: matsTypes.DatabaseRoles.META_DATA });
}
@@ -1762,6 +1751,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (sumSettings) {
+ // eslint-disable-next-line no-undef
sumPool = mysql.createPool(sumSettings);
allPools.push({ pool: "sumPool", role: matsTypes.DatabaseRoles.SUMS_DATA });
}
@@ -1790,6 +1780,7 @@ Meteor.startup(function () {
// These are application specific mongo data - like curve params
// The appSpecificResetRoutines object is a special name,
// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way.
+// eslint-disable-next-line no-undef
appSpecificResetRoutines = [
doPlotGraph,
doCurveParams,
diff --git a/apps/landuse/.eslintrc.json b/apps/landuse/.eslintrc.json
index b6823a8810..79d49c5bb6 100644
--- a/apps/landuse/.eslintrc.json
+++ b/apps/landuse/.eslintrc.json
@@ -28,22 +28,6 @@
"space-before-function-paren": "off",
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
- "prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
- "no-undef": "warn",
- "no-plusplus": "warn",
- "vars-on-top": "warn",
- "no-var": "warn",
- "block-scoped-var": "warn",
- "no-loop-func": "warn",
- "no-unused-vars": "warn",
- "no-param-reassign": "warn",
- "camelcase": "warn",
- "no-redeclare": "warn",
- "no-shadow": "warn"
+ "prefer-arrow-callback": "off"
}
}
diff --git a/apps/landuse/client/main.js b/apps/landuse/client/main.js
index a87407a1f4..ecd922b6a2 100644
--- a/apps/landuse/client/main.js
+++ b/apps/landuse/client/main.js
@@ -2,6 +2,7 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+// eslint-disable-next-line no-unused-vars
import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common";
import "@fortawesome/fontawesome-free";
import "@fortawesome/fontawesome-free/css/all.css";
diff --git a/apps/landuse/server/dataFunctions/data_contour.js b/apps/landuse/server/dataFunctions/data_contour.js
index 78bf636a46..0cbc825076 100644
--- a/apps/landuse/server/dataFunctions/data_contour.js
+++ b/apps/landuse/server/dataFunctions/data_contour.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContour = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,60 +23,77 @@ dataContour = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
- const totalProcessingStart = moment();
+
+ const curves = JSON.parse(JSON.stringify(plotParams.curves));
+ if (curves.length > 1) {
+ throw new Error("INFO: There must only be one added curve.");
+ }
+
+ const axisMap = Object.create(null);
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- const curves = JSON.parse(JSON.stringify(plotParams.curves));
- if (curves.length > 1) {
- throw new Error("INFO: There must only be one added curve.");
- }
- const dataset = [];
- const axisMap = Object.create(null);
- // initialize variables specific to the curve
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- const vgtypStr = curve.vgtyp;
- const vgtyp = Object.keys(
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
- ).find(
- (key) =>
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
- );
- const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
- const queryTableClause = `from ${model} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
+
let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.hour IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ `sum(${variable[0]}) as square_diff_sum, sum(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
+ `group_concat(m0.valid_day+3600*m0.hour, ';', ${variable[0]}, ';', ${variable[1]}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variable[0]}) as N0`;
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -86,108 +104,118 @@ dataContour = function (plotParams, plotFunction) {
dateString = "m0.valid_day+3600*m0.hour";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- `sum(${variable[0]}) as square_diff_sum, sum(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
- `group_concat(m0.valid_day+3600*m0.hour, ';', ${variable[0]}, ';', ${variable[1]}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variable[0]}) as N0`;
- const statType = statisticOptionsMap[statisticSelect];
+
+ const vgtypStr = curve.vgtyp;
+ const vgtyp = Object.keys(
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
+ );
+ const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
+
+ const queryTableClause = `from ${model} as m0`;
+
+ // For contours, this functions as the colorbar label.
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
+ const statType = statisticOptionsMap[statisticSelect];
const varUnits = statVarUnitMap[statisticSelect][variableStr];
-
- // For contours, this functions as the colorbar label.
curve.unitKey = varUnits;
let d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{vgtypClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
-
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{vgtypClause}}", vgtypClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- `${statisticSelect}_${variableStr}`
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- if (error.includes("Unknown column")) {
- throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for the model/vgtyp [${model} and ${vgtyp}].`
- );
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{vgtypClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
+
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{vgtypClause}}", vgtypClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ `${statisticSelect}_${variableStr}`
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
+ }
+
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
+ // this is NOT an error just a no data condition
+ dataFoundForCurve = false;
} else {
- throw new Error(error);
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ if (error.includes("Unknown column")) {
+ throw new Error(
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for the model/vgtyp [${model} and ${vgtyp}].`
+ );
+ } else {
+ throw new Error(error);
+ }
}
}
- }
- if (!dataFoundForCurve) {
- // we found no data for any curves so don't bother proceeding
- throw new Error("INFO: No valid data for any curves.");
+ if (!dataFoundForCurve) {
+ // we found no data for any curves so don't bother proceeding
+ throw new Error("INFO: No valid data for any curves.");
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
}
- const postQueryStartMoment = moment();
-
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
diff --git a/apps/landuse/server/dataFunctions/data_contour_diff.js b/apps/landuse/server/dataFunctions/data_contour_diff.js
index e899f00307..2b553c6773 100644
--- a/apps/landuse/server/dataFunctions/data_contour_diff.js
+++ b/apps/landuse/server/dataFunctions/data_contour_diff.js
@@ -14,6 +14,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContourDiff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -24,64 +25,84 @@ dataContourDiff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
let dataNotFoundForAnyCurve = false;
+
+ let curves = JSON.parse(JSON.stringify(plotParams.curves));
+ const curvesLength = curves.length;
+ if (curvesLength !== 2) {
+ throw new Error("INFO: There must be two added curves.");
+ }
+
+ const axisMap = Object.create(null);
const showSignificance = plotParams.significance !== "none";
- const totalProcessingStart = moment();
+
+ let statType;
+ let statisticSelect;
+ let variableStr;
+
+ let statement = "";
+ let error = "";
+ let dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- let curves = JSON.parse(JSON.stringify(plotParams.curves));
- const curvesLength = curves.length;
- if (curvesLength !== 2) {
- throw new Error("INFO: There must be two added curves.");
- }
- let dataset = [];
- const axisMap = Object.create(null);
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var vgtypStr = curve.vgtyp;
- const vgtyp = Object.keys(
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
- ).find(
- (key) =>
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
- );
- const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
- const queryTableClause = `from ${model} as m0`;
- var variableStr = curve.variable;
+
+ variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
+
let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.hour IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ `sum(${variable[0]}) as square_diff_sum, sum(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
+ `group_concat(m0.valid_day+3600*m0.hour, ';', ${variable[0]}, ';', ${variable[1]}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variable[0]}) as N0`;
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -92,104 +113,110 @@ dataContourDiff = function (plotParams, plotFunction) {
dateString = "m0.valid_day+3600*m0.hour";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- var statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- `sum(${variable[0]}) as square_diff_sum, sum(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
- `group_concat(m0.valid_day+3600*m0.hour, ';', ${variable[0]}, ';', ${variable[1]}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
+
+ const vgtypStr = curve.vgtyp;
+ const vgtyp = Object.keys(
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
+ );
+ const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
+ const queryTableClause = `from ${model} as m0`;
+
+ // For contours, this functions as the colorbar label.
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
+ statType = statisticOptionsMap[statisticSelect];
const varUnits = statVarUnitMap[statisticSelect][variableStr];
-
- // For contours, this functions as the colorbar label.
curves[curveIndex].unitKey = varUnits;
- var d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{vgtypClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
+ let d;
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{vgtypClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{vgtypClause}}", vgtypClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{vgtypClause}}", vgtypClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- `${statisticSelect}_${variableStr}`
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- if (error.includes("Unknown column")) {
- throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for the model/vgtyp [${model} and ${vgtyp}].`
- );
- } else {
- throw new Error(error);
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ `${statisticSelect}_${variableStr}`
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
+ }
+
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ if (error.includes("Unknown column")) {
+ throw new Error(
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for the model/vgtyp [${model} and ${vgtyp}].`
+ );
+ } else {
+ throw new Error(error);
+ }
}
+ dataNotFoundForAnyCurve = true;
}
- dataNotFoundForAnyCurve = true;
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
}
- const postQueryStartMoment = moment();
-
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
@@ -238,8 +265,9 @@ dataContourDiff = function (plotParams, plotFunction) {
statType === "ctc",
statType === "scalar"
);
- plotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
- curves = plotParams.curves;
+ const newPlotParams = plotParams;
+ newPlotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
+ curves = newPlotParams.curves;
dataset[0].name = matsPlotUtils.getCurveText(
matsTypes.PlotTypes.contourDiff,
curves[0]
@@ -255,7 +283,7 @@ dataContourDiff = function (plotParams, plotFunction) {
const result = matsDataProcessUtils.processDataContour(
dataset,
curveInfoParams,
- plotParams,
+ newPlotParams,
bookkeepingParams
);
plotFunction(result);
diff --git a/apps/landuse/server/dataFunctions/data_dailymodelcycle.js b/apps/landuse/server/dataFunctions/data_dailymodelcycle.js
index e039e21394..5785c82180 100644
--- a/apps/landuse/server/dataFunctions/data_dailymodelcycle.js
+++ b/apps/landuse/server/dataFunctions/data_dailymodelcycle.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDailyModelCycle = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,47 +24,48 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var vgtypStr = curve.vgtyp;
- const vgtyp = Object.keys(
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
- ).find(
- (key) =>
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
- );
- const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
- const queryTableClause = `from ${model} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
+
if (curve["utc-cycle-start"].length !== 1) {
throw new Error(
"INFO: Please select exactly one UTC Cycle Init Hour for this plot type."
@@ -72,8 +74,9 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
const utcCycleStart = Number(curve["utc-cycle-start"][0]);
utcCycleStarts[curveIndex] = utcCycleStart;
const utcCycleStartClause = `and floor((m0.valid_day+3600*m0.hour - m0.fcst_len*3600)%(24*3600)/3600) IN(${utcCycleStart})`;
+
const forecastLengthClause = "and m0.fcst_len < 24";
- const dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -82,59 +85,72 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
const statisticClause =
`sum(${variable[0]}) as square_diff_sum, sum(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
`group_concat(m0.valid_day+3600*m0.hour, ';', ${variable[0]}, ';', ${variable[1]}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
- const { statVarUnitMap } = matsCollections.variable.findOne(
- { name: "variable" },
- { statVarUnitMap: 1 }
+
+ const dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
+
+ const vgtypStr = curve.vgtyp;
+ const vgtyp = Object.keys(
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
);
- const varUnits = statVarUnitMap[statisticSelect][variableStr];
+ const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
+
+ const queryTableClause = `from ${model} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- const axisKey = varUnits;
+ const { statVarUnitMap } = matsCollections.variable.findOne(
+ { name: "variable" },
+ { statVarUnitMap: 1 }
+ );
+ statType = statisticOptionsMap[statisticSelect];
+ const axisKey = statVarUnitMap[statisticSelect][variableStr];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.valid_day+3600*m0.hour as avtime, " +
- "count(distinct m0.valid_day+3600*m0.hour) as N_times, " +
- "min(m0.valid_day+3600*m0.hour) as min_secs, " +
- "max(m0.valid_day+3600*m0.hour) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{utcCycleStartClause}} " +
- "{{forecastLengthClause}} " +
- "{{vgtypClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{vgtypClause}}", vgtypClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.valid_day+3600*m0.hour as avtime, " +
+ "count(distinct m0.valid_day+3600*m0.hour) as N_times, " +
+ "min(m0.valid_day+3600*m0.hour) as min_secs, " +
+ "max(m0.valid_day+3600*m0.hour) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{utcCycleStartClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{vgtypClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{vgtypClause}}", vgtypClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
`${statisticSelect}_${variableStr}`
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -150,6 +166,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -170,7 +187,6 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -195,6 +211,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/landuse/server/dataFunctions/data_dieoff.js b/apps/landuse/server/dataFunctions/data_dieoff.js
index d136f5ef91..44bcb46045 100644
--- a/apps/landuse/server/dataFunctions/data_dieoff.js
+++ b/apps/landuse/server/dataFunctions/data_dieoff.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDieoff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,58 +24,82 @@ dataDieoff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var vgtypStr = curve.vgtyp;
- const vgtyp = Object.keys(
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
- ).find(
- (key) =>
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
- );
- const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
- const queryTableClause = `from ${model} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
- var validTimes;
+
let validTimeClause = "";
- var utcCycleStart;
+ let validTimes;
+
let utcCycleStartClause = "";
+ let utcCycleStart;
+
const forecastLengthStr = curve["dieoff-type"];
const forecastLengthOptionsMap = matsCollections["dieoff-type"].findOne(
{ name: "dieoff-type" },
{ optionsMap: 1 }
).optionsMap;
const forecastLength = forecastLengthOptionsMap[forecastLengthStr][0];
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ `sum(${variable[0]}) as square_diff_sum, sum(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
+ `group_concat(m0.valid_day+3600*m0.hour, ';', ${variable[0]}, ';', ${variable[1]}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variable[0]}) as N0`;
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
- var dateClause;
+ let dateClause;
+
+ const vgtypStr = curve.vgtyp;
+ const vgtyp = Object.keys(
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
+ );
+ const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
+
+ const queryTableClause = `from ${model} as m0`;
+
if (forecastLength === matsTypes.ForecastTypes.dieoff) {
validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
@@ -91,67 +116,60 @@ dataDieoff = function (plotParams, plotFunction) {
} else {
dateClause = `and m0.valid_day+3600*m0.hour-m0.fcst_len*3600 = ${fromSecs}`;
}
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- `sum(${variable[0]}) as square_diff_sum, sum(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
- `group_concat(m0.valid_day+3600*m0.hour, ';', ${variable[0]}, ';', ${variable[1]}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
+
+ // axisKey is used to determine which axis a curve should use.
+ // This axisKeySet object is used like a set and if a curve has the same
+ // units (axisKey) it will use the same axis.
+ // The axis number is assigned to the axisKeySet value, which is the axisKey.
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
+ statType = statisticOptionsMap[statisticSelect];
const varUnits = statVarUnitMap[statisticSelect][variableStr];
- // axisKey is used to determine which axis a curve should use.
- // This axisKeySet object is used like a set and if a curve has the same
- // units (axisKey) it will use the same axis.
- // The axis number is assigned to the axisKeySet value, which is the axisKey.
const axisKey = varUnits;
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.fcst_len as fcst_lead, " +
- "count(distinct m0.valid_day+3600*m0.hour) as N_times, " +
- "min(m0.valid_day+3600*m0.hour) as min_secs, " +
- "max(m0.valid_day+3600*m0.hour) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{utcCycleStartClause}} " +
- "{{vgtypClause}} " +
- "group by fcst_lead " +
- "order by fcst_lead" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{vgtypClause}}", vgtypClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.fcst_len as fcst_lead, " +
+ "count(distinct m0.valid_day+3600*m0.hour) as N_times, " +
+ "min(m0.valid_day+3600*m0.hour) as min_secs, " +
+ "max(m0.valid_day+3600*m0.hour) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{utcCycleStartClause}} " +
+ "{{vgtypClause}} " +
+ "group by fcst_lead " +
+ "order by fcst_lead" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{vgtypClause}}", vgtypClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
`${statisticSelect}_${variableStr}`
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -167,6 +185,7 @@ dataDieoff = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -187,7 +206,6 @@ dataDieoff = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -212,6 +230,7 @@ dataDieoff = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/landuse/server/dataFunctions/data_histogram.js b/apps/landuse/server/dataFunctions/data_histogram.js
index 0e4760ae0f..c935fc7959 100644
--- a/apps/landuse/server/dataFunctions/data_histogram.js
+++ b/apps/landuse/server/dataFunctions/data_histogram.js
@@ -11,6 +11,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataHistogram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -21,58 +22,56 @@ dataHistogram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
- const alreadyMatched = false;
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
const dataFoundForCurve = [];
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+ const alreadyMatched = false;
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
+
+ const axisMap = Object.create(null);
+ let statType;
+ let varUnits;
+
+ let statement = "";
+ let error = "";
const dataset = [];
const allReturnedSubStats = [];
const allReturnedSubSecs = [];
- const axisMap = Object.create(null);
// process user bin customizations
const binParams = matsDataUtils.setHistogramParameters(plotParams);
const { yAxisFormat } = binParams;
const { binNum } = binParams;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
dataFoundForCurve[curveIndex] = true;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var vgtypStr = curve.vgtyp;
- const vgtyp = Object.keys(
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
- ).find(
- (key) =>
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
- );
- const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
- const queryTableClause = `from ${model} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.hour IN(${validTimes})`;
}
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -81,16 +80,33 @@ dataHistogram = function (plotParams, plotFunction) {
const statisticClause =
`sum(${variable[0]}) as square_diff_sum, sum(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
`group_concat(m0.valid_day+3600*m0.hour, ';', ${variable[0]}, ';', ${variable[1]}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
- const { statVarUnitMap } = matsCollections.variable.findOne(
- { name: "variable" },
- { statVarUnitMap: 1 }
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
+
+ const vgtypStr = curve.vgtyp;
+ const vgtyp = Object.keys(
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
);
- var varUnits = statVarUnitMap[statisticSelect][variableStr];
+ const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
+
+ const queryTableClause = `from ${model} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ const { statVarUnitMap } = matsCollections.variable.findOne(
+ { name: "variable" },
+ { statVarUnitMap: 1 }
+ );
+ statType = statisticOptionsMap[statisticSelect];
+ varUnits = statVarUnitMap[statisticSelect][variableStr];
let axisKey = yAxisFormat;
if (yAxisFormat === "Relative frequency") {
axisKey += " (x100)";
@@ -98,46 +114,46 @@ dataHistogram = function (plotParams, plotFunction) {
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
curves[curveIndex].binNum = binNum; // stash the binNum to use it later for bar chart options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.valid_day+3600*m0.hour as avtime, " +
- "count(distinct m0.valid_day+3600*m0.hour) as N_times, " +
- "min(m0.valid_day+3600*m0.hour) as min_secs, " +
- "max(m0.valid_day+3600*m0.hour) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{vgtypClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{vgtypClause}}", vgtypClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.valid_day+3600*m0.hour as avtime, " +
+ "count(distinct m0.valid_day+3600*m0.hour) as N_times, " +
+ "min(m0.valid_day+3600*m0.hour) as min_secs, " +
+ "max(m0.valid_day+3600*m0.hour) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{vgtypClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{vgtypClause}}", vgtypClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
`${statisticSelect}_${variableStr}`
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -155,6 +171,7 @@ dataHistogram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/landuse/server/dataFunctions/data_series.js b/apps/landuse/server/dataFunctions/data_series.js
index fd9e2cc47f..af291dab86 100644
--- a/apps/landuse/server/dataFunctions/data_series.js
+++ b/apps/landuse/server/dataFunctions/data_series.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSeries = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,41 +24,41 @@ dataSeries = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var vgtypStr = curve.vgtyp;
- const vgtyp = Object.keys(
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
- ).find(
- (key) =>
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
- );
- const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
- const queryTableClause = `from ${model} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
@@ -69,15 +70,10 @@ dataSeries = function (plotParams, plotFunction) {
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.hour IN(${validTimes})`;
}
+
let forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
- const averageStr = curve.average;
- const averageOptionsMap = matsCollections.average.findOne(
- { name: "average" },
- { optionsMap: 1 }
- ).optionsMap;
- const average = averageOptionsMap[averageStr][0];
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -86,60 +82,79 @@ dataSeries = function (plotParams, plotFunction) {
const statisticClause =
`sum(${variable[0]}) as square_diff_sum, sum(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
`group_concat(m0.valid_day+3600*m0.hour, ';', ${variable[0]}, ';', ${variable[1]}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
- const { statVarUnitMap } = matsCollections.variable.findOne(
- { name: "variable" },
- { statVarUnitMap: 1 }
+
+ const averageStr = curve.average;
+ const averageOptionsMap = matsCollections.average.findOne(
+ { name: "average" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const average = averageOptionsMap[averageStr][0];
+
+ const dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
+
+ const vgtypStr = curve.vgtyp;
+ const vgtyp = Object.keys(
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
);
- const varUnits = statVarUnitMap[statisticSelect][variableStr];
+ const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
+
+ const queryTableClause = `from ${model} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ const { statVarUnitMap } = matsCollections.variable.findOne(
+ { name: "variable" },
+ { statVarUnitMap: 1 }
+ );
+ statType = statisticOptionsMap[statisticSelect];
+ const varUnits = statVarUnitMap[statisticSelect][variableStr];
const axisKey = varUnits;
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select {{average}} as avtime, " +
- "count(distinct m0.valid_day+3600*m0.hour) as N_times, " +
- "min(m0.valid_day+3600*m0.hour) as min_secs, " +
- "max(m0.valid_day+3600*m0.hour) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{vgtypClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "select {{average}} as avtime, " +
+ "count(distinct m0.valid_day+3600*m0.hour) as N_times, " +
+ "min(m0.valid_day+3600*m0.hour) as min_secs, " +
+ "max(m0.valid_day+3600*m0.hour) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{vgtypClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
- statement = statement.replace("{{average}}", average);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{vgtypClause}}", vgtypClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
+ statement = statement.replace("{{average}}", average);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{vgtypClause}}", vgtypClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
- // math is done on forecastLength later on -- set all analyses to 0
- if (forecastLength === "-99") {
- forecastLength = "0";
- }
+ // math is done on forecastLength later on -- set all analyses to 0
+ if (forecastLength === "-99") {
+ forecastLength = "0";
+ }
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBTimeSeries(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
model,
forecastLength,
@@ -151,7 +166,9 @@ dataSeries = function (plotParams, plotFunction) {
appParams,
false
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -167,6 +184,7 @@ dataSeries = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -187,7 +205,6 @@ dataSeries = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -212,6 +229,7 @@ dataSeries = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/landuse/server/dataFunctions/data_simple_scatter.js b/apps/landuse/server/dataFunctions/data_simple_scatter.js
index 866874b6fa..a1054b0875 100644
--- a/apps/landuse/server/dataFunctions/data_simple_scatter.js
+++ b/apps/landuse/server/dataFunctions/data_simple_scatter.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSimpleScatter = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,14 +23,15 @@ dataSimpleScatter = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
+
const axisXMap = Object.create(null);
const axisYMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
@@ -37,26 +39,27 @@ dataSimpleScatter = function (plotParams, plotFunction) {
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statType;
+ let varUnitsX;
+ let varUnitsY;
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const binParam = curve["bin-parameter"];
const binClause = matsCollections["bin-parameter"].findOne({
name: "bin-parameter",
}).optionsMap[binParam];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var vgtypStr = curve.vgtyp;
- const vgtyp = Object.keys(
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
- ).find(
- (key) =>
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
- );
- const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
- const queryTableClause = `from ${model} as m0`;
+
const variableXStr = curve["x-variable"];
const variableYStr = curve["y-variable"];
const variableOptionsMap = matsCollections.variable.findOne(
@@ -65,19 +68,16 @@ dataSimpleScatter = function (plotParams, plotFunction) {
).optionsMap;
const variableX = variableOptionsMap[variableXStr];
const variableY = variableOptionsMap[variableYStr];
+
let validTimeClause = "";
- let forecastLengthClause = "";
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let dateString = "";
- let dateClause = "";
if (binParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.hour IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (binParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
if (forecastLength === undefined) {
@@ -87,12 +87,7 @@ dataSimpleScatter = function (plotParams, plotFunction) {
}
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
- if (binParam === "Init Date" && binParam !== "Valid Date") {
- dateString = "m0.valid_day+3600*m0.hour-m0.fcst_len*3600";
- } else {
- dateString = "m0.valid_day+3600*m0.hour";
- }
- dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
+
const statisticXSelect = curve["x-statistic"];
const statisticYSelect = curve["y-statistic"];
const statisticOptionsMap = matsCollections.statistic.findOne(
@@ -103,57 +98,81 @@ dataSimpleScatter = function (plotParams, plotFunction) {
`sum(${variableX[0]}) as square_diff_sumX, sum(${variableX[1]}) as N_sumX, sum(${variableX[2]}) as obs_model_diff_sumX, sum(${variableX[3]}) as model_sumX, sum(${variableX[4]}) as obs_sumX, sum(${variableX[5]}) as abs_sumX, ` +
`sum(${variableY[0]}) as square_diff_sumY, sum(${variableY[1]}) as N_sumY, sum(${variableY[2]}) as obs_model_diff_sumY, sum(${variableY[3]}) as model_sumY, sum(${variableY[4]}) as obs_sumY, sum(${variableY[5]}) as abs_sumY, ` +
`group_concat(m0.valid_day+3600*m0.hour, ';', ${variableX[0]}, ';', ${variableX[1]}, ';', ${variableX[2]}, ';', ${variableX[3]}, ';', ${variableX[4]}, ';', ${variableX[5]}, ';', ${variableY[0]}, ';', ${variableY[1]}, ';', ${variableY[2]}, ';', ${variableY[3]}, ';', ${variableY[4]}, ';', ${variableY[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variableX[0]}) as N0`;
- var statType = statisticOptionsMap[statisticXSelect];
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ let dateString = "";
+ let dateClause = "";
+ if (binParam === "Init Date" && binParam !== "Valid Date") {
+ dateString = "m0.valid_day+3600*m0.hour-m0.fcst_len*3600";
+ } else {
+ dateString = "m0.valid_day+3600*m0.hour";
+ }
+ dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
+
+ const vgtypStr = curve.vgtyp;
+ const vgtyp = Object.keys(
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
+ );
+ const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
+
+ const queryTableClause = `from ${model} as m0`;
+
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
- const varUnitsX = statVarUnitMap[statisticXSelect][variableXStr];
- const varUnitsY = statVarUnitMap[statisticYSelect][variableYStr];
+ statType = statisticOptionsMap[statisticXSelect];
+ varUnitsX = statVarUnitMap[statisticXSelect][variableXStr];
+ varUnitsY = statVarUnitMap[statisticYSelect][variableYStr];
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{binClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{vgtypClause}} " +
- "group by binVal " +
- "order by binVal" +
- ";";
-
- statement = statement.replace("{{binClause}}", binClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{vgtypClause}}", vgtypClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "{{binClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{vgtypClause}} " +
+ "group by binVal " +
+ "order by binVal" +
+ ";";
+
+ statement = statement.replace("{{binClause}}", binClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{vgtypClause}}", vgtypClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSimpleScatter(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
`${statisticXSelect}_${variableXStr}`,
`${statisticYSelect}_${variableYStr}`
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -169,6 +188,7 @@ dataSimpleScatter = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -189,7 +209,6 @@ dataSimpleScatter = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -197,7 +216,7 @@ dataSimpleScatter = function (plotParams, plotFunction) {
ymax = ymax > d.ymax ? ymax : d.ymax;
}
} else {
- // this is a difference curve -- not supported for ROC plots
+ // this is a difference curve -- not supported for scatter plots
throw new Error(
"INFO: Difference curves are not supported for performance diagrams, as they do not feature consistent x or y values across all curves."
);
@@ -205,6 +224,7 @@ dataSimpleScatter = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/landuse/server/dataFunctions/data_validtime.js b/apps/landuse/server/dataFunctions/data_validtime.js
index 63309bef5b..3cdf1eaa96 100644
--- a/apps/landuse/server/dataFunctions/data_validtime.js
+++ b/apps/landuse/server/dataFunctions/data_validtime.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataValidTime = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,50 +24,47 @@ dataValidTime = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var vgtypStr = curve.vgtyp;
- const vgtyp = Object.keys(
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
- ).find(
- (key) =>
- matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
- );
- const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
- const queryTableClause = `from ${model} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -75,57 +73,74 @@ dataValidTime = function (plotParams, plotFunction) {
const statisticClause =
`sum(${variable[0]}) as square_diff_sum, sum(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
`group_concat(m0.valid_day+3600*m0.hour, ';', ${variable[0]}, ';', ${variable[1]}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
- const { statVarUnitMap } = matsCollections.variable.findOne(
- { name: "variable" },
- { statVarUnitMap: 1 }
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
+
+ const vgtypStr = curve.vgtyp;
+ const vgtyp = Object.keys(
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.vgtyp.findOne({ name: "vgtyp" }).valuesMap[key] === vgtypStr
);
- const varUnits = statVarUnitMap[statisticSelect][variableStr];
+ const vgtypClause = `and m0.vgtyp IN(${vgtyp})`;
+
+ const queryTableClause = `from ${model} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ const { statVarUnitMap } = matsCollections.variable.findOne(
+ { name: "variable" },
+ { statVarUnitMap: 1 }
+ );
+ statType = statisticOptionsMap[statisticSelect];
+ const varUnits = statVarUnitMap[statisticSelect][variableStr];
const axisKey = varUnits;
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.hour as hr_of_day, " +
- "count(distinct m0.valid_day+3600*m0.hour) as N_times, " +
- "min(m0.valid_day+3600*m0.hour) as min_secs, " +
- "max(m0.valid_day+3600*m0.hour) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{forecastLengthClause}} " +
- "{{vgtypClause}} " +
- "group by hr_of_day " +
- "order by hr_of_day" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{vgtypClause}}", vgtypClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.hour as hr_of_day, " +
+ "count(distinct m0.valid_day+3600*m0.hour) as N_times, " +
+ "min(m0.valid_day+3600*m0.hour) as min_secs, " +
+ "max(m0.valid_day+3600*m0.hour) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{vgtypClause}} " +
+ "group by hr_of_day " +
+ "order by hr_of_day" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{vgtypClause}}", vgtypClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
`${statisticSelect}_${variableStr}`
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -141,6 +156,7 @@ dataValidTime = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -161,7 +177,6 @@ dataValidTime = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -186,6 +201,7 @@ dataValidTime = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/landuse/server/main.js b/apps/landuse/server/main.js
index 1794482693..da195324ed 100644
--- a/apps/landuse/server/main.js
+++ b/apps/landuse/server/main.js
@@ -4,7 +4,9 @@
import { Meteor } from "meteor/meteor";
import { mysql } from "meteor/pcel:mysql";
+import { moment } from "meteor/momentjs:moment";
import {
+ matsMethods,
matsTypes,
matsCollections,
matsDataUtils,
@@ -319,71 +321,64 @@ const doCurveParams = function () {
const params = matsCollections.CurveParamsInfo.find({
curve_params: { $exists: true },
}).fetch()[0].curve_params;
- for (let cp = 0; cp < params.length; cp++) {
+ for (let cp = 0; cp < params.length; cp += 1) {
matsCollections[params[cp]].remove({});
}
}
+
const modelOptionsMap = {};
let modelDateRangeMap = {};
const forecastLengthOptionsMap = {};
const vgtypsModelOptionsMap = {};
- const masterVgtypValuesMap = {};
+ const allVgtypValuesMap = {};
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select vgtyp,description from vgtyp_descriptions;"
);
- let masterDescription;
- let masterVgtyp;
- for (var j = 0; j < rows.length; j++) {
- masterDescription = rows[j].description.trim();
- masterVgtyp = rows[j].vgtyp.trim();
- masterVgtypValuesMap[masterVgtyp] = masterDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allVgtypValuesMap[rows[j].vgtyp.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select model,display_text,fcst_lens,vgtyp,mindate,maxdate from regions_per_model_mats_all_categories order by display_category, display_order;"
);
- for (let i = 0; i < rows.length; i++) {
- const model_value = rows[i].model.trim();
+ for (let i = 0; i < rows.length; i += 1) {
+ const modelValue = rows[i].model.trim();
const model = rows[i].display_text.trim();
- modelOptionsMap[model] = [model_value];
+ modelOptionsMap[model] = [modelValue];
const rowMinDate = moment.utc(rows[i].mindate * 1000).format("MM/DD/YYYY HH:mm");
const rowMaxDate = moment.utc(rows[i].maxdate * 1000).format("MM/DD/YYYY HH:mm");
- modelDateRangeMap[model] = { minDate: rowMinDate, maxDate: rowMaxDate };
+ modelDateRangeMap[model] = {
+ minDate: rowMinDate,
+ maxDate: rowMaxDate,
+ };
const forecastLengths = rows[i].fcst_lens;
- const forecastLengthArr = forecastLengths
+ forecastLengthOptionsMap[model] = forecastLengths
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (var j = 0; j < forecastLengthArr.length; j++) {
- forecastLengthArr[j] = forecastLengthArr[j].replace(/'|\[|\]/g, "");
- }
- forecastLengthOptionsMap[model] = forecastLengthArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (fhr) {
+ return fhr.replace(/'|\[|\]/g, "");
+ });
const vgtyps = rows[i].vgtyp;
- const vgtypsArrRaw = vgtyps
+ vgtypsModelOptionsMap[model] = vgtyps
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const vgtypsArr = [];
- var dummyVgtyp;
- for (var j = 0; j < vgtypsArrRaw.length; j++) {
- dummyVgtyp = vgtypsArrRaw[j].replace(/'|\[|\]/g, "");
- if (dummyVgtyp !== "0") {
- vgtypsArr.push(masterVgtypValuesMap[dummyVgtyp]);
- }
- }
- vgtypsModelOptionsMap[model] = vgtypsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (vgtyp) {
+ return allVgtypValuesMap[vgtyp.replace(/'|\[|\]/g, "")];
+ });
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
if (matsCollections.label.findOne({ name: "label" }) === undefined) {
@@ -421,7 +416,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["data-source"].findOne({ name: "data-source" });
+ const currentParam = matsCollections["data-source"].findOne({
+ name: "data-source",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap) ||
!matsDataUtils.areObjectsEqual(currentParam.dates, modelDateRangeMap)
@@ -447,7 +444,7 @@ const doCurveParams = function () {
type: matsTypes.InputTypes.select,
optionsMap: vgtypsModelOptionsMap,
options: vgtypsModelOptionsMap[Object.keys(vgtypsModelOptionsMap)[0]],
- valuesMap: masterVgtypValuesMap,
+ valuesMap: allVgtypValuesMap,
superiorNames: ["data-source"],
controlButtonCovered: true,
unique: false,
@@ -460,10 +457,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.vgtyp.findOne({ name: "vgtyp" });
+ const currentParam = matsCollections.region.findOne({ name: "vgtyp" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, vgtypsModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterVgtypValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allVgtypValuesMap)
) {
// have to reload vgtyp data
matsCollections.vgtyp.update(
@@ -471,7 +468,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: vgtypsModelOptionsMap,
- valuesMap: masterVgtypValuesMap,
+ valuesMap: allVgtypValuesMap,
options: vgtypsModelOptionsMap[Object.keys(vgtypsModelOptionsMap)[0]],
default: vgtypsModelOptionsMap[Object.keys(vgtypsModelOptionsMap)[0]][0],
},
@@ -480,7 +477,7 @@ const doCurveParams = function () {
}
}
- const optionsMap = {
+ const statOptionsMap = {
RMSE: "scalar",
"Bias (Model - Obs)": "scalar",
@@ -500,11 +497,11 @@ const doCurveParams = function () {
matsCollections.statistic.insert({
name: "statistic",
type: matsTypes.InputTypes.select,
- optionsMap,
- options: Object.keys(optionsMap),
+ optionsMap: statOptionsMap,
+ options: Object.keys(statOptionsMap),
controlButtonCovered: true,
unique: false,
- default: Object.keys(optionsMap)[0],
+ default: Object.keys(statOptionsMap)[0],
controlButtonVisibility: "block",
displayOrder: 1,
displayPriority: 1,
@@ -516,11 +513,11 @@ const doCurveParams = function () {
matsCollections["x-statistic"].insert({
name: "x-statistic",
type: matsTypes.InputTypes.select,
- optionsMap,
- options: Object.keys(optionsMap),
+ optionsMap: statOptionsMap,
+ options: Object.keys(statOptionsMap),
controlButtonCovered: true,
unique: false,
- default: Object.keys(optionsMap)[0],
+ default: Object.keys(statOptionsMap)[0],
controlButtonVisibility: "block",
displayOrder: 3,
displayPriority: 1,
@@ -532,11 +529,11 @@ const doCurveParams = function () {
matsCollections["y-statistic"].insert({
name: "y-statistic",
type: matsTypes.InputTypes.select,
- optionsMap,
- options: Object.keys(optionsMap),
+ optionsMap: statOptionsMap,
+ options: Object.keys(statOptionsMap),
controlButtonCovered: true,
unique: false,
- default: Object.keys(optionsMap)[0],
+ default: Object.keys(statOptionsMap)[0],
controlButtonVisibility: "block",
displayOrder: 1,
displayPriority: 1,
@@ -704,7 +701,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["forecast-length"].findOne({
+ const currentParam = matsCollections["forecast-length"].findOne({
name: "forecast-length",
});
if (
@@ -998,7 +995,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["curve-dates"].findOne({ name: "curve-dates" });
+ const currentParam = matsCollections["curve-dates"].findOne({
+ name: "curve-dates",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.startDate, minDate) ||
!matsDataUtils.areObjectsEqual(currentParam.stopDate, maxDate) ||
@@ -1303,7 +1302,8 @@ const doPlotGraph = function () {
Meteor.startup(function () {
matsCollections.Databases.remove({});
if (matsCollections.Databases.find({}).count() < 0) {
- console.log(
+ // eslint-disable-next-line no-console
+ console.warn(
"main startup: corrupted Databases collection: dropping Databases collection"
);
matsCollections.Databases.drop();
@@ -1320,7 +1320,7 @@ Meteor.startup(function () {
databases = Meteor.settings.private.databases;
}
if (databases !== null && databases !== undefined && Array.isArray(databases)) {
- for (let di = 0; di < databases.length; di++) {
+ for (let di = 0; di < databases.length; di += 1) {
matsCollections.Databases.insert(databases[di]);
}
}
@@ -1347,6 +1347,7 @@ Meteor.startup(function () {
);
if (cbConnection) {
// global cbScorecardSettingsPool
+ // eslint-disable-next-line no-undef
cbScorecardSettingsPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1373,6 +1374,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (sumSettings) {
+ // eslint-disable-next-line no-undef
sumPool = mysql.createPool(sumSettings);
allPools.push({ pool: "sumPool", role: matsTypes.DatabaseRoles.SUMS_DATA });
}
@@ -1389,7 +1391,7 @@ Meteor.startup(function () {
appType: matsTypes.AppTypes.mats,
});
} catch (error) {
- console.log(error.message);
+ throw new Error(error.message);
}
});
@@ -1397,6 +1399,7 @@ Meteor.startup(function () {
// These are application specific mongo data - like curve params
// The appSpecificResetRoutines object is a special name,
// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way.
+// eslint-disable-next-line no-undef
appSpecificResetRoutines = [
doPlotGraph,
doCurveParams,
diff --git a/apps/precipAccum/.eslintrc.json b/apps/precipAccum/.eslintrc.json
index 8b795b7df7..79d49c5bb6 100644
--- a/apps/precipAccum/.eslintrc.json
+++ b/apps/precipAccum/.eslintrc.json
@@ -28,22 +28,6 @@
"space-before-function-paren": "off",
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
- "prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
- "no-undef": "warn",
- "no-plusplus": "warn",
- "vars-on-top": "warn",
- "no-var": "warn",
- "block-scoped-var": "warn",
- "no-loop-func": "warn",
- "no-unused-vars": "warn",
- "prefer-destructuring": "warn",
- "no-param-reassign": "warn",
- "camelcase": "warn",
- "no-redeclare": "warn"
+ "prefer-arrow-callback": "off"
}
}
diff --git a/apps/precipAccum/client/main.js b/apps/precipAccum/client/main.js
index a87407a1f4..ecd922b6a2 100644
--- a/apps/precipAccum/client/main.js
+++ b/apps/precipAccum/client/main.js
@@ -2,6 +2,7 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+// eslint-disable-next-line no-unused-vars
import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common";
import "@fortawesome/fontawesome-free";
import "@fortawesome/fontawesome-free/css/all.css";
diff --git a/apps/precipAccum/server/dataFunctions/data_contour.js b/apps/precipAccum/server/dataFunctions/data_contour.js
index d47b9547f6..c95df32b35 100644
--- a/apps/precipAccum/server/dataFunctions/data_contour.js
+++ b/apps/precipAccum/server/dataFunctions/data_contour.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContour = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,56 +23,53 @@ dataContour = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
- const totalProcessingStart = moment();
+
+ const curves = JSON.parse(JSON.stringify(plotParams.curves));
+ if (curves.length > 1) {
+ throw new Error("INFO: There must only be one added curve.");
+ }
+
+ const axisMap = Object.create(null);
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- const curves = JSON.parse(JSON.stringify(plotParams.curves));
- if (curves.length > 1) {
- throw new Error("INFO: There must only be one added curve.");
- }
- const dataset = [];
- const axisMap = Object.create(null);
- // initialize variables specific to the curve
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" }).optionsMap[
variable
];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- const regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
- scaleStr
- );
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
+
let thresholdClause = "";
- const forecastLength = 0; // precip apps have no forecast length, but the query and matching algorithms still need it passed in.
- let dateClause = "";
if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") {
const thresholdStr = curve.threshold;
+ if (thresholdStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s threshold is undefined. Please assign it a value.`
+ );
+ }
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -82,6 +80,17 @@ dataContour = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold * 0.01}`;
}
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
+ scaleStr
+ );
+
+ let forecastTypeClause;
const forecastTypeStr = curve["forecast-type"];
const forecastType = Object.keys(
matsCollections["forecast-type"].findOne({ name: "forecast-type" }).valuesMap[
@@ -93,13 +102,12 @@ dataContour = function (plotParams, plotFunction) {
variable
][key] === forecastTypeStr
);
- let forecastTypeClause;
if (databaseRef === "precip") {
forecastTypeClause = `and m0.num_fcsts = ${forecastType}`;
} else {
forecastTypeClause = `and m0.accum_len = ${forecastType}`;
}
- dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -107,85 +115,104 @@ dataContour = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
// For contours, this functions as the colorbar label.
const statType = statisticOptionsMap[statisticSelect][0];
- curve.unitKey = statisticOptionsMap[statisticSelect][1];
+ [, curve.unitKey] = statisticOptionsMap[statisticSelect];
let d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{forecastTypeClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
-
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{forecastTypeClause}}", forecastTypeClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastTypeClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
+
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{forecastTypeClause}}", forecastTypeClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
- }
- if (!dataFoundForCurve) {
- // we found no data for any curves so don't bother proceeding
- throw new Error("INFO: No valid data for any curves.");
- }
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
+ // this is NOT an error just a no data condition
+ dataFoundForCurve = false;
+ } else {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ }
- const postQueryStartMoment = moment();
+ if (!dataFoundForCurve) {
+ // we found no data for any curves so don't bother proceeding
+ throw new Error("INFO: No valid data for any curves.");
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
+ }
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
diff --git a/apps/precipAccum/server/dataFunctions/data_contour_diff.js b/apps/precipAccum/server/dataFunctions/data_contour_diff.js
index 4732fc299c..ce2b0e3a75 100644
--- a/apps/precipAccum/server/dataFunctions/data_contour_diff.js
+++ b/apps/precipAccum/server/dataFunctions/data_contour_diff.js
@@ -14,6 +14,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContourDiff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -24,59 +25,58 @@ dataContourDiff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
let dataNotFoundForAnyCurve = false;
+
+ let curves = JSON.parse(JSON.stringify(plotParams.curves));
+ const curvesLength = curves.length;
+ if (curvesLength !== 2) {
+ throw new Error("INFO: There must be two added curves.");
+ }
+
+ const axisMap = Object.create(null);
const showSignificance = plotParams.significance !== "none";
- const totalProcessingStart = moment();
+
+ let statType;
+ let statisticSelect;
+
+ let statement = "";
+ let error = "";
+ let dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- let curves = JSON.parse(JSON.stringify(plotParams.curves));
- const curvesLength = curves.length;
- if (curvesLength !== 2) {
- throw new Error("INFO: There must be two added curves.");
- }
- let dataset = [];
- const axisMap = Object.create(null);
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
- scaleStr
- );
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
+
let thresholdClause = "";
- const forecastLength = 0; // precip apps have no forecast length, but the query and matching algorithms still need it passed in.
- let dateClause = "";
if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") {
- var thresholdStr = curve.threshold;
+ const thresholdStr = curve.threshold;
+ if (thresholdStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s threshold is undefined. Please assign it a value.`
+ );
+ }
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -87,7 +87,18 @@ dataContourDiff = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold * 0.01}`;
}
- var forecastTypeStr = curve["forecast-type"];
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
+ scaleStr
+ );
+
+ let forecastTypeClause;
+ const forecastTypeStr = curve["forecast-type"];
const forecastType = Object.keys(
matsCollections["forecast-type"].findOne({ name: "forecast-type" }).valuesMap[
variable
@@ -98,95 +109,110 @@ dataContourDiff = function (plotParams, plotFunction) {
variable
][key] === forecastTypeStr
);
- var forecastTypeClause;
if (databaseRef === "precip") {
forecastTypeClause = `and m0.num_fcsts = ${forecastType}`;
} else {
forecastTypeClause = `and m0.accum_len = ${forecastType}`;
}
- dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
- var statisticSelect = curve.statistic;
+
+ statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
// For contours, this functions as the colorbar label.
- var statType = statisticOptionsMap[statisticSelect][0];
- curves[curveIndex].unitKey = statisticOptionsMap[statisticSelect][1];
+ [statType] = statisticOptionsMap[statisticSelect];
+ [, curve.unitKey] = statisticOptionsMap[statisticSelect];
- var d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{forecastTypeClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
+ let d;
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastTypeClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{forecastTypeClause}}", forecastTypeClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{forecastTypeClause}}", forecastTypeClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
- dataNotFoundForAnyCurve = true;
- }
- const postQueryStartMoment = moment();
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ dataNotFoundForAnyCurve = true;
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
+ }
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
@@ -235,8 +261,9 @@ dataContourDiff = function (plotParams, plotFunction) {
statType === "ctc",
statType === "scalar"
);
- plotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
- curves = plotParams.curves;
+ const newPlotParams = plotParams;
+ newPlotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
+ curves = newPlotParams.curves;
dataset[0].name = matsPlotUtils.getCurveText(
matsTypes.PlotTypes.contourDiff,
curves[0]
@@ -252,7 +279,7 @@ dataContourDiff = function (plotParams, plotFunction) {
const result = matsDataProcessUtils.processDataContour(
dataset,
curveInfoParams,
- plotParams,
+ newPlotParams,
bookkeepingParams
);
plotFunction(result);
diff --git a/apps/precipAccum/server/dataFunctions/data_histogram.js b/apps/precipAccum/server/dataFunctions/data_histogram.js
index 63f76437a5..f3f9273559 100644
--- a/apps/precipAccum/server/dataFunctions/data_histogram.js
+++ b/apps/precipAccum/server/dataFunctions/data_histogram.js
@@ -11,6 +11,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataHistogram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -21,52 +22,45 @@ dataHistogram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
- const alreadyMatched = false;
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
const dataFoundForCurve = [];
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+ const alreadyMatched = false;
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
+
+ const axisMap = Object.create(null);
+ let statType;
+ let varUnits;
+
+ let statement = "";
+ let error = "";
const dataset = [];
const allReturnedSubStats = [];
const allReturnedSubSecs = [];
- const axisMap = Object.create(null);
// process user bin customizations
const binParams = matsDataUtils.setHistogramParameters(plotParams);
const { yAxisFormat } = binParams;
const { binNum } = binParams;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
dataFoundForCurve[curveIndex] = true;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
- scaleStr
- );
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -76,8 +70,18 @@ dataHistogram = function (plotParams, plotFunction) {
] === thresholdStr
);
const thresholdClause = `and m0.trsh = ${threshold * 0.01}`;
- const forecastLength = 0; // precip apps have no forecast length, but the query and matching algorithms still need it passed in.
- var forecastTypeStr = curve["forecast-type"];
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
+ scaleStr
+ );
+
+ let forecastTypeClause;
+ const forecastTypeStr = curve["forecast-type"];
const forecastType = Object.keys(
matsCollections["forecast-type"].findOne({ name: "forecast-type" }).valuesMap[
variable
@@ -88,16 +92,12 @@ dataHistogram = function (plotParams, plotFunction) {
variable
][key] === forecastTypeStr
);
- var forecastTypeClause;
if (databaseRef === "precip") {
forecastTypeClause = `and m0.num_fcsts = ${forecastType}`;
} else {
forecastTypeClause = `and m0.accum_len = ${forecastType}`;
}
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -105,12 +105,27 @@ dataHistogram = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
- var varUnits = statisticOptionsMap[statisticSelect][1];
+ [statType] = statisticOptionsMap[statisticSelect];
+ [, varUnits] = statisticOptionsMap[statisticSelect];
let axisKey = yAxisFormat;
if (yAxisFormat === "Relative frequency") {
axisKey += " (x100)";
@@ -118,44 +133,44 @@ dataHistogram = function (plotParams, plotFunction) {
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
curves[curveIndex].binNum = binNum; // stash the binNum to use it later for bar chart options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.time as avtime, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{forecastTypeClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{forecastTypeClause}}", forecastTypeClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.time as avtime, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastTypeClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{forecastTypeClause}}", forecastTypeClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -173,6 +188,7 @@ dataHistogram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/precipAccum/server/dataFunctions/data_perfDiagram.js b/apps/precipAccum/server/dataFunctions/data_perfDiagram.js
index 057d743bea..4530b50dc3 100644
--- a/apps/precipAccum/server/dataFunctions/data_perfDiagram.js
+++ b/apps/precipAccum/server/dataFunctions/data_perfDiagram.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataPerformanceDiagram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,57 +23,47 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statType;
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const binParam = curve["bin-parameter"];
const binClause = matsCollections["bin-parameter"].findOne({
name: "bin-parameter",
}).optionsMap[binParam];
- var { variable } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
- scaleStr
- );
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
+
let thresholdClause = "";
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let dateClause = "";
if (binParam !== "Threshold") {
- var thresholdStr = curve.threshold;
+ const thresholdStr = curve.threshold;
if (thresholdStr === undefined) {
throw new Error(
`INFO: ${label}'s threshold is undefined. Please assign it a value.`
@@ -88,7 +79,18 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold * 0.01}`;
}
- var forecastTypeStr = curve["forecast-type"];
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
+ scaleStr
+ );
+
+ let forecastTypeClause;
+ const forecastTypeStr = curve["forecast-type"];
const forecastType = Object.keys(
matsCollections["forecast-type"].findOne({ name: "forecast-type" }).valuesMap[
variable
@@ -99,60 +101,74 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
variable
][key] === forecastTypeStr
);
- var forecastTypeClause;
if (databaseRef === "precip") {
forecastTypeClause = `and m0.num_fcsts = ${forecastType}`;
} else {
forecastTypeClause = `and m0.accum_len = ${forecastType}`;
}
- dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
const statisticSelect = "PerformanceDiagram";
- var statType = "ctc";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// variable + statistic (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ statType = "ctc";
curves[curveIndex].axisKey = statisticSelect; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{binClause}} " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "((sum(m0.yy)+0.00)/sum(m0.yy+m0.yn)) as pod, ((sum(m0.ny)+0.00)/sum(m0.ny+m0.yy)) as far, " +
- "sum(m0.yy+m0.yn) as oy_all, sum(m0.ny+m0.nn) as on_all, group_concat(m0.time, ';', m0.yy, ';', " +
- "m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0 " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{forecastTypeClause}} " +
- "group by binVal " +
- "order by binVal" +
- ";";
-
- statement = statement.replace("{{binClause}}", binClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{forecastTypeClause}}", forecastTypeClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "{{binClause}} " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "((sum(m0.yy)+0.00)/sum(m0.yy+m0.yn)) as pod, ((sum(m0.ny)+0.00)/sum(m0.ny+m0.yy)) as far, " +
+ "sum(m0.yy+m0.yn) as oy_all, sum(m0.ny+m0.nn) as on_all, group_concat(m0.time, ';', m0.yy, ';', " +
+ "m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0 " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastTypeClause}} " +
+ "group by binVal " +
+ "order by binVal" +
+ ";";
+
+ statement = statement.replace("{{binClause}}", binClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{forecastTypeClause}}", forecastTypeClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBPerformanceDiagram(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -168,6 +184,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -189,7 +206,6 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -197,7 +213,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
ymax = ymax > d.ymax ? ymax : d.ymax;
}
} else {
- // this is a difference curve -- not supported for ROC plots
+ // this is a difference curve -- not supported for performance diagrams
throw new Error(
"INFO: Difference curves are not supported for performance diagrams, as they do not feature consistent x or y values across all curves."
);
@@ -205,6 +221,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipAccum/server/dataFunctions/data_series.js b/apps/precipAccum/server/dataFunctions/data_series.js
index a62f0a21d7..ecf33d1aad 100644
--- a/apps/precipAccum/server/dataFunctions/data_series.js
+++ b/apps/precipAccum/server/dataFunctions/data_series.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSeries = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,52 +24,46 @@ dataSeries = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
- scaleStr
- );
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -78,8 +73,19 @@ dataSeries = function (plotParams, plotFunction) {
] === thresholdStr
);
const thresholdClause = `and m0.trsh = ${threshold * 0.01}`;
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
+ scaleStr
+ );
+
const forecastLength = 0; // precip apps have no forecast length, but the query and matching algorithms still need it passed in.
- var forecastTypeStr = curve["forecast-type"];
+ let forecastTypeClause;
+ const forecastTypeStr = curve["forecast-type"];
const forecastType = Object.keys(
matsCollections["forecast-type"].findOne({ name: "forecast-type" }).valuesMap[
variable
@@ -90,19 +96,12 @@ dataSeries = function (plotParams, plotFunction) {
variable
][key] === forecastTypeStr
);
- var forecastTypeClause;
if (databaseRef === "precip") {
forecastTypeClause = `and m0.num_fcsts = ${forecastType}`;
} else {
forecastTypeClause = `and m0.accum_len = ${forecastType}`;
}
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
- const averageStr = curve.average;
- const averageOptionsMap = matsCollections.average.findOne(
- { name: "average" },
- { optionsMap: 1 }
- ).optionsMap;
- const average = averageOptionsMap[averageStr][0];
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -110,11 +109,30 @@ dataSeries = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const averageStr = curve.average;
+ const averageOptionsMap = matsCollections.average.findOne(
+ { name: "average" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const average = averageOptionsMap[averageStr][0];
+
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -122,40 +140,38 @@ dataSeries = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select {{average}} as avtime, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{forecastTypeClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{average}}", average);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{forecastTypeClause}}", forecastTypeClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select {{average}} as avtime, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastTypeClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{average}}", average);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{forecastTypeClause}}", forecastTypeClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBTimeSeries(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
model,
forecastLength,
@@ -167,7 +183,9 @@ dataSeries = function (plotParams, plotFunction) {
appParams,
false
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -183,6 +201,7 @@ dataSeries = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -197,7 +216,6 @@ dataSeries = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -222,6 +240,7 @@ dataSeries = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipAccum/server/dataFunctions/data_threshold.js b/apps/precipAccum/server/dataFunctions/data_threshold.js
index a3042c78ef..a0a75f16bf 100644
--- a/apps/precipAccum/server/dataFunctions/data_threshold.js
+++ b/apps/precipAccum/server/dataFunctions/data_threshold.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataThreshold = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,51 +24,51 @@ dataThreshold = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
).find(
(key) =>
matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
scaleStr
);
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
- const thresholdClause = "";
- const forecastLength = 0; // precip apps have no forecast length, but the query and matching algorithms still need it passed in.
- var forecastTypeStr = curve["forecast-type"];
+
+ let forecastTypeClause;
+ const forecastTypeStr = curve["forecast-type"];
const forecastType = Object.keys(
matsCollections["forecast-type"].findOne({ name: "forecast-type" }).valuesMap[
variable
@@ -78,16 +79,12 @@ dataThreshold = function (plotParams, plotFunction) {
variable
][key] === forecastTypeStr
);
- var forecastTypeClause;
if (databaseRef === "precip") {
forecastTypeClause = `and m0.num_fcsts = ${forecastType}`;
} else {
forecastTypeClause = `and m0.accum_len = ${forecastType}`;
}
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -95,11 +92,26 @@ dataThreshold = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -107,44 +119,42 @@ dataThreshold = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.trsh as thresh, " + // produces thresholds in in
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{forecastTypeClause}} " +
- "group by thresh " +
- "order by thresh" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{forecastTypeClause}}", forecastTypeClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.trsh as thresh, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{forecastTypeClause}} " +
+ "group by thresh " +
+ "order by thresh" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{forecastTypeClause}}", forecastTypeClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -160,6 +170,7 @@ dataThreshold = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -174,7 +185,6 @@ dataThreshold = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -199,6 +209,7 @@ dataThreshold = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipAccum/server/main.js b/apps/precipAccum/server/main.js
index 170439a8f9..06fe12be3d 100644
--- a/apps/precipAccum/server/main.js
+++ b/apps/precipAccum/server/main.js
@@ -4,7 +4,9 @@
import { Meteor } from "meteor/meteor";
import { mysql } from "meteor/pcel:mysql";
+import { moment } from "meteor/momentjs:moment";
import {
+ matsMethods,
matsTypes,
matsCollections,
matsDataUtils,
@@ -319,7 +321,7 @@ const doCurveParams = function () {
const params = matsCollections.CurveParamsInfo.find({
curve_params: { $exists: true },
}).fetch()[0].curve_params;
- for (let cp = 0; cp < params.length; cp++) {
+ for (let cp = 0; cp < params.length; cp += 1) {
matsCollections[params[cp]].remove({});
}
}
@@ -330,113 +332,95 @@ const doCurveParams = function () {
const thresholdsModelOptionsMap = {};
const scaleModelOptionsMap = {};
const fcstTypeModelOptionsMap = {};
- const masterRegionValuesMap = {};
- const masterThresholdValuesMap = {};
- const masterScaleValuesMap = {};
- const masterFcstTypeValuesMap = {};
+ const allRegionValuesMap = {};
+ const allThresholdValuesMap = {};
+ const allScaleValuesMap = {};
+ const allFcstTypeValuesMap = {};
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- metadataPool,
+ metadataPool, // eslint-disable-line no-undef
"select short_name,description from region_descriptions;"
);
- let masterRegDescription;
- let masterShortName;
- for (var j = 0; j < rows.length; j++) {
- masterRegDescription = rows[j].description.trim();
- masterShortName = rows[j].short_name.trim();
- masterRegionValuesMap[masterShortName] = masterRegDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allRegionValuesMap[rows[j].short_name.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
- let rows;
- let didx;
-
try {
- for (didx = 0; didx < variables.length; didx++) {
- masterThresholdValuesMap[variables[didx]] = {};
- rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ for (let didx = 0; didx < variables.length; didx += 1) {
+ allThresholdValuesMap[variables[didx]] = {};
+ const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
+ sumPool, // eslint-disable-line no-undef
`select trsh,description from ${
variableDBNames[variables[didx]]
}.threshold_descriptions;`
);
- var masterDescription;
- var masterTrsh;
- for (var j = 0; j < rows.length; j++) {
- masterDescription = rows[j].description.trim();
- masterTrsh = rows[j].trsh.trim();
- masterThresholdValuesMap[variables[didx]][masterTrsh] = masterDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allThresholdValuesMap[variables[didx]][rows[j].trsh.trim()] =
+ rows[j].description.trim();
}
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
- for (didx = 0; didx < variables.length; didx++) {
- masterScaleValuesMap[variables[didx]] = {};
- rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ for (let didx = 0; didx < variables.length; didx += 1) {
+ allScaleValuesMap[variables[didx]] = {};
+ const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
+ sumPool, // eslint-disable-line no-undef
`select scle,description from ${
variableDBNames[variables[didx]]
}.scale_descriptions;`
);
- var masterDescription;
- var masterScale;
- for (var j = 0; j < rows.length; j++) {
- masterDescription = rows[j].description.trim();
- masterScale = rows[j].scle.trim();
- masterScaleValuesMap[variables[didx]][masterScale] = masterDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allScaleValuesMap[variables[didx]][rows[j].scle.trim()] =
+ rows[j].description.trim();
}
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
- for (didx = 0; didx < variables.length; didx++) {
- masterFcstTypeValuesMap[variables[didx]] = {};
- rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ for (let didx = 0; didx < variables.length; didx += 1) {
+ allFcstTypeValuesMap[variables[didx]] = {};
+ const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
+ sumPool, // eslint-disable-line no-undef
`select fcst_type,description from ${
variableDBNames[variables[didx]]
}.fcst_type_descriptions;`
);
- var masterFcstTypeDescription;
- var masterFcstType;
- for (var j = 0; j < rows.length; j++) {
- masterFcstTypeDescription = rows[j].description.trim();
- masterFcstType = rows[j].fcst_type.trim();
- masterFcstTypeValuesMap[variables[didx]][masterFcstType] =
- masterFcstTypeDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allFcstTypeValuesMap[variables[didx]][rows[j].fcst_type.trim()] =
+ rows[j].description.trim();
}
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
- for (didx = 0; didx < variables.length; didx++) {
- modelOptionsMap[variables[didx]] = {};
- modelDateRangeMap[variables[didx]] = {};
- thresholdsModelOptionsMap[variables[didx]] = {};
- scaleModelOptionsMap[variables[didx]] = {};
- fcstTypeModelOptionsMap[variables[didx]] = {};
- regionModelOptionsMap[variables[didx]] = {};
-
- rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
- `select model,regions,display_text,fcst_types,trsh,scle,mindate,maxdate from ${
- variableDBNames[variables[didx]]
- }.regions_per_model_mats_all_categories order by display_category, display_order;`
+ for (let didx = 0; didx < variables.length; didx += 1) {
+ const variable = variables[didx];
+ modelOptionsMap[variable] = {};
+ modelDateRangeMap[variable] = {};
+ thresholdsModelOptionsMap[variable] = {};
+ scaleModelOptionsMap[variable] = {};
+ fcstTypeModelOptionsMap[variable] = {};
+ regionModelOptionsMap[variable] = {};
+
+ const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
+ sumPool, // eslint-disable-line no-undef
+ `select model,regions,display_text,fcst_types,trsh,scle,mindate,maxdate from ${variableDBNames[variable]}.regions_per_model_mats_all_categories order by display_category, display_order;`
);
- for (let i = 0; i < rows.length; i++) {
- const model_value = rows[i].model.trim();
+ for (let i = 0; i < rows.length; i += 1) {
+ const modelValue = rows[i].model.trim();
const model = rows[i].display_text.trim();
- modelOptionsMap[variables[didx]][model] = [model_value];
+ modelOptionsMap[variable][model] = [modelValue];
const rowMinDate = moment
.utc(rows[i].mindate * 1000)
@@ -444,62 +428,46 @@ const doCurveParams = function () {
const rowMaxDate = moment
.utc(rows[i].maxdate * 1000)
.format("MM/DD/YYYY HH:mm");
- modelDateRangeMap[variables[didx]][model] = {
+ modelDateRangeMap[variable][model] = {
minDate: rowMinDate,
maxDate: rowMaxDate,
};
const fcstTypes = rows[i].fcst_types;
- const fcstTypesArrRaw = fcstTypes
+ fcstTypeModelOptionsMap[variable][model] = fcstTypes
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const fcstTypesArr = [];
- var dummyfcstType;
- for (var j = 0; j < fcstTypesArrRaw.length; j++) {
- dummyfcstType = fcstTypesArrRaw[j].replace(/'|\[|\]/g, "");
- fcstTypesArr.push(masterFcstTypeValuesMap[variables[didx]][dummyfcstType]);
- }
- fcstTypeModelOptionsMap[variables[didx]][model] = fcstTypesArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (fcstType) {
+ return allFcstTypeValuesMap[variable][fcstType.replace(/'|\[|\]/g, "")];
+ });
const thresholds = rows[i].trsh;
- const thresholdsArrRaw = thresholds
+ thresholdsModelOptionsMap[variable][model] = thresholds
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const thresholdsArr = [];
- var dummyThresh;
- for (var j = 0; j < thresholdsArrRaw.length; j++) {
- dummyThresh = thresholdsArrRaw[j].replace(/'|\[|\]/g, "");
- thresholdsArr.push(masterThresholdValuesMap[variables[didx]][dummyThresh]);
- }
- thresholdsModelOptionsMap[variables[didx]][model] = thresholdsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (threshold) {
+ return allThresholdValuesMap[variable][threshold.replace(/'|\[|\]/g, "")];
+ });
const scales = rows[i].scle;
- const scalesArrRaw = scales
+ scaleModelOptionsMap[variable][model] = scales
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const scalesArr = [];
- var dummyScale;
- for (var j = 0; j < scalesArrRaw.length; j++) {
- dummyScale = scalesArrRaw[j].replace(/'|\[|\]/g, "");
- scalesArr.push(masterScaleValuesMap[variables[didx]][dummyScale]);
- }
- scaleModelOptionsMap[variables[didx]][model] = scalesArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (scale) {
+ return allScaleValuesMap[variable][scale.replace(/'|\[|\]/g, "")];
+ });
const { regions } = rows[i];
- const regionsArrRaw = regions
+ regionModelOptionsMap[variable][model] = regions
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const regionsArr = [];
- var dummyRegion;
- for (var j = 0; j < regionsArrRaw.length; j++) {
- dummyRegion = regionsArrRaw[j].replace(/'|\[|\]/g, "");
- regionsArr.push(masterRegionValuesMap[dummyRegion]);
- }
- regionModelOptionsMap[variables[didx]][model] = regionsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (region) {
+ return allRegionValuesMap[region.replace(/'|\[|\]/g, "")];
+ });
}
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
if (matsCollections.label.findOne({ name: "label" }) === undefined) {
@@ -537,7 +505,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.variable.findOne({ name: "variable" });
+ const currentParam = matsCollections.variable.findOne({ name: "variable" });
if (!matsDataUtils.areObjectsEqual(currentParam.dates, modelDateRangeMap)) {
// have to reload variable data
matsCollections.variable.update(
@@ -576,7 +544,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["data-source"].findOne({ name: "data-source" });
+ const currentParam = matsCollections["data-source"].findOne({
+ name: "data-source",
+ });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap)) {
// have to reload model data
matsCollections["data-source"].update(
@@ -601,7 +571,7 @@ const doCurveParams = function () {
regionModelOptionsMap[variables[0]][
Object.keys(regionModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -616,10 +586,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.region.findOne({ name: "region" });
+ const currentParam = matsCollections.region.findOne({ name: "region" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, regionModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterRegionValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allRegionValuesMap)
) {
// have to reload region data
matsCollections.region.update(
@@ -627,7 +597,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: regionModelOptionsMap,
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
options:
regionModelOptionsMap[variables[0]][
Object.keys(regionModelOptionsMap[variables[0]])[0]
@@ -708,7 +678,7 @@ const doCurveParams = function () {
thresholdsModelOptionsMap[variables[0]][
Object.keys(thresholdsModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterThresholdValuesMap,
+ valuesMap: allThresholdValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -723,13 +693,13 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.threshold.findOne({ name: "threshold" });
+ const currentParam = matsCollections.threshold.findOne({ name: "threshold" });
if (
!matsDataUtils.areObjectsEqual(
currentParam.optionsMap,
thresholdsModelOptionsMap
) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterThresholdValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allThresholdValuesMap)
) {
// have to reload threshold data
matsCollections.threshold.update(
@@ -737,7 +707,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: thresholdsModelOptionsMap,
- valuesMap: masterThresholdValuesMap,
+ valuesMap: allThresholdValuesMap,
options:
thresholdsModelOptionsMap[variables[0]][
Object.keys(thresholdsModelOptionsMap[variables[0]])[0]
@@ -761,7 +731,7 @@ const doCurveParams = function () {
scaleModelOptionsMap[variables[0]][
Object.keys(scaleModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterScaleValuesMap,
+ valuesMap: allScaleValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -776,10 +746,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.scale.findOne({ name: "scale" });
+ const currentParam = matsCollections.scale.findOne({ name: "scale" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, scaleModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterScaleValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allScaleValuesMap)
) {
// have to reload scale data
matsCollections.scale.update(
@@ -787,7 +757,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: scaleModelOptionsMap,
- valuesMap: masterScaleValuesMap,
+ valuesMap: allScaleValuesMap,
options:
scaleModelOptionsMap[variables[0]][
Object.keys(scaleModelOptionsMap[variables[0]])[0]
@@ -813,7 +783,7 @@ const doCurveParams = function () {
fcstTypeModelOptionsMap[variables[0]][
Object.keys(fcstTypeModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterFcstTypeValuesMap,
+ valuesMap: allFcstTypeValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -829,7 +799,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["forecast-type"].findOne({
+ const currentParam = matsCollections["forecast-type"].findOne({
name: "forecast-type",
});
if (
@@ -837,7 +807,7 @@ const doCurveParams = function () {
currentParam.optionsMap,
fcstTypeModelOptionsMap
) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterFcstTypeValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allFcstTypeValuesMap)
) {
// have to reload forecast type data
matsCollections["forecast-type"].update(
@@ -845,7 +815,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: fcstTypeModelOptionsMap,
- valuesMap: masterFcstTypeValuesMap,
+ valuesMap: allFcstTypeValuesMap,
options:
fcstTypeModelOptionsMap[variables[0]][
Object.keys(fcstTypeModelOptionsMap[variables[0]])[0]
@@ -938,18 +908,14 @@ const doCurveParams = function () {
}
// determine date defaults for dates and curveDates
- const defaultDb = matsCollections.variable.findOne(
- { name: "variable" },
+ const defaultDataSource = matsCollections["data-source"].findOne(
+ { name: "data-source" },
{ default: 1 }
).default;
modelDateRangeMap = matsCollections.variable.findOne(
{ name: "variable" },
{ dates: 1 }
).dates;
- const defaultDataSource = matsCollections["data-source"].findOne(
- { name: "data-source" },
- { default: 1 }
- ).default;
minDate = modelDateRangeMap[variables[0]][defaultDataSource].minDate;
maxDate = modelDateRangeMap[variables[0]][defaultDataSource].maxDate;
@@ -990,7 +956,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["curve-dates"].findOne({ name: "curve-dates" });
+ const currentParam = matsCollections["curve-dates"].findOne({
+ name: "curve-dates",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.startDate, minDate) ||
!matsDataUtils.areObjectsEqual(currentParam.stopDate, maxDate) ||
@@ -1244,7 +1212,8 @@ const doPlotGraph = function () {
Meteor.startup(function () {
matsCollections.Databases.remove({});
if (matsCollections.Databases.find({}).count() < 0) {
- console.log(
+ // eslint-disable-next-line no-console
+ console.warn(
"main startup: corrupted Databases collection: dropping Databases collection"
);
matsCollections.Databases.drop();
@@ -1261,7 +1230,7 @@ Meteor.startup(function () {
databases = Meteor.settings.private.databases;
}
if (databases !== null && databases !== undefined && Array.isArray(databases)) {
- for (let di = 0; di < databases.length; di++) {
+ for (let di = 0; di < databases.length; di += 1) {
matsCollections.Databases.insert(databases[di]);
}
}
@@ -1288,6 +1257,7 @@ Meteor.startup(function () {
);
if (cbConnection) {
// global cbScorecardSettingsPool
+ // eslint-disable-next-line no-undef
cbScorecardSettingsPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1314,6 +1284,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (metadataSettings) {
+ // eslint-disable-next-line no-undef
metadataPool = mysql.createPool(metadataSettings);
allPools.push({ pool: "metadataPool", role: matsTypes.DatabaseRoles.META_DATA });
}
@@ -1334,6 +1305,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (sumSettings) {
+ // eslint-disable-next-line no-undef
sumPool = mysql.createPool(sumSettings);
allPools.push({ pool: "sumPool", role: matsTypes.DatabaseRoles.SUMS_DATA });
}
@@ -1342,7 +1314,7 @@ Meteor.startup(function () {
const mdr = new matsTypes.MetaDataDBRecord("metadataPool", "mats_common", [
"region_descriptions",
]);
- for (let didx = 0; didx < variables.length; didx++) {
+ for (let didx = 0; didx < variables.length; didx += 1) {
mdr.addRecord("sumPool", variableDBNames[variables[didx]], [
"threshold_descriptions",
"scale_descriptions",
@@ -1357,7 +1329,7 @@ Meteor.startup(function () {
appType: matsTypes.AppTypes.mats,
});
} catch (error) {
- console.log(error.message);
+ throw new Error(error.message);
}
});
@@ -1365,6 +1337,7 @@ Meteor.startup(function () {
// These are application specific mongo data - like curve params
// The appSpecificResetRoutines object is a special name,
// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way.
+// eslint-disable-next-line no-undef
appSpecificResetRoutines = [
doPlotGraph,
doCurveParams,
diff --git a/apps/precipGauge/.eslintrc.json b/apps/precipGauge/.eslintrc.json
index 8b795b7df7..79d49c5bb6 100644
--- a/apps/precipGauge/.eslintrc.json
+++ b/apps/precipGauge/.eslintrc.json
@@ -28,22 +28,6 @@
"space-before-function-paren": "off",
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
- "prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
- "no-undef": "warn",
- "no-plusplus": "warn",
- "vars-on-top": "warn",
- "no-var": "warn",
- "block-scoped-var": "warn",
- "no-loop-func": "warn",
- "no-unused-vars": "warn",
- "prefer-destructuring": "warn",
- "no-param-reassign": "warn",
- "camelcase": "warn",
- "no-redeclare": "warn"
+ "prefer-arrow-callback": "off"
}
}
diff --git a/apps/precipGauge/client/main.js b/apps/precipGauge/client/main.js
index a87407a1f4..ecd922b6a2 100644
--- a/apps/precipGauge/client/main.js
+++ b/apps/precipGauge/client/main.js
@@ -2,6 +2,7 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+// eslint-disable-next-line no-unused-vars
import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common";
import "@fortawesome/fontawesome-free";
import "@fortawesome/fontawesome-free/css/all.css";
diff --git a/apps/precipGauge/server/dataFunctions/data_contour.js b/apps/precipGauge/server/dataFunctions/data_contour.js
index e4cd3b9a06..eb4ea3d4c5 100644
--- a/apps/precipGauge/server/dataFunctions/data_contour.js
+++ b/apps/precipGauge/server/dataFunctions/data_contour.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContour = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,51 +23,48 @@ dataContour = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
- const totalProcessingStart = moment();
+
+ const curves = JSON.parse(JSON.stringify(plotParams.curves));
+ if (curves.length > 1) {
+ throw new Error("INFO: There must only be one added curve.");
+ }
+
+ const axisMap = Object.create(null);
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- const curves = JSON.parse(JSON.stringify(plotParams.curves));
- if (curves.length > 1) {
- throw new Error("INFO: There must only be one added curve.");
- }
- const dataset = [];
- const axisMap = Object.create(null);
- // initialize variables specific to the curve
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- const regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${region}${sourceStr} as m0`;
+
let thresholdClause = "";
- let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") {
const thresholdStr = curve.threshold;
+ if (thresholdStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s threshold is undefined. Please assign it a value.`
+ );
+ }
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap
).find(
@@ -76,16 +74,38 @@ dataContour = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.thresh = ${threshold}`;
}
+
+ let validTimeClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.valid_time%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -96,95 +116,105 @@ dataContour = function (plotParams, plotFunction) {
dateString = "m0.valid_time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${region}${source} as m0`;
+
// For contours, this functions as the colorbar label.
const statType = statisticOptionsMap[statisticSelect][0];
- curve.unitKey = statisticOptionsMap[statisticSelect][1];
+ [, curve.unitKey] = statisticOptionsMap[statisticSelect];
let d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
-
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
+
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
- }
- if (!dataFoundForCurve) {
- // we found no data for any curves so don't bother proceeding
- throw new Error("INFO: No valid data for any curves.");
- }
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
+ // this is NOT an error just a no data condition
+ dataFoundForCurve = false;
+ } else {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ }
- const postQueryStartMoment = moment();
+ if (!dataFoundForCurve) {
+ // we found no data for any curves so don't bother proceeding
+ throw new Error("INFO: No valid data for any curves.");
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
+ }
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
diff --git a/apps/precipGauge/server/dataFunctions/data_contour_diff.js b/apps/precipGauge/server/dataFunctions/data_contour_diff.js
index 5460fe0f7f..44d4306424 100644
--- a/apps/precipGauge/server/dataFunctions/data_contour_diff.js
+++ b/apps/precipGauge/server/dataFunctions/data_contour_diff.js
@@ -14,6 +14,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContourDiff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -24,55 +25,54 @@ dataContourDiff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
let dataNotFoundForAnyCurve = false;
+
+ let curves = JSON.parse(JSON.stringify(plotParams.curves));
+ const curvesLength = curves.length;
+ if (curvesLength !== 2) {
+ throw new Error("INFO: There must be two added curves.");
+ }
+
+ const axisMap = Object.create(null);
const showSignificance = plotParams.significance !== "none";
- const totalProcessingStart = moment();
+
+ let statType;
+ let statisticSelect;
+
+ let statement = "";
+ let error = "";
+ let dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- let curves = JSON.parse(JSON.stringify(plotParams.curves));
- const curvesLength = curves.length;
- if (curvesLength !== 2) {
- throw new Error("INFO: There must be two added curves.");
- }
- let dataset = [];
- const axisMap = Object.create(null);
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${region}${sourceStr} as m0`;
+
let thresholdClause = "";
- let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") {
- var thresholdStr = curve.threshold;
+ const thresholdStr = curve.threshold;
+ if (thresholdStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s threshold is undefined. Please assign it a value.`
+ );
+ }
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap
).find(
@@ -82,16 +82,38 @@ dataContourDiff = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.thresh = ${threshold}`;
}
+
+ let validTimeClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.valid_time%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
+ statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -102,91 +124,98 @@ dataContourDiff = function (plotParams, plotFunction) {
dateString = "m0.valid_time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- var statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${region}${source} as m0`;
+
// For contours, this functions as the colorbar label.
- var statType = statisticOptionsMap[statisticSelect][0];
- curves[curveIndex].unitKey = statisticOptionsMap[statisticSelect][1];
+ [statType] = statisticOptionsMap[statisticSelect];
+ [, curve.unitKey] = statisticOptionsMap[statisticSelect];
- var d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
+ let d;
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
- dataNotFoundForAnyCurve = true;
- }
- const postQueryStartMoment = moment();
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ dataNotFoundForAnyCurve = true;
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
+ }
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
@@ -235,8 +264,9 @@ dataContourDiff = function (plotParams, plotFunction) {
statType === "ctc",
statType === "scalar"
);
- plotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
- curves = plotParams.curves;
+ const newPlotParams = plotParams;
+ newPlotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
+ curves = newPlotParams.curves;
dataset[0].name = matsPlotUtils.getCurveText(
matsTypes.PlotTypes.contourDiff,
curves[0]
@@ -252,7 +282,7 @@ dataContourDiff = function (plotParams, plotFunction) {
const result = matsDataProcessUtils.processDataContour(
dataset,
curveInfoParams,
- plotParams,
+ newPlotParams,
bookkeepingParams
);
plotFunction(result);
diff --git a/apps/precipGauge/server/dataFunctions/data_dailymodelcycle.js b/apps/precipGauge/server/dataFunctions/data_dailymodelcycle.js
index e0f4721495..314b566fb5 100644
--- a/apps/precipGauge/server/dataFunctions/data_dailymodelcycle.js
+++ b/apps/precipGauge/server/dataFunctions/data_dailymodelcycle.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDailyModelCycle = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,46 +24,42 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${region}${sourceStr} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap
).find(
@@ -71,6 +68,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
thresholdStr
);
const thresholdClause = `and m0.thresh = ${threshold}`;
+
if (curve["utc-cycle-start"].length !== 1) {
throw new Error(
"INFO: Please select exactly one UTC Cycle Init Hour for this plot type."
@@ -79,20 +77,35 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
const utcCycleStart = Number(curve["utc-cycle-start"][0]);
utcCycleStarts[curveIndex] = utcCycleStart;
const utcCycleStartClause = `and floor((m0.valid_time - m0.fcst_len*3600)%(24*3600)/3600) IN(${utcCycleStart})`;
+
const forecastLengthClause = "and m0.fcst_len < 24";
- const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`;
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap;
const statisticClause =
- "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+ "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+
+ const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${region}${source} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -100,46 +113,46 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.valid_time as avtime, " +
- "count(distinct m0.valid_time) as N_times, " +
- "min(m0.valid_time) as min_secs, " +
- "max(m0.valid_time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{utcCycleStartClause}} " +
- "{{thresholdClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.valid_time as avtime, " +
+ "count(distinct m0.valid_time) as N_times, " +
+ "min(m0.valid_time) as min_secs, " +
+ "max(m0.valid_time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{utcCycleStartClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -155,6 +168,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -169,7 +183,6 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -194,6 +207,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipGauge/server/dataFunctions/data_dieoff.js b/apps/precipGauge/server/dataFunctions/data_dieoff.js
index 3684c6bcd2..20334fdb0a 100644
--- a/apps/precipGauge/server/dataFunctions/data_dieoff.js
+++ b/apps/precipGauge/server/dataFunctions/data_dieoff.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDieoff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,43 +24,38 @@ dataDieoff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${region}${sourceStr} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap
).find(
@@ -68,21 +64,44 @@ dataDieoff = function (plotParams, plotFunction) {
thresholdStr
);
const thresholdClause = `and m0.thresh = ${threshold}`;
- var validTimes;
+
let validTimeClause = "";
- var utcCycleStart;
+ let validTimes;
+
let utcCycleStartClause = "";
+ let utcCycleStart;
+
const forecastLengthStr = curve["dieoff-type"];
const forecastLengthOptionsMap = matsCollections["dieoff-type"].findOne(
{ name: "dieoff-type" },
{ optionsMap: 1 }
).optionsMap;
const forecastLength = forecastLengthOptionsMap[forecastLengthStr][0];
- const forecastLengthClause = "";
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
- var dateClause;
+ let dateClause;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${region}${source} as m0`;
+
if (forecastLength === matsTypes.ForecastTypes.dieoff) {
validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
@@ -99,18 +118,12 @@ dataDieoff = function (plotParams, plotFunction) {
} else {
dateClause = `and m0.valid_time-m0.fcst_len*3600 = ${fromSecs}`;
}
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -118,48 +131,46 @@ dataDieoff = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.fcst_len as fcst_lead, " +
- "count(distinct m0.valid_time) as N_times, " +
- "min(m0.valid_time) as min_secs, " +
- "max(m0.valid_time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{utcCycleStartClause}} " +
- "group by fcst_lead " +
- "order by fcst_lead" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.fcst_len as fcst_lead, " +
+ "count(distinct m0.valid_time) as N_times, " +
+ "min(m0.valid_time) as min_secs, " +
+ "max(m0.valid_time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{utcCycleStartClause}} " +
+ "group by fcst_lead " +
+ "order by fcst_lead" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -175,6 +186,7 @@ dataDieoff = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -189,7 +201,6 @@ dataDieoff = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -214,6 +225,7 @@ dataDieoff = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipGauge/server/dataFunctions/data_histogram.js b/apps/precipGauge/server/dataFunctions/data_histogram.js
index 08e43cd2e6..aeef9ba343 100644
--- a/apps/precipGauge/server/dataFunctions/data_histogram.js
+++ b/apps/precipGauge/server/dataFunctions/data_histogram.js
@@ -11,6 +11,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataHistogram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -21,46 +22,42 @@ dataHistogram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
- const alreadyMatched = false;
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
const dataFoundForCurve = [];
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+ const alreadyMatched = false;
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
+
+ const axisMap = Object.create(null);
+ let statType;
+ let varUnits;
+
+ let statement = "";
+ let error = "";
const dataset = [];
const allReturnedSubStats = [];
const allReturnedSubSecs = [];
- const axisMap = Object.create(null);
// process user bin customizations
const binParams = matsDataUtils.setHistogramParameters(plotParams);
const { yAxisFormat } = binParams;
const { binNum } = binParams;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
dataFoundForCurve[curveIndex] = true;
const { label } = curve;
+ const { diffFrom } = curve;
+
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${region}${sourceStr} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap
).find(
@@ -69,30 +66,46 @@ dataHistogram = function (plotParams, plotFunction) {
thresholdStr
);
const thresholdClause = `and m0.thresh = ${threshold}`;
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.valid_time)%(24*3600)/3600) IN(${validTimes})`;
}
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`;
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap;
const statisticClause =
- "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+ "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${region}${source} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
- var varUnits = statisticOptionsMap[statisticSelect][1];
+ [statType] = statisticOptionsMap[statisticSelect];
+ [, varUnits] = statisticOptionsMap[statisticSelect];
let axisKey = yAxisFormat;
if (yAxisFormat === "Relative frequency") {
axisKey += " (x100)";
@@ -100,46 +113,46 @@ dataHistogram = function (plotParams, plotFunction) {
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
curves[curveIndex].binNum = binNum; // stash the binNum to use it later for bar chart options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.valid_time as avtime, " +
- "count(distinct m0.valid_time) as N_times, " +
- "min(m0.valid_time) as min_secs, " +
- "max(m0.valid_time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.valid_time as avtime, " +
+ "count(distinct m0.valid_time) as N_times, " +
+ "min(m0.valid_time) as min_secs, " +
+ "max(m0.valid_time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -157,6 +170,7 @@ dataHistogram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/precipGauge/server/dataFunctions/data_perfDiagram.js b/apps/precipGauge/server/dataFunctions/data_perfDiagram.js
index 12c3fb5d20..a068e2685d 100644
--- a/apps/precipGauge/server/dataFunctions/data_perfDiagram.js
+++ b/apps/precipGauge/server/dataFunctions/data_perfDiagram.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataPerformanceDiagram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,54 +23,43 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statType;
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const binParam = curve["bin-parameter"];
const binClause = matsCollections["bin-parameter"].findOne({
name: "bin-parameter",
}).optionsMap[binParam];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${region}${sourceStr} as m0`;
+
let thresholdClause = "";
- let validTimeClause = "";
- let forecastLengthClause = "";
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let dateString = "";
- let dateClause = "";
if (binParam !== "Threshold") {
- var thresholdStr = curve.threshold;
+ const thresholdStr = curve.threshold;
if (thresholdStr === undefined) {
throw new Error(
`INFO: ${label}'s threshold is undefined. Please assign it a value.`
@@ -84,12 +74,16 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.thresh = ${threshold}`;
}
+
+ let validTimeClause = "";
if (binParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.valid_time%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (binParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
if (forecastLength === undefined) {
@@ -99,62 +93,81 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
}
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
+ const statisticSelect = "PerformanceDiagram";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ let dateString = "";
+ let dateClause = "";
if (binParam === "Init Date") {
dateString = "m0.valid_time-m0.fcst_len*3600";
} else {
dateString = "m0.valid_time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const statisticSelect = "PerformanceDiagram";
- var statType = "ctc";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${region}${source} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// variable + statistic (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ statType = "ctc";
curves[curveIndex].axisKey = statisticSelect; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{binClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "((sum(m0.yy)+0.00)/sum(m0.yy+m0.ny)) as pod, ((sum(m0.yn)+0.00)/sum(m0.yn+m0.yy)) as far, " +
- "sum(m0.yy+m0.ny) as oy_all, sum(m0.yn+m0.nn) as on_all, group_concat(m0.valid_time, ';', m0.yy, ';', " +
- "m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0 " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by binVal " +
- "order by binVal" +
- ";";
-
- statement = statement.replace("{{binClause}}", binClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "{{binClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "((sum(m0.yy)+0.00)/sum(m0.yy+m0.ny)) as pod, ((sum(m0.yn)+0.00)/sum(m0.yn+m0.yy)) as far, " +
+ "sum(m0.yy+m0.ny) as oy_all, sum(m0.yn+m0.nn) as on_all, group_concat(m0.valid_time, ';', m0.yy, ';', " +
+ "m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0 " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by binVal " +
+ "order by binVal" +
+ ";";
+
+ statement = statement.replace("{{binClause}}", binClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBPerformanceDiagram(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -170,6 +183,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -177,21 +191,13 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
} else {
// this is an error returned by the mysql database
error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- if (error.includes("ER_NO_SUCH_TABLE")) {
- throw new Error(
- `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` +
- `Choose a different scale to continue using this region.`
- );
- } else {
- throw new Error(error);
- }
+ throw new Error(error);
}
} else {
dataFoundForAnyCurve = true;
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -199,7 +205,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
ymax = ymax > d.ymax ? ymax : d.ymax;
}
} else {
- // this is a difference curve -- not supported for ROC plots
+ // this is a difference curve -- not supported for performance diagrams
throw new Error(
"INFO: Difference curves are not supported for performance diagrams, as they do not feature consistent x or y values across all curves."
);
@@ -207,6 +213,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipGauge/server/dataFunctions/data_series.js b/apps/precipGauge/server/dataFunctions/data_series.js
index 7a929ba26b..79d9686be7 100644
--- a/apps/precipGauge/server/dataFunctions/data_series.js
+++ b/apps/precipGauge/server/dataFunctions/data_series.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSeries = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,46 +24,42 @@ dataSeries = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${region}${sourceStr} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap
).find(
@@ -71,20 +68,18 @@ dataSeries = function (plotParams, plotFunction) {
thresholdStr
);
const thresholdClause = `and m0.thresh = ${threshold}`;
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.valid_time)%(24*3600)/3600) IN(${validTimes})`;
}
+
let forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`;
- const averageStr = curve.average;
- const averageOptionsMap = matsCollections.average.findOne(
- { name: "average" },
- { optionsMap: 1 }
- ).optionsMap;
- const average = averageOptionsMap[averageStr][0];
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -92,11 +87,30 @@ dataSeries = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+
+ const averageStr = curve.average;
+ const averageOptionsMap = matsCollections.average.findOne(
+ { name: "average" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const average = averageOptionsMap[averageStr][0];
+
+ const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${region}${source} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -104,47 +118,45 @@ dataSeries = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select {{average}} as avtime, " +
- "count(distinct m0.valid_time) as N_times, " +
- "min(m0.valid_time) as min_secs, " +
- "max(m0.valid_time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "select {{average}} as avtime, " +
+ "count(distinct m0.valid_time) as N_times, " +
+ "min(m0.valid_time) as min_secs, " +
+ "max(m0.valid_time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
- statement = statement.replace("{{average}}", average);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
+ statement = statement.replace("{{average}}", average);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
- // math is done on forecastLength later on -- set all analyses to 0
- if (forecastLength === "-99") {
- forecastLength = "0";
- }
+ // math is done on forecastLength later on -- set all analyses to 0
+ if (forecastLength === "-99") {
+ forecastLength = "0";
+ }
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBTimeSeries(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
model,
forecastLength,
@@ -156,7 +168,9 @@ dataSeries = function (plotParams, plotFunction) {
appParams,
false
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -172,6 +186,7 @@ dataSeries = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -186,7 +201,6 @@ dataSeries = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -211,6 +225,7 @@ dataSeries = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipGauge/server/dataFunctions/data_threshold.js b/apps/precipGauge/server/dataFunctions/data_threshold.js
index 1e8b3b36da..af77af8e6a 100644
--- a/apps/precipGauge/server/dataFunctions/data_threshold.js
+++ b/apps/precipGauge/server/dataFunctions/data_threshold.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataThreshold = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,66 +24,75 @@ dataThreshold = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${region}${sourceStr} as m0`;
- const thresholdClause = "";
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.valid_time)%(24*3600)/3600) IN(${validTimes})`;
}
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`;
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap;
const statisticClause =
- "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+ "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${region}${source} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -90,46 +100,44 @@ dataThreshold = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.thresh/100 as thresh, " + // produces thresholds in inches
- "count(distinct m0.valid_time) as N_times, " +
- "min(m0.valid_time) as min_secs, " +
- "max(m0.valid_time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by thresh " +
- "order by thresh" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.thresh/100 as thresh, " + // produces thresholds in inches
+ "count(distinct m0.valid_time) as N_times, " +
+ "min(m0.valid_time) as min_secs, " +
+ "max(m0.valid_time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by thresh " +
+ "order by thresh" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -145,6 +153,7 @@ dataThreshold = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -159,7 +168,6 @@ dataThreshold = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -184,6 +192,7 @@ dataThreshold = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipGauge/server/dataFunctions/data_validtime.js b/apps/precipGauge/server/dataFunctions/data_validtime.js
index 6df0ed4397..764138ced9 100644
--- a/apps/precipGauge/server/dataFunctions/data_validtime.js
+++ b/apps/precipGauge/server/dataFunctions/data_validtime.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataValidTime = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,43 +24,38 @@ dataValidTime = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${region}${sourceStr} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap
).find(
@@ -68,24 +64,39 @@ dataValidTime = function (plotParams, plotFunction) {
thresholdStr
);
const thresholdClause = `and m0.thresh = ${threshold}`;
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`;
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap;
const statisticClause =
- "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+ "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${region}${source} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -93,44 +104,44 @@ dataValidTime = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select floor(m0.valid_time%(24*3600)/3600) as hr_of_day, " +
- "count(distinct m0.valid_time) as N_times, " +
- "min(m0.valid_time) as min_secs, " +
- "max(m0.valid_time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{forecastLengthClause}} " +
- "group by hr_of_day " +
- "order by hr_of_day" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select floor(m0.valid_time%(24*3600)/3600) as hr_of_day, " +
+ "count(distinct m0.valid_time) as N_times, " +
+ "min(m0.valid_time) as min_secs, " +
+ "max(m0.valid_time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by hr_of_day " +
+ "order by hr_of_day" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -146,6 +157,7 @@ dataValidTime = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -160,7 +172,6 @@ dataValidTime = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -185,6 +196,7 @@ dataValidTime = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipGauge/server/main.js b/apps/precipGauge/server/main.js
index f5bcd67650..f3b0947bc6 100644
--- a/apps/precipGauge/server/main.js
+++ b/apps/precipGauge/server/main.js
@@ -4,7 +4,9 @@
import { Meteor } from "meteor/meteor";
import { mysql } from "meteor/pcel:mysql";
+import { moment } from "meteor/momentjs:moment";
import {
+ matsMethods,
matsTypes,
matsCollections,
matsDataUtils,
@@ -320,109 +322,95 @@ const doCurveParams = function () {
const params = matsCollections.CurveParamsInfo.find({
curve_params: { $exists: true },
}).fetch()[0].curve_params;
- for (let cp = 0; cp < params.length; cp++) {
+ for (let cp = 0; cp < params.length; cp += 1) {
matsCollections[params[cp]].remove({});
}
}
+
const modelOptionsMap = {};
let modelDateRangeMap = {};
const regionModelOptionsMap = {};
const forecastLengthOptionsMap = {};
const thresholdsModelOptionsMap = {};
const sourceOptionsMap = {};
- const masterRegionValuesMap = {};
- const masterThresholdValuesMap = {};
+ const allRegionValuesMap = {};
+ const allThresholdValuesMap = {};
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- metadataPool,
+ metadataPool, // eslint-disable-line no-undef
"select short_name,description from region_descriptions;"
);
- let masterRegDescription;
- let masterShortName;
- for (var j = 0; j < rows.length; j++) {
- masterRegDescription = rows[j].description.trim();
- masterShortName = rows[j].short_name.trim();
- masterRegionValuesMap[masterShortName] = masterRegDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allRegionValuesMap[rows[j].short_name.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- modelPool,
+ modelPool, // eslint-disable-line no-undef
"select trsh,description from threshold_descriptions;"
);
- let masterDescription;
- let masterTrsh;
- for (var j = 0; j < rows.length; j++) {
- masterDescription = rows[j].description.trim();
- masterTrsh = rows[j].trsh.trim();
- masterThresholdValuesMap[masterTrsh] = masterDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allThresholdValuesMap[rows[j].trsh.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select model,regions,sources,display_text,fcst_lens,trsh,mindate,maxdate from regions_per_model_mats_all_categories order by display_category, display_order;"
);
- for (let i = 0; i < rows.length; i++) {
- const model_value = rows[i].model.trim();
+ for (let i = 0; i < rows.length; i += 1) {
+ const modelValue = rows[i].model.trim();
const model = rows[i].display_text.trim();
- modelOptionsMap[model] = [model_value];
+ modelOptionsMap[model] = [modelValue];
const rowMinDate = moment.utc(rows[i].mindate * 1000).format("MM/DD/YYYY HH:mm");
const rowMaxDate = moment.utc(rows[i].maxdate * 1000).format("MM/DD/YYYY HH:mm");
- modelDateRangeMap[model] = { minDate: rowMinDate, maxDate: rowMaxDate };
+ modelDateRangeMap[model] = {
+ minDate: rowMinDate,
+ maxDate: rowMaxDate,
+ };
const { sources } = rows[i];
- const sourceArr = sources
+ sourceOptionsMap[model] = sources
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (var j = 0; j < sourceArr.length; j++) {
- sourceArr[j] = sourceArr[j].replace(/'|\[|\]/g, "");
- }
- sourceOptionsMap[model] = sourceArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (source) {
+ return source.replace(/'|\[|\]/g, "");
+ });
const forecastLengths = rows[i].fcst_lens;
- const forecastLengthArr = forecastLengths
+ forecastLengthOptionsMap[model] = forecastLengths
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (var j = 0; j < forecastLengthArr.length; j++) {
- forecastLengthArr[j] = forecastLengthArr[j].replace(/'|\[|\]/g, "");
- }
- forecastLengthOptionsMap[model] = forecastLengthArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (fhr) {
+ return fhr.replace(/'|\[|\]/g, "");
+ });
const thresholds = rows[i].trsh;
- const thresholdsArrRaw = thresholds
+ thresholdsModelOptionsMap[model] = thresholds
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const thresholdsArr = [];
- var dummyThresh;
- for (var j = 0; j < thresholdsArrRaw.length; j++) {
- dummyThresh = thresholdsArrRaw[j].replace(/'|\[|\]/g, "");
- thresholdsArr.push(masterThresholdValuesMap[dummyThresh]);
- }
- thresholdsModelOptionsMap[model] = thresholdsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (threshold) {
+ return allThresholdValuesMap[threshold.replace(/'|\[|\]/g, "")];
+ });
const { regions } = rows[i];
- const regionsArrRaw = regions
+ regionModelOptionsMap[model] = regions
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const regionsArr = [];
- var dummyRegion;
- for (var j = 0; j < regionsArrRaw.length; j++) {
- dummyRegion = regionsArrRaw[j].replace(/'|\[|\]/g, "");
- regionsArr.push(masterRegionValuesMap[dummyRegion]);
- }
- regionModelOptionsMap[model] = regionsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (region) {
+ return allRegionValuesMap[region.replace(/'|\[|\]/g, "")];
+ });
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
if (matsCollections.label.findOne({ name: "label" }) === undefined) {
@@ -467,7 +455,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["data-source"].findOne({ name: "data-source" });
+ const currentParam = matsCollections["data-source"].findOne({
+ name: "data-source",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap) ||
!matsDataUtils.areObjectsEqual(currentParam.dates, modelDateRangeMap)
@@ -493,7 +483,7 @@ const doCurveParams = function () {
type: matsTypes.InputTypes.select,
optionsMap: regionModelOptionsMap,
options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]],
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
superiorNames: ["data-source"],
controlButtonCovered: true,
unique: false,
@@ -505,10 +495,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.region.findOne({ name: "region" });
+ const currentParam = matsCollections.region.findOne({ name: "region" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, regionModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterRegionValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allRegionValuesMap)
) {
// have to reload region data
matsCollections.region.update(
@@ -516,7 +506,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: regionModelOptionsMap,
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]],
default: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]][0],
},
@@ -588,7 +578,7 @@ const doCurveParams = function () {
type: matsTypes.InputTypes.select,
optionsMap: thresholdsModelOptionsMap,
options: thresholdsModelOptionsMap[Object.keys(thresholdsModelOptionsMap)[0]],
- valuesMap: masterThresholdValuesMap,
+ valuesMap: allThresholdValuesMap,
superiorNames: ["data-source"],
controlButtonCovered: true,
unique: false,
@@ -600,13 +590,13 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.threshold.findOne({ name: "threshold" });
+ const currentParam = matsCollections.threshold.findOne({ name: "threshold" });
if (
!matsDataUtils.areObjectsEqual(
currentParam.optionsMap,
thresholdsModelOptionsMap
) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterThresholdValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allThresholdValuesMap)
) {
// have to reload threshold data
matsCollections.threshold.update(
@@ -614,7 +604,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: thresholdsModelOptionsMap,
- valuesMap: masterThresholdValuesMap,
+ valuesMap: allThresholdValuesMap,
options:
thresholdsModelOptionsMap[Object.keys(thresholdsModelOptionsMap)[0]],
default:
@@ -642,7 +632,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.truth.findOne({ name: "truth" });
+ const currentParam = matsCollections.truth.findOne({ name: "truth" });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, sourceOptionsMap)) {
// have to reload truth data
matsCollections.truth.update(
@@ -680,7 +670,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["forecast-length"].findOne({
+ const currentParam = matsCollections["forecast-length"].findOne({
name: "forecast-length",
});
if (
@@ -962,7 +952,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["curve-dates"].findOne({ name: "curve-dates" });
+ const currentParam = matsCollections["curve-dates"].findOne({
+ name: "curve-dates",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.startDate, minDate) ||
!matsDataUtils.areObjectsEqual(currentParam.stopDate, maxDate) ||
@@ -1308,7 +1300,8 @@ const doPlotGraph = function () {
Meteor.startup(function () {
matsCollections.Databases.remove({});
if (matsCollections.Databases.find({}).count() < 0) {
- console.log(
+ // eslint-disable-next-line no-console
+ console.warn(
"main startup: corrupted Databases collection: dropping Databases collection"
);
matsCollections.Databases.drop();
@@ -1325,7 +1318,7 @@ Meteor.startup(function () {
databases = Meteor.settings.private.databases;
}
if (databases !== null && databases !== undefined && Array.isArray(databases)) {
- for (let di = 0; di < databases.length; di++) {
+ for (let di = 0; di < databases.length; di += 1) {
matsCollections.Databases.insert(databases[di]);
}
}
@@ -1352,6 +1345,7 @@ Meteor.startup(function () {
);
if (cbConnection) {
// global cbScorecardSettingsPool
+ // eslint-disable-next-line no-undef
cbScorecardSettingsPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1378,6 +1372,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (metadataSettings) {
+ // eslint-disable-next-line no-undef
metadataPool = mysql.createPool(metadataSettings);
allPools.push({ pool: "metadataPool", role: matsTypes.DatabaseRoles.META_DATA });
}
@@ -1395,6 +1390,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (modelSettings) {
+ // eslint-disable-next-line no-undef
modelPool = mysql.createPool(modelSettings);
allPools.push({ pool: "modelPool", role: matsTypes.DatabaseRoles.MODEL_DATA });
}
@@ -1415,6 +1411,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (sumSettings) {
+ // eslint-disable-next-line no-undef
sumPool = mysql.createPool(sumSettings);
allPools.push({ pool: "sumPool", role: matsTypes.DatabaseRoles.SUMS_DATA });
}
@@ -1434,7 +1431,7 @@ Meteor.startup(function () {
appType: matsTypes.AppTypes.mats,
});
} catch (error) {
- console.log(error.message);
+ throw new Error(error.message);
}
});
@@ -1442,6 +1439,7 @@ Meteor.startup(function () {
// These are application specific mongo data - like curve params
// The appSpecificResetRoutines object is a special name,
// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way.
+// eslint-disable-next-line no-undef
appSpecificResetRoutines = [
doPlotGraph,
doCurveParams,
diff --git a/apps/precipitation1hr/.eslintrc.json b/apps/precipitation1hr/.eslintrc.json
index 8b795b7df7..79d49c5bb6 100644
--- a/apps/precipitation1hr/.eslintrc.json
+++ b/apps/precipitation1hr/.eslintrc.json
@@ -28,22 +28,6 @@
"space-before-function-paren": "off",
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
- "prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
- "no-undef": "warn",
- "no-plusplus": "warn",
- "vars-on-top": "warn",
- "no-var": "warn",
- "block-scoped-var": "warn",
- "no-loop-func": "warn",
- "no-unused-vars": "warn",
- "prefer-destructuring": "warn",
- "no-param-reassign": "warn",
- "camelcase": "warn",
- "no-redeclare": "warn"
+ "prefer-arrow-callback": "off"
}
}
diff --git a/apps/precipitation1hr/client/main.js b/apps/precipitation1hr/client/main.js
index a87407a1f4..ecd922b6a2 100644
--- a/apps/precipitation1hr/client/main.js
+++ b/apps/precipitation1hr/client/main.js
@@ -2,6 +2,7 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+// eslint-disable-next-line no-unused-vars
import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common";
import "@fortawesome/fontawesome-free";
import "@fortawesome/fontawesome-free/css/all.css";
diff --git a/apps/precipitation1hr/server/dataFunctions/data_contour.js b/apps/precipitation1hr/server/dataFunctions/data_contour.js
index 7e0dd2f574..508c06e924 100644
--- a/apps/precipitation1hr/server/dataFunctions/data_contour.js
+++ b/apps/precipitation1hr/server/dataFunctions/data_contour.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContour = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,58 +23,48 @@ dataContour = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
- const totalProcessingStart = moment();
+
+ const curves = JSON.parse(JSON.stringify(plotParams.curves));
+ if (curves.length > 1) {
+ throw new Error("INFO: There must only be one added curve.");
+ }
+
+ const axisMap = Object.create(null);
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- const curves = JSON.parse(JSON.stringify(plotParams.curves));
- if (curves.length > 1) {
- throw new Error("INFO: There must only be one added curve.");
- }
- const dataset = [];
- const axisMap = Object.create(null);
- // initialize variables specific to the curve
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- const regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${grid_scale}${sourceStr}_${region} as m0`;
+
let thresholdClause = "";
- let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") {
const thresholdStr = curve.threshold;
+ if (thresholdStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s threshold is undefined. Please assign it a value.`
+ );
+ }
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap
).find(
@@ -83,16 +74,46 @@ dataContour = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold * 0.01}`;
}
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+
+ let validTimeClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.time%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ "sum(m0.hit) as hit, sum(m0.fa) as fa, sum(m0.miss) as miss, sum(m0.cn) as cn, group_concat(m0.time, ';', m0.hit, ';', m0.fa, ';', m0.miss, ';', m0.cn order by m0.time) as sub_data, count(m0.hit) as N0";
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -103,95 +124,105 @@ dataContour = function (plotParams, plotFunction) {
dateString = "m0.time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- "sum(m0.hit) as hit, sum(m0.fa) as fa, sum(m0.miss) as miss, sum(m0.cn) as cn, group_concat(m0.time, ';', m0.hit, ';', m0.fa, ';', m0.miss, ';', m0.cn order by m0.time) as sub_data, count(m0.hit) as N0";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${scale}${source}_${region} as m0`;
+
// For contours, this functions as the colorbar label.
const statType = statisticOptionsMap[statisticSelect][0];
- curve.unitKey = statisticOptionsMap[statisticSelect][1];
+ [, curve.unitKey] = statisticOptionsMap[statisticSelect];
let d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
-
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
+
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
- }
- if (!dataFoundForCurve) {
- // we found no data for any curves so don't bother proceeding
- throw new Error("INFO: No valid data for any curves.");
- }
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
+ // this is NOT an error just a no data condition
+ dataFoundForCurve = false;
+ } else {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ }
- const postQueryStartMoment = moment();
+ if (!dataFoundForCurve) {
+ // we found no data for any curves so don't bother proceeding
+ throw new Error("INFO: No valid data for any curves.");
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
+ }
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
diff --git a/apps/precipitation1hr/server/dataFunctions/data_contour_diff.js b/apps/precipitation1hr/server/dataFunctions/data_contour_diff.js
index 3f14ae824e..2cb3a698f7 100644
--- a/apps/precipitation1hr/server/dataFunctions/data_contour_diff.js
+++ b/apps/precipitation1hr/server/dataFunctions/data_contour_diff.js
@@ -14,6 +14,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContourDiff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -24,62 +25,54 @@ dataContourDiff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
let dataNotFoundForAnyCurve = false;
+
+ let curves = JSON.parse(JSON.stringify(plotParams.curves));
+ const curvesLength = curves.length;
+ if (curvesLength !== 2) {
+ throw new Error("INFO: There must be two added curves.");
+ }
+
+ const axisMap = Object.create(null);
const showSignificance = plotParams.significance !== "none";
- const totalProcessingStart = moment();
+
+ let statType;
+ let statisticSelect;
+
+ let statement = "";
+ let error = "";
+ let dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- let curves = JSON.parse(JSON.stringify(plotParams.curves));
- const curvesLength = curves.length;
- if (curvesLength !== 2) {
- throw new Error("INFO: There must be two added curves.");
- }
- let dataset = [];
- const axisMap = Object.create(null);
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${grid_scale}${sourceStr}_${region} as m0`;
+
let thresholdClause = "";
- let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") {
- var thresholdStr = curve.threshold;
+ const thresholdStr = curve.threshold;
+ if (thresholdStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s threshold is undefined. Please assign it a value.`
+ );
+ }
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap
).find(
@@ -89,16 +82,46 @@ dataContourDiff = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold * 0.01}`;
}
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+
+ let validTimeClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.time%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
+ statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ "sum(m0.hit) as hit, sum(m0.fa) as fa, sum(m0.miss) as miss, sum(m0.cn) as cn, group_concat(m0.time, ';', m0.hit, ';', m0.fa, ';', m0.miss, ';', m0.cn order by m0.time) as sub_data, count(m0.hit) as N0";
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -109,91 +132,98 @@ dataContourDiff = function (plotParams, plotFunction) {
dateString = "m0.time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- var statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- "sum(m0.hit) as hit, sum(m0.fa) as fa, sum(m0.miss) as miss, sum(m0.cn) as cn, group_concat(m0.time, ';', m0.hit, ';', m0.fa, ';', m0.miss, ';', m0.cn order by m0.time) as sub_data, count(m0.hit) as N0";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${scale}${source}_${region} as m0`;
+
// For contours, this functions as the colorbar label.
- var statType = statisticOptionsMap[statisticSelect][0];
- curves[curveIndex].unitKey = statisticOptionsMap[statisticSelect][1];
+ [statType] = statisticOptionsMap[statisticSelect];
+ [, curve.unitKey] = statisticOptionsMap[statisticSelect];
- var d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
+ let d;
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
- dataNotFoundForAnyCurve = true;
- }
- const postQueryStartMoment = moment();
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ dataNotFoundForAnyCurve = true;
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
+ }
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
@@ -242,8 +272,9 @@ dataContourDiff = function (plotParams, plotFunction) {
statType === "ctc",
statType === "scalar"
);
- plotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
- curves = plotParams.curves;
+ const newPlotParams = plotParams;
+ newPlotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
+ curves = newPlotParams.curves;
dataset[0].name = matsPlotUtils.getCurveText(
matsTypes.PlotTypes.contourDiff,
curves[0]
@@ -259,7 +290,7 @@ dataContourDiff = function (plotParams, plotFunction) {
const result = matsDataProcessUtils.processDataContour(
dataset,
curveInfoParams,
- plotParams,
+ newPlotParams,
bookkeepingParams
);
plotFunction(result);
diff --git a/apps/precipitation1hr/server/dataFunctions/data_dailymodelcycle.js b/apps/precipitation1hr/server/dataFunctions/data_dailymodelcycle.js
index fe955e3613..de3aedda2f 100644
--- a/apps/precipitation1hr/server/dataFunctions/data_dailymodelcycle.js
+++ b/apps/precipitation1hr/server/dataFunctions/data_dailymodelcycle.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDailyModelCycle = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,53 +24,42 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${grid_scale}${sourceStr}_${region} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap
).find(
@@ -78,6 +68,15 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
thresholdStr
);
const thresholdClause = `and m0.trsh = ${threshold * 0.01}`;
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+
if (curve["utc-cycle-start"].length !== 1) {
throw new Error(
"INFO: Please select exactly one UTC Cycle Init Hour for this plot type."
@@ -86,8 +85,11 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
const utcCycleStart = Number(curve["utc-cycle-start"][0]);
utcCycleStarts[curveIndex] = utcCycleStart;
const utcCycleStartClause = `and floor((m0.time - m0.fcst_len*3600)%(24*3600)/3600) IN(${utcCycleStart})`;
+
const forecastLengthClause = "and m0.fcst_len < 24";
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -95,11 +97,23 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.hit) as hit, sum(m0.fa) as fa, sum(m0.miss) as miss, sum(m0.cn) as cn, group_concat(m0.time, ';', m0.hit, ';', m0.fa, ';', m0.miss, ';', m0.cn order by m0.time) as sub_data, count(m0.hit) as N0";
+
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${scale}${source}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -107,46 +121,46 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.time as avtime, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{utcCycleStartClause}} " +
- "{{thresholdClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.time as avtime, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{utcCycleStartClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -162,6 +176,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -176,7 +191,6 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -201,6 +215,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipitation1hr/server/dataFunctions/data_dieoff.js b/apps/precipitation1hr/server/dataFunctions/data_dieoff.js
index b38a02403f..c6ea50ac19 100644
--- a/apps/precipitation1hr/server/dataFunctions/data_dieoff.js
+++ b/apps/precipitation1hr/server/dataFunctions/data_dieoff.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDieoff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,50 +24,38 @@ dataDieoff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${grid_scale}${sourceStr}_${region} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap
).find(
@@ -75,21 +64,52 @@ dataDieoff = function (plotParams, plotFunction) {
thresholdStr
);
const thresholdClause = `and m0.trsh = ${threshold * 0.01}`;
- var validTimes;
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+
let validTimeClause = "";
- var utcCycleStart;
+ let validTimes;
+
let utcCycleStartClause = "";
+ let utcCycleStart;
+
const forecastLengthStr = curve["dieoff-type"];
const forecastLengthOptionsMap = matsCollections["dieoff-type"].findOne(
{ name: "dieoff-type" },
{ optionsMap: 1 }
).optionsMap;
const forecastLength = forecastLengthOptionsMap[forecastLengthStr][0];
- const forecastLengthClause = "";
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ "sum(m0.hit) as hit, sum(m0.fa) as fa, sum(m0.miss) as miss, sum(m0.cn) as cn, group_concat(m0.time, ';', m0.hit, ';', m0.fa, ';', m0.miss, ';', m0.cn order by m0.time) as sub_data, count(m0.hit) as N0";
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
- var dateClause;
+ let dateClause;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${scale}${source}_${region} as m0`;
+
if (forecastLength === matsTypes.ForecastTypes.dieoff) {
validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
@@ -106,18 +126,12 @@ dataDieoff = function (plotParams, plotFunction) {
} else {
dateClause = `and m0.time-m0.fcst_len*3600 = ${fromSecs}`;
}
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- "sum(m0.hit) as hit, sum(m0.fa) as fa, sum(m0.miss) as miss, sum(m0.cn) as cn, group_concat(m0.time, ';', m0.hit, ';', m0.fa, ';', m0.miss, ';', m0.cn order by m0.time) as sub_data, count(m0.hit) as N0";
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -125,48 +139,46 @@ dataDieoff = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.fcst_len as fcst_lead, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{utcCycleStartClause}} " +
- "group by fcst_lead " +
- "order by fcst_lead" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.fcst_len as fcst_lead, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{utcCycleStartClause}} " +
+ "group by fcst_lead " +
+ "order by fcst_lead" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -182,6 +194,7 @@ dataDieoff = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -196,7 +209,6 @@ dataDieoff = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -221,6 +233,7 @@ dataDieoff = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipitation1hr/server/dataFunctions/data_histogram.js b/apps/precipitation1hr/server/dataFunctions/data_histogram.js
index 3f1324a817..466a9c0f4f 100644
--- a/apps/precipitation1hr/server/dataFunctions/data_histogram.js
+++ b/apps/precipitation1hr/server/dataFunctions/data_histogram.js
@@ -11,6 +11,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataHistogram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -21,53 +22,42 @@ dataHistogram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
- const alreadyMatched = false;
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
const dataFoundForCurve = [];
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+ const alreadyMatched = false;
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
+
+ const axisMap = Object.create(null);
+ let statType;
+ let varUnits;
+
+ let statement = "";
+ let error = "";
const dataset = [];
const allReturnedSubStats = [];
const allReturnedSubSecs = [];
- const axisMap = Object.create(null);
// process user bin customizations
const binParams = matsDataUtils.setHistogramParameters(plotParams);
const { yAxisFormat } = binParams;
const { binNum } = binParams;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
dataFoundForCurve[curveIndex] = true;
const { label } = curve;
+ const { diffFrom } = curve;
+
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${grid_scale}${sourceStr}_${region} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap
).find(
@@ -76,17 +66,26 @@ dataHistogram = function (plotParams, plotFunction) {
thresholdStr
);
const thresholdClause = `and m0.trsh = ${threshold * 0.01}`;
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
}
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -94,12 +93,26 @@ dataHistogram = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.hit) as hit, sum(m0.fa) as fa, sum(m0.miss) as miss, sum(m0.cn) as cn, group_concat(m0.time, ';', m0.hit, ';', m0.fa, ';', m0.miss, ';', m0.cn order by m0.time) as sub_data, count(m0.hit) as N0";
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${scale}${source}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
- var varUnits = statisticOptionsMap[statisticSelect][1];
+ [statType] = statisticOptionsMap[statisticSelect];
+ [, varUnits] = statisticOptionsMap[statisticSelect];
let axisKey = yAxisFormat;
if (yAxisFormat === "Relative frequency") {
axisKey += " (x100)";
@@ -107,46 +120,46 @@ dataHistogram = function (plotParams, plotFunction) {
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
curves[curveIndex].binNum = binNum; // stash the binNum to use it later for bar chart options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.time as avtime, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.time as avtime, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -164,6 +177,7 @@ dataHistogram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/precipitation1hr/server/dataFunctions/data_perfDiagram.js b/apps/precipitation1hr/server/dataFunctions/data_perfDiagram.js
index ea562f906e..2d30b32150 100644
--- a/apps/precipitation1hr/server/dataFunctions/data_perfDiagram.js
+++ b/apps/precipitation1hr/server/dataFunctions/data_perfDiagram.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataPerformanceDiagram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,61 +23,43 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statType;
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const binParam = curve["bin-parameter"];
const binClause = matsCollections["bin-parameter"].findOne({
name: "bin-parameter",
}).optionsMap[binParam];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${grid_scale}${sourceStr}_${region} as m0`;
+
let thresholdClause = "";
- let validTimeClause = "";
- let forecastLengthClause = "";
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let dateString = "";
- let dateClause = "";
if (binParam !== "Threshold") {
- var thresholdStr = curve.threshold;
+ const thresholdStr = curve.threshold;
if (thresholdStr === undefined) {
throw new Error(
`INFO: ${label}'s threshold is undefined. Please assign it a value.`
@@ -91,12 +74,24 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold * 0.01}`;
}
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+
+ let validTimeClause = "";
if (binParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.time%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (binParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
if (forecastLength === undefined) {
@@ -106,62 +101,81 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
}
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
+ const statisticSelect = "PerformanceDiagram";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ let dateString = "";
+ let dateClause = "";
if (binParam === "Init Date") {
dateString = "m0.time-m0.fcst_len*3600";
} else {
dateString = "m0.time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const statisticSelect = "PerformanceDiagram";
- var statType = "ctc";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${scale}${source}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// variable + statistic (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ statType = "ctc";
curves[curveIndex].axisKey = statisticSelect; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{binClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "((sum(m0.hit)+0.00)/sum(m0.hit+m0.miss)) as pod, ((sum(m0.fa)+0.00)/sum(m0.fa+m0.hit)) as far, " +
- "sum(m0.hit+m0.miss) as oy_all, sum(m0.fa+m0.cn) as on_all, group_concat(m0.time, ';', m0.hit, ';', " +
- "m0.fa, ';', m0.miss, ';', m0.cn order by m0.time) as sub_data, count(m0.hit) as N0 " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by binVal " +
- "order by binVal" +
- ";";
-
- statement = statement.replace("{{binClause}}", binClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "{{binClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "((sum(m0.hit)+0.00)/sum(m0.hit+m0.miss)) as pod, ((sum(m0.fa)+0.00)/sum(m0.fa+m0.hit)) as far, " +
+ "sum(m0.hit+m0.miss) as oy_all, sum(m0.fa+m0.cn) as on_all, group_concat(m0.time, ';', m0.hit, ';', " +
+ "m0.fa, ';', m0.miss, ';', m0.cn order by m0.time) as sub_data, count(m0.hit) as N0 " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by binVal " +
+ "order by binVal" +
+ ";";
+
+ statement = statement.replace("{{binClause}}", binClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBPerformanceDiagram(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -177,6 +191,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -198,7 +213,6 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -206,7 +220,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
ymax = ymax > d.ymax ? ymax : d.ymax;
}
} else {
- // this is a difference curve -- not supported for ROC plots
+ // this is a difference curve -- not supported for performance diagrams
throw new Error(
"INFO: Difference curves are not supported for performance diagrams, as they do not feature consistent x or y values across all curves."
);
@@ -214,6 +228,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipitation1hr/server/dataFunctions/data_series.js b/apps/precipitation1hr/server/dataFunctions/data_series.js
index 427ba3c98f..698d87c047 100644
--- a/apps/precipitation1hr/server/dataFunctions/data_series.js
+++ b/apps/precipitation1hr/server/dataFunctions/data_series.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSeries = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,53 +24,42 @@ dataSeries = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${grid_scale}${sourceStr}_${region} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap
).find(
@@ -78,20 +68,26 @@ dataSeries = function (plotParams, plotFunction) {
thresholdStr
);
const thresholdClause = `and m0.trsh = ${threshold * 0.01}`;
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
}
+
let forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
- const averageStr = curve.average;
- const averageOptionsMap = matsCollections.average.findOne(
- { name: "average" },
- { optionsMap: 1 }
- ).optionsMap;
- const average = averageOptionsMap[averageStr][0];
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -99,11 +95,30 @@ dataSeries = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.hit) as hit, sum(m0.fa) as fa, sum(m0.miss) as miss, sum(m0.cn) as cn, group_concat(m0.time, ';', m0.hit, ';', m0.fa, ';', m0.miss, ';', m0.cn order by m0.time) as sub_data, count(m0.hit) as N0";
+
+ const averageStr = curve.average;
+ const averageOptionsMap = matsCollections.average.findOne(
+ { name: "average" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const average = averageOptionsMap[averageStr][0];
+
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${scale}${source}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -111,47 +126,45 @@ dataSeries = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select {{average}} as avtime, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "select {{average}} as avtime, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
- statement = statement.replace("{{average}}", average);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
+ statement = statement.replace("{{average}}", average);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
- // math is done on forecastLength later on -- set all analyses to 0
- if (forecastLength === "-99") {
- forecastLength = "0";
- }
+ // math is done on forecastLength later on -- set all analyses to 0
+ if (forecastLength === "-99") {
+ forecastLength = "0";
+ }
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBTimeSeries(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
model,
forecastLength,
@@ -163,7 +176,9 @@ dataSeries = function (plotParams, plotFunction) {
appParams,
false
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -179,6 +194,7 @@ dataSeries = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -193,7 +209,6 @@ dataSeries = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -218,6 +233,7 @@ dataSeries = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipitation1hr/server/dataFunctions/data_threshold.js b/apps/precipitation1hr/server/dataFunctions/data_threshold.js
index 7769401475..a7f304c54f 100644
--- a/apps/precipitation1hr/server/dataFunctions/data_threshold.js
+++ b/apps/precipitation1hr/server/dataFunctions/data_threshold.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataThreshold = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,61 +24,56 @@ dataThreshold = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
matsCollections.scale.findOne({ name: "scale" }).valuesMap
).find(
(key) =>
matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
);
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${grid_scale}${sourceStr}_${region} as m0`;
- const thresholdClause = "";
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
}
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -85,11 +81,26 @@ dataThreshold = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.hit) as hit, sum(m0.fa) as fa, sum(m0.miss) as miss, sum(m0.cn) as cn, group_concat(m0.time, ';', m0.hit, ';', m0.fa, ';', m0.miss, ';', m0.cn order by m0.time) as sub_data, count(m0.hit) as N0";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${scale}${source}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -97,46 +108,44 @@ dataThreshold = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.trsh as thresh, " + // produces thresholds in in
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by thresh " +
- "order by thresh" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.trsh as thresh, " + // produces thresholds in in
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by thresh " +
+ "order by thresh" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -152,6 +161,7 @@ dataThreshold = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -173,7 +183,6 @@ dataThreshold = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -198,6 +207,7 @@ dataThreshold = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipitation1hr/server/dataFunctions/data_validtime.js b/apps/precipitation1hr/server/dataFunctions/data_validtime.js
index eae8cb0b8d..aab14f122b 100644
--- a/apps/precipitation1hr/server/dataFunctions/data_validtime.js
+++ b/apps/precipitation1hr/server/dataFunctions/data_validtime.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataValidTime = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,50 +24,38 @@ dataValidTime = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const source = curve.truth;
- let sourceStr = "";
- if (source !== "All") {
- sourceStr = `_${source}`;
- }
- const queryTableClause = `from ${model}_${grid_scale}${sourceStr}_${region} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap
).find(
@@ -75,12 +64,20 @@ dataValidTime = function (plotParams, plotFunction) {
thresholdStr
);
const thresholdClause = `and m0.trsh = ${threshold * 0.01}`;
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const source = curve.truth === "All" ? "" : `_${curve.truth}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -88,11 +85,26 @@ dataValidTime = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.hit) as hit, sum(m0.fa) as fa, sum(m0.miss) as miss, sum(m0.cn) as cn, group_concat(m0.time, ';', m0.hit, ';', m0.fa, ';', m0.miss, ';', m0.cn order by m0.time) as sub_data, count(m0.hit) as N0";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_${scale}${source}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -100,44 +112,44 @@ dataValidTime = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select floor(m0.time%(24*3600)/3600) as hr_of_day, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{forecastLengthClause}} " +
- "group by hr_of_day " +
- "order by hr_of_day" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select floor(m0.time%(24*3600)/3600) as hr_of_day, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by hr_of_day " +
+ "order by hr_of_day" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -153,6 +165,7 @@ dataValidTime = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -167,7 +180,6 @@ dataValidTime = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -192,6 +204,7 @@ dataValidTime = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/precipitation1hr/server/main.js b/apps/precipitation1hr/server/main.js
index cc3538dd26..29c9162f25 100644
--- a/apps/precipitation1hr/server/main.js
+++ b/apps/precipitation1hr/server/main.js
@@ -4,7 +4,9 @@
import { Meteor } from "meteor/meteor";
import { mysql } from "meteor/pcel:mysql";
+import { moment } from "meteor/momentjs:moment";
import {
+ matsMethods,
matsTypes,
matsCollections,
matsDataUtils,
@@ -319,10 +321,11 @@ const doCurveParams = function () {
const params = matsCollections.CurveParamsInfo.find({
curve_params: { $exists: true },
}).fetch()[0].curve_params;
- for (let cp = 0; cp < params.length; cp++) {
+ for (let cp = 0; cp < params.length; cp += 1) {
matsCollections[params[cp]].remove({});
}
}
+
const modelOptionsMap = {};
let modelDateRangeMap = {};
const regionModelOptionsMap = {};
@@ -330,128 +333,105 @@ const doCurveParams = function () {
const thresholdsModelOptionsMap = {};
const scaleModelOptionsMap = {};
const sourceOptionsMap = {};
- const masterRegionValuesMap = {};
- const masterThresholdValuesMap = {};
- const masterScaleValuesMap = {};
+ const allRegionValuesMap = {};
+ const allThresholdValuesMap = {};
+ const allScaleValuesMap = {};
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- metadataPool,
+ metadataPool, // eslint-disable-line no-undef
"select short_name,description from region_descriptions;"
);
- let masterRegDescription;
- let masterShortName;
- for (var j = 0; j < rows.length; j++) {
- masterRegDescription = rows[j].description.trim();
- masterShortName = rows[j].short_name.trim();
- masterRegionValuesMap[masterShortName] = masterRegDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allRegionValuesMap[rows[j].short_name.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select trsh,description from threshold_descriptions;"
);
- let masterDescription;
- let masterTrsh;
- for (var j = 0; j < rows.length; j++) {
- masterDescription = rows[j].description.trim();
- masterTrsh = rows[j].trsh.trim();
- masterThresholdValuesMap[masterTrsh] = masterDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allThresholdValuesMap[rows[j].trsh.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select scle,description from scale_descriptions;"
);
- let masterScaleDescription;
- let masterScale;
- for (var j = 0; j < rows.length; j++) {
- masterScaleDescription = rows[j].description.trim();
- masterScale = rows[j].scle.trim();
- masterScaleValuesMap[masterScale] = masterScaleDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allScaleValuesMap[rows[j].scle.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select model,regions,sources,display_text,fcst_lens,thresh,scale,mindate,maxdate from regions_per_model_mats_all_categories order by display_category, display_order;"
);
- for (let i = 0; i < rows.length; i++) {
- const model_value = rows[i].model.trim();
+ for (let i = 0; i < rows.length; i += 1) {
+ const modelValue = rows[i].model.trim();
const model = rows[i].display_text.trim();
- modelOptionsMap[model] = [model_value];
+ modelOptionsMap[model] = [modelValue];
const rowMinDate = moment.utc(rows[i].mindate * 1000).format("MM/DD/YYYY HH:mm");
const rowMaxDate = moment.utc(rows[i].maxdate * 1000).format("MM/DD/YYYY HH:mm");
- modelDateRangeMap[model] = { minDate: rowMinDate, maxDate: rowMaxDate };
+ modelDateRangeMap[model] = {
+ minDate: rowMinDate,
+ maxDate: rowMaxDate,
+ };
const { sources } = rows[i];
- const sourceArr = sources
+ sourceOptionsMap[model] = sources
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (var j = 0; j < sourceArr.length; j++) {
- sourceArr[j] = sourceArr[j].replace(/'|\[|\]/g, "");
- }
- sourceOptionsMap[model] = sourceArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (source) {
+ return source.replace(/'|\[|\]/g, "");
+ });
const forecastLengths = rows[i].fcst_lens;
- const forecastLengthArr = forecastLengths
+ forecastLengthOptionsMap[model] = forecastLengths
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (var j = 0; j < forecastLengthArr.length; j++) {
- forecastLengthArr[j] = forecastLengthArr[j].replace(/'|\[|\]/g, "");
- }
- forecastLengthOptionsMap[model] = forecastLengthArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (fhr) {
+ return fhr.replace(/'|\[|\]/g, "");
+ });
const thresholds = rows[i].thresh;
- const thresholdsArrRaw = thresholds
+ thresholdsModelOptionsMap[model] = thresholds
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const thresholdsArr = [];
- var dummyThresh;
- for (var j = 0; j < thresholdsArrRaw.length; j++) {
- dummyThresh = thresholdsArrRaw[j].replace(/'|\[|\]/g, "");
- thresholdsArr.push(masterThresholdValuesMap[dummyThresh]);
- }
- thresholdsModelOptionsMap[model] = thresholdsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (threshold) {
+ return allThresholdValuesMap[threshold.replace(/'|\[|\]/g, "")];
+ });
const scales = rows[i].scale;
- const scalesArrRaw = scales
+ scaleModelOptionsMap[model] = scales
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const scalesArr = [];
- var dummyScale;
- for (var j = 0; j < scalesArrRaw.length; j++) {
- dummyScale = scalesArrRaw[j].replace(/'|\[|\]/g, "");
- scalesArr.push(masterScaleValuesMap[dummyScale]);
- }
- scaleModelOptionsMap[model] = scalesArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (scale) {
+ return allScaleValuesMap[scale.replace(/'|\[|\]/g, "")];
+ });
const { regions } = rows[i];
- const regionsArrRaw = regions
+ regionModelOptionsMap[model] = regions
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const regionsArr = [];
- var dummyRegion;
- for (var j = 0; j < regionsArrRaw.length; j++) {
- dummyRegion = regionsArrRaw[j].replace(/'|\[|\]/g, "");
- regionsArr.push(masterRegionValuesMap[dummyRegion]);
- }
- regionModelOptionsMap[model] = regionsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (region) {
+ return allRegionValuesMap[region.replace(/'|\[|\]/g, "")];
+ });
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
if (matsCollections.label.findOne({ name: "label" }) === undefined) {
@@ -497,7 +477,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["data-source"].findOne({ name: "data-source" });
+ const currentParam = matsCollections["data-source"].findOne({
+ name: "data-source",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap) ||
!matsDataUtils.areObjectsEqual(currentParam.dates, modelDateRangeMap)
@@ -523,7 +505,7 @@ const doCurveParams = function () {
type: matsTypes.InputTypes.select,
optionsMap: regionModelOptionsMap,
options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]],
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
superiorNames: ["data-source"],
controlButtonCovered: true,
unique: false,
@@ -535,10 +517,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.region.findOne({ name: "region" });
+ const currentParam = matsCollections.region.findOne({ name: "region" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, regionModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterRegionValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allRegionValuesMap)
) {
// have to reload region data
matsCollections.region.update(
@@ -546,7 +528,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: regionModelOptionsMap,
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]],
default: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]][0],
},
@@ -618,7 +600,7 @@ const doCurveParams = function () {
type: matsTypes.InputTypes.select,
optionsMap: thresholdsModelOptionsMap,
options: thresholdsModelOptionsMap[Object.keys(thresholdsModelOptionsMap)[0]],
- valuesMap: masterThresholdValuesMap,
+ valuesMap: allThresholdValuesMap,
superiorNames: ["data-source"],
controlButtonCovered: true,
unique: false,
@@ -630,13 +612,13 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.threshold.findOne({ name: "threshold" });
+ const currentParam = matsCollections.threshold.findOne({ name: "threshold" });
if (
!matsDataUtils.areObjectsEqual(
currentParam.optionsMap,
thresholdsModelOptionsMap
) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterThresholdValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allThresholdValuesMap)
) {
// have to reload threshold data
matsCollections.threshold.update(
@@ -644,7 +626,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: thresholdsModelOptionsMap,
- valuesMap: masterThresholdValuesMap,
+ valuesMap: allThresholdValuesMap,
options:
thresholdsModelOptionsMap[Object.keys(thresholdsModelOptionsMap)[0]],
default:
@@ -661,7 +643,7 @@ const doCurveParams = function () {
type: matsTypes.InputTypes.select,
optionsMap: scaleModelOptionsMap,
options: scaleModelOptionsMap[Object.keys(scaleModelOptionsMap)[0]],
- valuesMap: masterScaleValuesMap,
+ valuesMap: allScaleValuesMap,
superiorNames: ["data-source"],
controlButtonCovered: true,
unique: false,
@@ -673,10 +655,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.scale.findOne({ name: "scale" });
+ const currentParam = matsCollections.scale.findOne({ name: "scale" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, scaleModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterScaleValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allScaleValuesMap)
) {
// have to reload scale data
matsCollections.scale.update(
@@ -684,7 +666,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: scaleModelOptionsMap,
- valuesMap: masterScaleValuesMap,
+ valuesMap: allScaleValuesMap,
options: scaleModelOptionsMap[Object.keys(scaleModelOptionsMap)[0]],
default: scaleModelOptionsMap[Object.keys(scaleModelOptionsMap)[0]][0],
},
@@ -710,7 +692,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.truth.findOne({ name: "truth" });
+ const currentParam = matsCollections.truth.findOne({ name: "truth" });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, sourceOptionsMap)) {
// have to reload truth data
matsCollections.truth.update(
@@ -748,7 +730,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["forecast-length"].findOne({
+ const currentParam = matsCollections["forecast-length"].findOne({
name: "forecast-length",
});
if (
@@ -1023,7 +1005,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["curve-dates"].findOne({ name: "curve-dates" });
+ const currentParam = matsCollections["curve-dates"].findOne({
+ name: "curve-dates",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.startDate, minDate) ||
!matsDataUtils.areObjectsEqual(currentParam.stopDate, maxDate) ||
@@ -1387,7 +1371,8 @@ const doPlotGraph = function () {
Meteor.startup(function () {
matsCollections.Databases.remove({});
if (matsCollections.Databases.find({}).count() < 0) {
- console.log(
+ // eslint-disable-next-line no-console
+ console.warn(
"main startup: corrupted Databases collection: dropping Databases collection"
);
matsCollections.Databases.drop();
@@ -1404,7 +1389,7 @@ Meteor.startup(function () {
databases = Meteor.settings.private.databases;
}
if (databases !== null && databases !== undefined && Array.isArray(databases)) {
- for (let di = 0; di < databases.length; di++) {
+ for (let di = 0; di < databases.length; di += 1) {
matsCollections.Databases.insert(databases[di]);
}
}
@@ -1431,6 +1416,7 @@ Meteor.startup(function () {
);
if (cbConnection) {
// global cbScorecardSettingsPool
+ // eslint-disable-next-line no-undef
cbScorecardSettingsPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1457,6 +1443,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (metadataSettings) {
+ // eslint-disable-next-line no-undef
metadataPool = mysql.createPool(metadataSettings);
allPools.push({ pool: "metadataPool", role: matsTypes.DatabaseRoles.META_DATA });
}
@@ -1477,6 +1464,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (sumSettings) {
+ // eslint-disable-next-line no-undef
sumPool = mysql.createPool(sumSettings);
allPools.push({ pool: "sumPool", role: matsTypes.DatabaseRoles.SUMS_DATA });
}
@@ -1497,7 +1485,7 @@ Meteor.startup(function () {
appType: matsTypes.AppTypes.mats,
});
} catch (error) {
- console.log(error.message);
+ throw new Error(error.message);
}
});
@@ -1505,6 +1493,7 @@ Meteor.startup(function () {
// These are application specific mongo data - like curve params
// The appSpecificResetRoutines object is a special name,
// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way.
+// eslint-disable-next-line no-undef
appSpecificResetRoutines = [
doPlotGraph,
doCurveParams,
diff --git a/apps/ptype/.eslintrc.json b/apps/ptype/.eslintrc.json
index 8b795b7df7..79d49c5bb6 100644
--- a/apps/ptype/.eslintrc.json
+++ b/apps/ptype/.eslintrc.json
@@ -28,22 +28,6 @@
"space-before-function-paren": "off",
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
- "prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
- "no-undef": "warn",
- "no-plusplus": "warn",
- "vars-on-top": "warn",
- "no-var": "warn",
- "block-scoped-var": "warn",
- "no-loop-func": "warn",
- "no-unused-vars": "warn",
- "prefer-destructuring": "warn",
- "no-param-reassign": "warn",
- "camelcase": "warn",
- "no-redeclare": "warn"
+ "prefer-arrow-callback": "off"
}
}
diff --git a/apps/ptype/client/main.js b/apps/ptype/client/main.js
index a87407a1f4..ecd922b6a2 100644
--- a/apps/ptype/client/main.js
+++ b/apps/ptype/client/main.js
@@ -2,6 +2,7 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+// eslint-disable-next-line no-unused-vars
import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common";
import "@fortawesome/fontawesome-free";
import "@fortawesome/fontawesome-free/css/all.css";
diff --git a/apps/ptype/server/dataFunctions/data_contour.js b/apps/ptype/server/dataFunctions/data_contour.js
index bf0950d1fb..70c7edaf16 100644
--- a/apps/ptype/server/dataFunctions/data_contour.js
+++ b/apps/ptype/server/dataFunctions/data_contour.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContour = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,70 +23,92 @@ dataContour = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
- const totalProcessingStart = moment();
+
+ const curves = JSON.parse(JSON.stringify(plotParams.curves));
+ if (curves.length > 1) {
+ throw new Error("INFO: There must only be one added curve.");
+ }
+
+ const axisMap = Object.create(null);
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- const curves = JSON.parse(JSON.stringify(plotParams.curves));
- if (curves.length > 1) {
- throw new Error("INFO: There must only be one added curve.");
- }
- const dataset = [];
- const axisMap = Object.create(null);
- // initialize variables specific to the curve
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- const regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${model}_freq_${region} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
- let validTimeClause = "";
+
let scaleClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
+ const scaleStr = curve.scale;
+ if (xAxisParam !== "Grid scale" && yAxisParam !== "Grid scale") {
+ if (scaleStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s grid scale is undefined. Please assign it a value.`
+ );
+ }
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+ scaleClause = `and m0.scale = ${scale} `;
+ }
+
+ let validTimeClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.valid_secs%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = Number(curve["forecast-length"]) * 60;
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
- if (xAxisParam !== "Grid scale" && yAxisParam !== "Grid scale") {
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- scaleClause = `and m0.scale = ${grid_scale} `;
- }
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause = statisticOptionsMap[statisticSelect][0];
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -96,102 +119,113 @@ dataContour = function (plotParams, plotFunction) {
dateString = "m0.valid_secs";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause = statisticOptionsMap[statisticSelect][0];
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_freq_${region} as m0`;
+
// For contours, this functions as the colorbar label.
const statType = statisticOptionsMap[statisticSelect][1];
- curve.unitKey = statisticOptionsMap[statisticSelect][2];
+ [, , curve.unitKey] = statisticOptionsMap[statisticSelect];
let d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{scaleClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
-
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{scaleClause}}", scaleClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- statement = statement.split("{{variable}}").join(variable);
- dataRequests[label] = statement;
-
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- if (error.includes("ER_NO_SUCH_TABLE")) {
- throw new Error(
- `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${dataSourceStr}]. ` +
- `Choose a different scale to continue using this region.`
- );
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{scaleClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
+
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{scaleClause}}", scaleClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ statement = statement.split("{{variable}}").join(variable);
+ dataRequests[label] = statement;
+
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
+ }
+
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
+ // this is NOT an error just a no data condition
+ dataFoundForCurve = false;
} else {
- throw new Error(error);
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ if (error.includes("ER_NO_SUCH_TABLE")) {
+ throw new Error(
+ `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` +
+ `Choose a different scale to continue using this region.`
+ );
+ } else {
+ throw new Error(error);
+ }
}
}
- }
- if (!dataFoundForCurve) {
- // we found no data for any curves so don't bother proceeding
- throw new Error("INFO: No valid data for any curves.");
+ if (!dataFoundForCurve) {
+ // we found no data for any curves so don't bother proceeding
+ throw new Error("INFO: No valid data for any curves.");
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
}
- const postQueryStartMoment = moment();
-
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
diff --git a/apps/ptype/server/dataFunctions/data_contour_diff.js b/apps/ptype/server/dataFunctions/data_contour_diff.js
index 2032dc5d99..df2e01a320 100644
--- a/apps/ptype/server/dataFunctions/data_contour_diff.js
+++ b/apps/ptype/server/dataFunctions/data_contour_diff.js
@@ -14,6 +14,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContourDiff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -24,74 +25,98 @@ dataContourDiff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
let dataNotFoundForAnyCurve = false;
- const showSignificance = false;
- const totalProcessingStart = moment();
+
+ let curves = JSON.parse(JSON.stringify(plotParams.curves));
+ const curvesLength = curves.length;
+ if (curvesLength !== 2) {
+ throw new Error("INFO: There must be two added curves.");
+ }
+
+ const axisMap = Object.create(null);
+ const showSignificance = plotParams.significance !== "none";
+
+ let statType;
+ let statisticSelect;
+
+ let statement = "";
+ let error = "";
+ let dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- let curves = JSON.parse(JSON.stringify(plotParams.curves));
- const curvesLength = curves.length;
- if (curvesLength !== 2) {
- throw new Error("INFO: There must be two added curves.");
- }
- let dataset = [];
- const axisMap = Object.create(null);
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${model}_freq_${region} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
- let validTimeClause = "";
+
let scaleClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
+ const scaleStr = curve.scale;
+ if (xAxisParam !== "Grid scale" && yAxisParam !== "Grid scale") {
+ if (scaleStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s grid scale is undefined. Please assign it a value.`
+ );
+ }
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+ scaleClause = `and m0.scale = ${scale} `;
+ }
+
+ let validTimeClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.valid_secs%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = Number(curve["forecast-length"]) * 60;
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
- if (xAxisParam !== "Grid scale" && yAxisParam !== "Grid scale") {
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- scaleClause = `and m0.scale = ${grid_scale} `;
- }
+
+ statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause = statisticOptionsMap[statisticSelect][0];
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -102,98 +127,106 @@ dataContourDiff = function (plotParams, plotFunction) {
dateString = "m0.valid_secs";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- var statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause = statisticOptionsMap[statisticSelect][0];
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_freq_${region} as m0`;
+
// For contours, this functions as the colorbar label.
- var statType = statisticOptionsMap[statisticSelect][1];
- curves[curveIndex].unitKey = statisticOptionsMap[statisticSelect][2];
+ [, statType] = statisticOptionsMap[statisticSelect];
+ [, , curve.unitKey] = statisticOptionsMap[statisticSelect];
- var d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{scaleClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
+ let d;
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{scaleClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{scaleClause}}", scaleClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- statement = statement.split("{{variable}}").join(variable);
- dataRequests[label] = statement;
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{scaleClause}}", scaleClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ statement = statement.split("{{variable}}").join(variable);
+ dataRequests[label] = statement;
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- if (error.includes("ER_NO_SUCH_TABLE")) {
- throw new Error(
- `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${dataSourceStr}]. ` +
- `Choose a different scale to continue using this region.`
- );
- } else {
- throw new Error(error);
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
+ }
+
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ if (error.includes("ER_NO_SUCH_TABLE")) {
+ throw new Error(
+ `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` +
+ `Choose a different scale to continue using this region.`
+ );
+ } else {
+ throw new Error(error);
+ }
}
+ dataNotFoundForAnyCurve = true;
}
- dataNotFoundForAnyCurve = true;
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
}
- const postQueryStartMoment = moment();
-
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
@@ -239,14 +272,17 @@ dataContourDiff = function (plotParams, plotFunction) {
showSignificance,
undefined,
statisticSelect,
- statType === "ctc"
+ statType === "ctc",
+ statType === "scalar"
);
- plotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
- curves = plotParams.curves;
+ const newPlotParams = plotParams;
+ newPlotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
+ curves = newPlotParams.curves;
dataset[0].name = matsPlotUtils.getCurveText(
matsTypes.PlotTypes.contourDiff,
curves[0]
);
+ dataset[1] = matsDataCurveOpsUtils.getContourSignificanceLayer(dataset);
// process the data returned by the query
const curveInfoParams = { curve: curves, statType, axisMap };
@@ -257,7 +293,7 @@ dataContourDiff = function (plotParams, plotFunction) {
const result = matsDataProcessUtils.processDataContour(
dataset,
curveInfoParams,
- plotParams,
+ newPlotParams,
bookkeepingParams
);
plotFunction(result);
diff --git a/apps/ptype/server/dataFunctions/data_dailymodelcycle.js b/apps/ptype/server/dataFunctions/data_dailymodelcycle.js
index adef91b43b..e0e8cb890d 100644
--- a/apps/ptype/server/dataFunctions/data_dailymodelcycle.js
+++ b/apps/ptype/server/dataFunctions/data_dailymodelcycle.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDailyModelCycle = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,54 +24,57 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const scaleClause = `and m0.scale = ${grid_scale}`;
- const queryTableClause = `from ${model}_freq_${region} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+ const scaleClause = `and m0.scale = ${scale}`;
+
if (curve["utc-cycle-start"].length !== 1) {
throw new Error(
"INFO: Please select exactly one UTC Cycle Init Hour for this plot type."
@@ -79,19 +83,32 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
const utcCycleStart = Number(curve["utc-cycle-start"][0]);
utcCycleStarts[curveIndex] = utcCycleStart;
const utcCycleStartClause = `and floor(((m0.valid_secs - m0.fcst_len*60))%(24*3600)/900)/4 IN(${utcCycleStart})`;
+
const forecastLengthClause = "and m0.fcst_len < 24 * 60";
- const dateClause = `and m0.valid_secs >= ${fromSecs} and m0.valid_secs <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap;
const statisticClause = statisticOptionsMap[statisticSelect][0];
+
+ const dateClause = `and m0.valid_secs >= ${fromSecs} and m0.valid_secs <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_freq_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][1];
+ [, statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][2];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][3];
@@ -99,47 +116,47 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.valid_secs as avtime, " +
- "count(distinct m0.valid_secs) as N_times, " +
- "min(m0.valid_secs) as min_secs, " +
- "max(m0.valid_secs) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{utcCycleStartClause}} " +
- "{{forecastLengthClause}} " +
- "{{scaleClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{scaleClause}}", scaleClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{variable}}").join(variable);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.valid_secs as avtime, " +
+ "count(distinct m0.valid_secs) as N_times, " +
+ "min(m0.valid_secs) as min_secs, " +
+ "max(m0.valid_secs) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{utcCycleStartClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{scaleClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{scaleClause}}", scaleClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{variable}}").join(variable);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -155,6 +172,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -164,7 +182,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
if (error.includes("ER_NO_SUCH_TABLE")) {
throw new Error(
- `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${dataSourceStr}]. ` +
+ `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` +
`Choose a different scale to continue using this region.`
);
} else {
@@ -176,7 +194,6 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -201,6 +218,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ptype/server/dataFunctions/data_dieoff.js b/apps/ptype/server/dataFunctions/data_dieoff.js
index 2bdf9b33d5..92a663f780 100644
--- a/apps/ptype/server/dataFunctions/data_dieoff.js
+++ b/apps/ptype/server/dataFunctions/data_dieoff.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDieoff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,65 +24,87 @@ dataDieoff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const scaleClause = `and m0.scale = ${grid_scale}`;
- const queryTableClause = `from ${model}_freq_${region} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
- var validTimes;
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+ const scaleClause = `and m0.scale = ${scale}`;
+
let validTimeClause = "";
- var utcCycleStart;
+ let validTimes;
+
let utcCycleStartClause = "";
+ let utcCycleStart;
+
const forecastLengthStr = curve["dieoff-type"];
const forecastLengthOptionsMap = matsCollections["dieoff-type"].findOne(
{ name: "dieoff-type" },
{ optionsMap: 1 }
).optionsMap;
const forecastLength = forecastLengthOptionsMap[forecastLengthStr][0];
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause = statisticOptionsMap[statisticSelect][0];
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
- var dateClause;
+ let dateClause;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_freq_${region} as m0`;
+
if (forecastLength === matsTypes.ForecastTypes.dieoff) {
validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
@@ -98,17 +121,12 @@ dataDieoff = function (plotParams, plotFunction) {
} else {
dateClause = `and m0.valid_secs-m0.fcst_len*60 = ${fromSecs}`;
}
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause = statisticOptionsMap[statisticSelect][0];
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][1];
+ [, statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][2];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][3];
@@ -116,47 +134,47 @@ dataDieoff = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.fcst_len/60 as fcst_lead, " +
- "count(distinct m0.valid_secs) as N_times, " +
- "min(m0.valid_secs) as min_secs, " +
- "max(m0.valid_secs) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{utcCycleStartClause}} " +
- "{{scaleClause}} " +
- "group by fcst_lead " +
- "order by fcst_lead" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{scaleClause}}", scaleClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{variable}}").join(variable);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.fcst_len/60 as fcst_lead, " +
+ "count(distinct m0.valid_secs) as N_times, " +
+ "min(m0.valid_secs) as min_secs, " +
+ "max(m0.valid_secs) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{utcCycleStartClause}} " +
+ "{{scaleClause}} " +
+ "group by fcst_lead " +
+ "order by fcst_lead" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{scaleClause}}", scaleClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{variable}}").join(variable);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -172,6 +190,7 @@ dataDieoff = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -181,7 +200,7 @@ dataDieoff = function (plotParams, plotFunction) {
error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
if (error.includes("ER_NO_SUCH_TABLE")) {
throw new Error(
- `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${dataSourceStr}]. ` +
+ `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` +
`Choose a different scale to continue using this region.`
);
} else {
@@ -193,7 +212,6 @@ dataDieoff = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -218,6 +236,7 @@ dataDieoff = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ptype/server/dataFunctions/data_histogram.js b/apps/ptype/server/dataFunctions/data_histogram.js
index e3ffa28416..26433dab5e 100644
--- a/apps/ptype/server/dataFunctions/data_histogram.js
+++ b/apps/ptype/server/dataFunctions/data_histogram.js
@@ -11,6 +11,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataHistogram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -21,76 +22,90 @@ dataHistogram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
- const alreadyMatched = false;
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
const dataFoundForCurve = [];
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+ const alreadyMatched = false;
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
+
+ const axisMap = Object.create(null);
+ let statType;
+
+ let statement = "";
+ let error = "";
const dataset = [];
const allReturnedSubStats = [];
const allReturnedSubSecs = [];
- const axisMap = Object.create(null);
// process user bin customizations
const binParams = matsDataUtils.setHistogramParameters(plotParams);
const { yAxisFormat } = binParams;
const { binNum } = binParams;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
dataFoundForCurve[curveIndex] = true;
const { label } = curve;
+ const { diffFrom } = curve;
+
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const scaleClause = `and m0.scale = ${grid_scale}`;
- const queryTableClause = `from ${model}_freq_${region} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+ const scaleClause = `and m0.scale = ${scale}`;
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and (m0.valid_secs)%(24*3600)/3600 IN(${validTimes})`;
}
+
const forecastLength = Number(curve["forecast-length"]) * 60;
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.valid_secs >= ${fromSecs} and m0.valid_secs <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap;
const statisticClause = statisticOptionsMap[statisticSelect][0];
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.valid_secs >= ${fromSecs} and m0.valid_secs <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_freq_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][1];
+ [, statType] = statisticOptionsMap[statisticSelect];
let axisKey = yAxisFormat;
if (yAxisFormat === "Relative frequency") {
axisKey += " (x100)";
@@ -98,47 +113,47 @@ dataHistogram = function (plotParams, plotFunction) {
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
curves[curveIndex].binNum = binNum; // stash the binNum to use it later for bar chart options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.valid_secs as avtime, " +
- "count(distinct m0.valid_secs) as N_times, " +
- "min(m0.valid_secs) as min_secs, " +
- "max(m0.valid_secs) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{scaleClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{scaleClause}}", scaleClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{variable}}").join(variable);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.valid_secs as avtime, " +
+ "count(distinct m0.valid_secs) as N_times, " +
+ "min(m0.valid_secs) as min_secs, " +
+ "max(m0.valid_secs) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{scaleClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{scaleClause}}", scaleClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{variable}}").join(variable);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -156,6 +171,7 @@ dataHistogram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -165,7 +181,7 @@ dataHistogram = function (plotParams, plotFunction) {
error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
if (error.includes("ER_NO_SUCH_TABLE")) {
throw new Error(
- `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${dataSourceStr}]. ` +
+ `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` +
`Choose a different scale to continue using this region.`
);
} else {
diff --git a/apps/ptype/server/dataFunctions/data_series.js b/apps/ptype/server/dataFunctions/data_series.js
index 35370a86bc..00cf621146 100644
--- a/apps/ptype/server/dataFunctions/data_series.js
+++ b/apps/ptype/server/dataFunctions/data_series.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSeries = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,79 +24,96 @@ dataSeries = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const scaleClause = `and m0.scale = ${grid_scale}`;
- const queryTableClause = `from ${model}_freq_${region} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+ const scaleClause = `and m0.scale = ${scale}`;
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and (m0.valid_secs)%(24*3600)/3600 IN(${validTimes})`;
}
+
let forecastLength = Number(curve["forecast-length"]) * 60;
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateClause = `and m0.valid_secs >= ${fromSecs} and m0.valid_secs <= ${toSecs}`;
- const averageStr = curve.average;
- const averageOptionsMap = matsCollections.average.findOne(
- { name: "average" },
- { optionsMap: 1 }
- ).optionsMap;
- const average = averageOptionsMap[averageStr][0];
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap;
const statisticClause = statisticOptionsMap[statisticSelect][0];
+
+ const averageStr = curve.average;
+ const averageOptionsMap = matsCollections.average.findOne(
+ { name: "average" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const average = averageOptionsMap[averageStr][0];
+
+ const dateClause = `and m0.valid_secs >= ${fromSecs} and m0.valid_secs <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_freq_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][1];
+ [, statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][2];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][3];
@@ -103,48 +121,46 @@ dataSeries = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select {{average}} as avtime, " +
- "count(distinct m0.valid_secs) as N_times, " +
- "min(m0.valid_secs) as min_secs, " +
- "max(m0.valid_secs) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{scaleClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "select {{average}} as avtime, " +
+ "count(distinct m0.valid_secs) as N_times, " +
+ "min(m0.valid_secs) as min_secs, " +
+ "max(m0.valid_secs) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{scaleClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
- statement = statement.replace("{{average}}", average);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{scaleClause}}", scaleClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{variable}}").join(variable);
- dataRequests[label] = statement;
+ statement = statement.replace("{{average}}", average);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{scaleClause}}", scaleClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{variable}}").join(variable);
+ dataRequests[label] = statement;
- // math is done on forecastLength later on -- set all analyses to 0
- if (forecastLength === "-99") {
- forecastLength = "0";
- }
+ // math is done on forecastLength later on -- set all analyses to 0
+ if (forecastLength === "-99") {
+ forecastLength = "0";
+ }
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBTimeSeries(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
model,
forecastLength,
@@ -156,7 +172,9 @@ dataSeries = function (plotParams, plotFunction) {
appParams,
false
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -172,6 +190,7 @@ dataSeries = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -181,7 +200,7 @@ dataSeries = function (plotParams, plotFunction) {
error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
if (error.includes("ER_NO_SUCH_TABLE")) {
throw new Error(
- `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${dataSourceStr}]. ` +
+ `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` +
`Choose a different scale to continue using this region.`
);
} else {
@@ -193,7 +212,6 @@ dataSeries = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -218,6 +236,7 @@ dataSeries = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ptype/server/dataFunctions/data_validtime.js b/apps/ptype/server/dataFunctions/data_validtime.js
index 7f3c96d483..78154000ee 100644
--- a/apps/ptype/server/dataFunctions/data_validtime.js
+++ b/apps/ptype/server/dataFunctions/data_validtime.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataValidTime = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,68 +24,82 @@ dataValidTime = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const scaleClause = `and m0.scale = ${grid_scale}`;
- const queryTableClause = `from ${model}_freq_${region} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+ const scaleClause = `and m0.scale = ${scale}`;
+
const forecastLength = Number(curve["forecast-length"]) * 60;
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.valid_secs >= ${fromSecs} and m0.valid_secs <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap;
const statisticClause = statisticOptionsMap[statisticSelect][0];
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.valid_secs >= ${fromSecs} and m0.valid_secs <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${model}_freq_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][1];
+ [, statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][2];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][3];
@@ -92,45 +107,45 @@ dataValidTime = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select floor((m0.valid_secs)%(24*3600)/900)/4 as hr_of_day, " +
- "count(distinct m0.valid_secs) as N_times, " +
- "min(m0.valid_secs) as min_secs, " +
- "max(m0.valid_secs) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{forecastLengthClause}} " +
- "{{scaleClause}} " +
- "group by hr_of_day " +
- "order by hr_of_day" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{scaleClause}}", scaleClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{variable}}").join(variable);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select floor((m0.valid_secs)%(24*3600)/900)/4 as hr_of_day, " +
+ "count(distinct m0.valid_secs) as N_times, " +
+ "min(m0.valid_secs) as min_secs, " +
+ "max(m0.valid_secs) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{scaleClause}} " +
+ "group by hr_of_day " +
+ "order by hr_of_day" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{scaleClause}}", scaleClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{variable}}").join(variable);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -146,6 +161,7 @@ dataValidTime = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -155,7 +171,7 @@ dataValidTime = function (plotParams, plotFunction) {
error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
if (error.includes("ER_NO_SUCH_TABLE")) {
throw new Error(
- `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${dataSourceStr}]. ` +
+ `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` +
`Choose a different scale to continue using this region.`
);
} else {
@@ -167,7 +183,6 @@ dataValidTime = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -192,6 +207,7 @@ dataValidTime = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/ptype/server/main.js b/apps/ptype/server/main.js
index 8e1efa8af2..baf82d999b 100644
--- a/apps/ptype/server/main.js
+++ b/apps/ptype/server/main.js
@@ -4,7 +4,9 @@
import { Meteor } from "meteor/meteor";
import { mysql } from "meteor/pcel:mysql";
+import { moment } from "meteor/momentjs:moment";
import {
+ matsMethods,
matsTypes,
matsCollections,
matsDataUtils,
@@ -304,118 +306,99 @@ const doCurveParams = function () {
const params = matsCollections.CurveParamsInfo.find({
curve_params: { $exists: true },
}).fetch()[0].curve_params;
- for (let cp = 0; cp < params.length; cp++) {
+ for (let cp = 0; cp < params.length; cp += 1) {
matsCollections[params[cp]].remove({});
}
}
+
const modelOptionsMap = {};
let modelDateRangeMap = {};
const regionModelOptionsMap = {};
const forecastLengthOptionsMap = {};
const scaleModelOptionsMap = {};
- const masterRegionValuesMap = {};
- const masterScaleValuesMap = {};
- const masterVariableValuesMap = {};
+ const allRegionValuesMap = {};
+ const allScaleValuesMap = {};
+ const allVariableValuesMap = {};
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- metadataPool,
+ metadataPool, // eslint-disable-line no-undef
"select short_name,description from region_descriptions;"
);
- let masterRegDescription;
- let masterShortName;
- for (var j = 0; j < rows.length; j++) {
- masterRegDescription = rows[j].description.trim();
- masterShortName = rows[j].short_name.trim();
- masterRegionValuesMap[masterShortName] = masterRegDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allRegionValuesMap[rows[j].short_name.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
- "select scle,description from scale_descriptions;"
+ sumPool, // eslint-disable-line no-undef
+ "select ptype,description from ptype_descriptions;"
);
- let masterDescription;
- let masterScale;
- for (var j = 0; j < rows.length; j++) {
- masterDescription = rows[j].description.trim();
- masterScale = rows[j].scle.trim();
- masterScaleValuesMap[masterScale] = masterDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allVariableValuesMap[rows[j].description.trim()] = rows[j].ptype.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
- "select ptype,description from ptype_descriptions;"
+ sumPool, // eslint-disable-line no-undef
+ "select scle,description from scale_descriptions;"
);
- let masterVarDescription;
- let masterVariable;
- for (var j = 0; j < rows.length; j++) {
- masterVarDescription = rows[j].description.trim();
- masterVariable = rows[j].ptype.trim();
- masterVariableValuesMap[masterVarDescription] = masterVariable;
+ for (let j = 0; j < rows.length; j += 1) {
+ allScaleValuesMap[rows[j].scle.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select model,regions,display_text,fcst_lens,scale,mindate,maxdate from regions_per_model_mats_all_categories order by display_category, display_order;"
);
- for (let i = 0; i < rows.length; i++) {
- const model_value = rows[i].model.trim();
+ for (let i = 0; i < rows.length; i += 1) {
+ const modelValue = rows[i].model.trim();
const model = rows[i].display_text.trim();
- modelOptionsMap[model] = [model_value];
+ modelOptionsMap[model] = [modelValue];
const rowMinDate = moment.utc(rows[i].mindate * 1000).format("MM/DD/YYYY HH:mm");
const rowMaxDate = moment.utc(rows[i].maxdate * 1000).format("MM/DD/YYYY HH:mm");
- modelDateRangeMap[model] = { minDate: rowMinDate, maxDate: rowMaxDate };
+ modelDateRangeMap[model] = {
+ minDate: rowMinDate,
+ maxDate: rowMaxDate,
+ };
const forecastLengths = rows[i].fcst_lens;
- const forecastLengthArr = forecastLengths
+ forecastLengthOptionsMap[model] = forecastLengths
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (var j = 0; j < forecastLengthArr.length; j++) {
- forecastLengthArr[j] = (
- Number(forecastLengthArr[j].replace(/'|\[|\]/g, "")) / 60
- ).toString();
- }
- forecastLengthOptionsMap[model] = forecastLengthArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (fhr) {
+ return Number(fhr.replace(/'|\[|\]/g, "")) / 60;
+ });
const scales = rows[i].scale;
- const scalesArrRaw = scales
+ scaleModelOptionsMap[model] = scales
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const scalesArr = [];
- var dummyScale;
- for (var j = 0; j < scalesArrRaw.length; j++) {
- dummyScale = scalesArrRaw[j].replace(/'|\[|\]/g, "");
- scalesArr.push(masterScaleValuesMap[dummyScale]);
- }
- scaleModelOptionsMap[model] = scalesArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (scale) {
+ return allScaleValuesMap[scale.replace(/'|\[|\]/g, "")];
+ });
const { regions } = rows[i];
- const regionsArrRaw = regions
+ regionModelOptionsMap[model] = regions
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const regionsArr = [];
- var dummyRegion;
- for (var j = 0; j < regionsArrRaw.length; j++) {
- dummyRegion = regionsArrRaw[j].replace(/'|\[|\]/g, "");
- regionsArr.push(masterRegionValuesMap[dummyRegion]);
- }
- regionModelOptionsMap[model] = regionsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (region) {
+ return allRegionValuesMap[region.replace(/'|\[|\]/g, "")];
+ });
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
if (matsCollections.label.findOne({ name: "label" }) === undefined) {
@@ -453,7 +436,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["data-source"].findOne({ name: "data-source" });
+ const currentParam = matsCollections["data-source"].findOne({
+ name: "data-source",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap) ||
!matsDataUtils.areObjectsEqual(currentParam.dates, modelDateRangeMap)
@@ -479,7 +464,7 @@ const doCurveParams = function () {
type: matsTypes.InputTypes.select,
optionsMap: regionModelOptionsMap,
options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]],
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
superiorNames: ["data-source"],
controlButtonCovered: true,
unique: false,
@@ -491,10 +476,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.region.findOne({ name: "region" });
+ const currentParam = matsCollections.region.findOne({ name: "region" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, regionModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterRegionValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allRegionValuesMap)
) {
// have to reload region data
matsCollections.region.update(
@@ -502,7 +487,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: regionModelOptionsMap,
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]],
default: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]][0],
},
@@ -526,7 +511,6 @@ const doCurveParams = function () {
null,
],
};
-
matsCollections.statistic.insert({
name: "statistic",
type: matsTypes.InputTypes.select,
@@ -546,11 +530,11 @@ const doCurveParams = function () {
matsCollections.variable.insert({
name: "variable",
type: matsTypes.InputTypes.select,
- optionsMap: masterVariableValuesMap,
- options: Object.keys(masterVariableValuesMap),
+ optionsMap: allVariableValuesMap,
+ options: Object.keys(allVariableValuesMap),
controlButtonCovered: true,
unique: false,
- default: Object.keys(masterVariableValuesMap)[0],
+ default: Object.keys(allVariableValuesMap)[0],
controlButtonVisibility: "block",
displayOrder: 2,
displayPriority: 1,
@@ -558,18 +542,16 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.variable.findOne({ name: "variable" });
- if (
- !matsDataUtils.areObjectsEqual(currentParam.optionsMap, masterVariableValuesMap)
- ) {
+ const currentParam = matsCollections.variable.findOne({ name: "variable" });
+ if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, allVariableValuesMap)) {
// have to reload variable data
matsCollections.variable.update(
{ name: "variable" },
{
$set: {
- optionsMap: masterVariableValuesMap,
- options: masterVariableValuesMap[Object.keys(masterVariableValuesMap)],
- default: masterVariableValuesMap[Object.keys(masterVariableValuesMap)[0]],
+ optionsMap: allVariableValuesMap,
+ options: allVariableValuesMap[Object.keys(allVariableValuesMap)],
+ default: allVariableValuesMap[Object.keys(allVariableValuesMap)[0]],
},
}
);
@@ -582,7 +564,7 @@ const doCurveParams = function () {
type: matsTypes.InputTypes.select,
optionsMap: scaleModelOptionsMap,
options: scaleModelOptionsMap[Object.keys(scaleModelOptionsMap)[0]],
- valuesMap: masterScaleValuesMap,
+ valuesMap: allScaleValuesMap,
superiorNames: ["data-source"],
controlButtonCovered: true,
unique: false,
@@ -594,10 +576,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.scale.findOne({ name: "scale" });
+ const currentParam = matsCollections.scale.findOne({ name: "scale" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, scaleModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterScaleValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allScaleValuesMap)
) {
// have to reload scale data
matsCollections.scale.update(
@@ -605,7 +587,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: scaleModelOptionsMap,
- valuesMap: masterScaleValuesMap,
+ valuesMap: allScaleValuesMap,
options: scaleModelOptionsMap[Object.keys(scaleModelOptionsMap)[0]],
default: scaleModelOptionsMap[Object.keys(scaleModelOptionsMap)[0]][0],
},
@@ -636,7 +618,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["forecast-length"].findOne({
+ const currentParam = matsCollections["forecast-length"].findOne({
name: "forecast-length",
});
if (
@@ -868,7 +850,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["curve-dates"].findOne({ name: "curve-dates" });
+ const currentParam = matsCollections["curve-dates"].findOne({
+ name: "curve-dates",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.startDate, minDate) ||
!matsDataUtils.areObjectsEqual(currentParam.stopDate, maxDate) ||
@@ -1153,7 +1137,8 @@ const doPlotGraph = function () {
Meteor.startup(function () {
matsCollections.Databases.remove({});
if (matsCollections.Databases.find({}).count() < 0) {
- console.log(
+ // eslint-disable-next-line no-console
+ console.warn(
"main startup: corrupted Databases collection: dropping Databases collection"
);
matsCollections.Databases.drop();
@@ -1170,7 +1155,7 @@ Meteor.startup(function () {
databases = Meteor.settings.private.databases;
}
if (databases !== null && databases !== undefined && Array.isArray(databases)) {
- for (let di = 0; di < databases.length; di++) {
+ for (let di = 0; di < databases.length; di += 1) {
matsCollections.Databases.insert(databases[di]);
}
}
@@ -1197,6 +1182,7 @@ Meteor.startup(function () {
);
if (cbConnection) {
// global cbScorecardSettingsPool
+ // eslint-disable-next-line no-undef
cbScorecardSettingsPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1223,6 +1209,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (metadataSettings) {
+ // eslint-disable-next-line no-undef
metadataPool = mysql.createPool(metadataSettings);
allPools.push({ pool: "metadataPool", role: matsTypes.DatabaseRoles.META_DATA });
}
@@ -1243,6 +1230,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (sumSettings) {
+ // eslint-disable-next-line no-undef
sumPool = mysql.createPool(sumSettings);
allPools.push({ pool: "sumPool", role: matsTypes.DatabaseRoles.SUMS_DATA });
}
@@ -1263,7 +1251,7 @@ Meteor.startup(function () {
appType: matsTypes.AppTypes.mats,
});
} catch (error) {
- console.log(error.message);
+ throw new Error(error.message);
}
});
@@ -1271,6 +1259,7 @@ Meteor.startup(function () {
// These are application specific mongo data - like curve params
// The appSpecificResetRoutines object is a special name,
// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way.
+// eslint-disable-next-line no-undef
appSpecificResetRoutines = [
doPlotGraph,
doCurveParams,
diff --git a/apps/radar/.eslintrc.json b/apps/radar/.eslintrc.json
index 8b795b7df7..79d49c5bb6 100644
--- a/apps/radar/.eslintrc.json
+++ b/apps/radar/.eslintrc.json
@@ -28,22 +28,6 @@
"space-before-function-paren": "off",
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
- "prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
- "no-undef": "warn",
- "no-plusplus": "warn",
- "vars-on-top": "warn",
- "no-var": "warn",
- "block-scoped-var": "warn",
- "no-loop-func": "warn",
- "no-unused-vars": "warn",
- "prefer-destructuring": "warn",
- "no-param-reassign": "warn",
- "camelcase": "warn",
- "no-redeclare": "warn"
+ "prefer-arrow-callback": "off"
}
}
diff --git a/apps/radar/client/main.js b/apps/radar/client/main.js
index a87407a1f4..ecd922b6a2 100644
--- a/apps/radar/client/main.js
+++ b/apps/radar/client/main.js
@@ -2,6 +2,7 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+// eslint-disable-next-line no-unused-vars
import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common";
import "@fortawesome/fontawesome-free";
import "@fortawesome/fontawesome-free/css/all.css";
diff --git a/apps/radar/server/dataFunctions/data_contour.js b/apps/radar/server/dataFunctions/data_contour.js
index f37c909014..fbed93abc2 100644
--- a/apps/radar/server/dataFunctions/data_contour.js
+++ b/apps/radar/server/dataFunctions/data_contour.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContour = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,58 +23,53 @@ dataContour = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
- const totalProcessingStart = moment();
+
+ const curves = JSON.parse(JSON.stringify(plotParams.curves));
+ if (curves.length > 1) {
+ throw new Error("INFO: There must only be one added curve.");
+ }
+
+ const axisMap = Object.create(null);
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- const curves = JSON.parse(JSON.stringify(plotParams.curves));
- if (curves.length > 1) {
- throw new Error("INFO: There must only be one added curve.");
- }
- const dataset = [];
- const axisMap = Object.create(null);
- // initialize variables specific to the curve
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
+
const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" }).optionsMap[
variable
];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- const regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
- scaleStr
- );
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
+
let thresholdClause = "";
- let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") {
const thresholdStr = curve.threshold;
+ if (thresholdStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s threshold is undefined. Please assign it a value.`
+ );
+ }
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -84,16 +80,45 @@ dataContour = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold / 10000}`;
}
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
+ scaleStr
+ );
+
+ let validTimeClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.time%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ "sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -104,102 +129,112 @@ dataContour = function (plotParams, plotFunction) {
dateString = "m0.time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- "sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
// For contours, this functions as the colorbar label.
const statType = statisticOptionsMap[statisticSelect][0];
- curve.unitKey = statisticOptionsMap[statisticSelect][1];
+ [, curve.unitKey] = statisticOptionsMap[statisticSelect];
let d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
-
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- if (error.includes("ER_NO_SUCH_TABLE")) {
- throw new Error(
- `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` +
- `Choose a different scale to continue using this region.`
- );
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
+
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
+ }
+
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
+ // this is NOT an error just a no data condition
+ dataFoundForCurve = false;
} else {
- throw new Error(error);
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ if (error.includes("ER_NO_SUCH_TABLE")) {
+ throw new Error(
+ `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` +
+ `Choose a different scale to continue using this region.`
+ );
+ } else {
+ throw new Error(error);
+ }
}
}
- }
- if (!dataFoundForCurve) {
- // we found no data for any curves so don't bother proceeding
- throw new Error("INFO: No valid data for any curves.");
+ if (!dataFoundForCurve) {
+ // we found no data for any curves so don't bother proceeding
+ throw new Error("INFO: No valid data for any curves.");
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
}
- const postQueryStartMoment = moment();
-
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
diff --git a/apps/radar/server/dataFunctions/data_contour_diff.js b/apps/radar/server/dataFunctions/data_contour_diff.js
index f367787887..02d29f0126 100644
--- a/apps/radar/server/dataFunctions/data_contour_diff.js
+++ b/apps/radar/server/dataFunctions/data_contour_diff.js
@@ -14,6 +14,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContourDiff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -24,61 +25,58 @@ dataContourDiff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
let dataNotFoundForAnyCurve = false;
+
+ let curves = JSON.parse(JSON.stringify(plotParams.curves));
+ const curvesLength = curves.length;
+ if (curvesLength !== 2) {
+ throw new Error("INFO: There must be two added curves.");
+ }
+
+ const axisMap = Object.create(null);
const showSignificance = plotParams.significance !== "none";
- const totalProcessingStart = moment();
+
+ let statType;
+ let statisticSelect;
+
+ let statement = "";
+ let error = "";
+ let dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- let curves = JSON.parse(JSON.stringify(plotParams.curves));
- const curvesLength = curves.length;
- if (curvesLength !== 2) {
- throw new Error("INFO: There must be two added curves.");
- }
- let dataset = [];
- const axisMap = Object.create(null);
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
- scaleStr
- );
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
+
let thresholdClause = "";
- let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") {
- var thresholdStr = curve.threshold;
+ const thresholdStr = curve.threshold;
+ if (thresholdStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s threshold is undefined. Please assign it a value.`
+ );
+ }
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -89,16 +87,45 @@ dataContourDiff = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold / 10000}`;
}
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
+ scaleStr
+ );
+
+ let validTimeClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.time%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ "sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -109,98 +136,105 @@ dataContourDiff = function (plotParams, plotFunction) {
dateString = "m0.time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- var statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- "sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
// For contours, this functions as the colorbar label.
- var statType = statisticOptionsMap[statisticSelect][0];
- curves[curveIndex].unitKey = statisticOptionsMap[statisticSelect][1];
+ [statType] = statisticOptionsMap[statisticSelect];
+ [, curve.unitKey] = statisticOptionsMap[statisticSelect];
- var d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
+ let d;
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- statisticSelect
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- if (error.includes("ER_NO_SUCH_TABLE")) {
- throw new Error(
- `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` +
- `Choose a different scale to continue using this region.`
- );
- } else {
- throw new Error(error);
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ statisticSelect
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
+ }
+
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ if (error.includes("ER_NO_SUCH_TABLE")) {
+ throw new Error(
+ `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` +
+ `Choose a different scale to continue using this region.`
+ );
+ } else {
+ throw new Error(error);
+ }
}
+ dataNotFoundForAnyCurve = true;
}
- dataNotFoundForAnyCurve = true;
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
}
- const postQueryStartMoment = moment();
-
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
@@ -249,8 +283,9 @@ dataContourDiff = function (plotParams, plotFunction) {
statType === "ctc",
statType === "scalar"
);
- plotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
- curves = plotParams.curves;
+ const newPlotParams = plotParams;
+ newPlotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
+ curves = newPlotParams.curves;
dataset[0].name = matsPlotUtils.getCurveText(
matsTypes.PlotTypes.contourDiff,
curves[0]
@@ -266,7 +301,7 @@ dataContourDiff = function (plotParams, plotFunction) {
const result = matsDataProcessUtils.processDataContour(
dataset,
curveInfoParams,
- plotParams,
+ newPlotParams,
bookkeepingParams
);
plotFunction(result);
diff --git a/apps/radar/server/dataFunctions/data_dailymodelcycle.js b/apps/radar/server/dataFunctions/data_dailymodelcycle.js
index be4a3b51b7..5ca328ca9d 100644
--- a/apps/radar/server/dataFunctions/data_dailymodelcycle.js
+++ b/apps/radar/server/dataFunctions/data_dailymodelcycle.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDailyModelCycle = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,52 +24,46 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
- scaleStr
- );
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -78,6 +73,16 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
] === thresholdStr
);
const thresholdClause = `and m0.trsh = ${threshold / 10000}`;
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
+ scaleStr
+ );
+
if (curve["utc-cycle-start"].length !== 1) {
throw new Error(
"INFO: Please select exactly one UTC Cycle Init Hour for this plot type."
@@ -86,8 +91,9 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
const utcCycleStart = Number(curve["utc-cycle-start"][0]);
utcCycleStarts[curveIndex] = utcCycleStart;
const utcCycleStartClause = `and floor((m0.time - m0.fcst_len*3600)%(24*3600)/3600) IN(${utcCycleStart})`;
+
const forecastLengthClause = "and m0.fcst_len < 24";
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -95,11 +101,23 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -107,46 +125,46 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.time as avtime, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{utcCycleStartClause}} " +
- "{{thresholdClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.time as avtime, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{utcCycleStartClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -162,6 +180,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -183,7 +202,6 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -208,6 +226,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/radar/server/dataFunctions/data_dieoff.js b/apps/radar/server/dataFunctions/data_dieoff.js
index b9ef5bd281..08f8664c6f 100644
--- a/apps/radar/server/dataFunctions/data_dieoff.js
+++ b/apps/radar/server/dataFunctions/data_dieoff.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDieoff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,49 +24,42 @@ dataDieoff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
- scaleStr
- );
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -75,21 +69,51 @@ dataDieoff = function (plotParams, plotFunction) {
] === thresholdStr
);
const thresholdClause = `and m0.trsh = ${threshold / 10000}`;
- var validTimes;
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
+ scaleStr
+ );
+
let validTimeClause = "";
- var utcCycleStart;
+ let validTimes;
+
let utcCycleStartClause = "";
+ let utcCycleStart;
+
const forecastLengthStr = curve["dieoff-type"];
const forecastLengthOptionsMap = matsCollections["dieoff-type"].findOne(
{ name: "dieoff-type" },
{ optionsMap: 1 }
).optionsMap;
const forecastLength = forecastLengthOptionsMap[forecastLengthStr][0];
- const forecastLengthClause = "";
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ "sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
- var dateClause;
+ let dateClause;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
if (forecastLength === matsTypes.ForecastTypes.dieoff) {
validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
@@ -106,18 +130,12 @@ dataDieoff = function (plotParams, plotFunction) {
} else {
dateClause = `and m0.time-m0.fcst_len*3600 = ${fromSecs}`;
}
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- "sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -125,48 +143,46 @@ dataDieoff = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.fcst_len as fcst_lead, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{utcCycleStartClause}} " +
- "group by fcst_lead " +
- "order by fcst_lead" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.fcst_len as fcst_lead, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{utcCycleStartClause}} " +
+ "group by fcst_lead " +
+ "order by fcst_lead" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -182,6 +198,7 @@ dataDieoff = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -203,7 +220,6 @@ dataDieoff = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -228,6 +244,7 @@ dataDieoff = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/radar/server/dataFunctions/data_histogram.js b/apps/radar/server/dataFunctions/data_histogram.js
index 1ea2f4bb97..00c9d5738d 100644
--- a/apps/radar/server/dataFunctions/data_histogram.js
+++ b/apps/radar/server/dataFunctions/data_histogram.js
@@ -11,6 +11,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataHistogram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -21,52 +22,45 @@ dataHistogram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
- const alreadyMatched = false;
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
const dataFoundForCurve = [];
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+ const alreadyMatched = false;
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
+
+ const axisMap = Object.create(null);
+ let statType;
+ let varUnits;
+
+ let statement = "";
+ let error = "";
const dataset = [];
const allReturnedSubStats = [];
const allReturnedSubSecs = [];
- const axisMap = Object.create(null);
// process user bin customizations
const binParams = matsDataUtils.setHistogramParameters(plotParams);
const { yAxisFormat } = binParams;
const { binNum } = binParams;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
dataFoundForCurve[curveIndex] = true;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
- scaleStr
- );
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -76,17 +70,25 @@ dataHistogram = function (plotParams, plotFunction) {
] === thresholdStr
);
const thresholdClause = `and m0.trsh = ${threshold / 10000}`;
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
+ scaleStr
+ );
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
}
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -94,12 +96,27 @@ dataHistogram = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
- var varUnits = statisticOptionsMap[statisticSelect][1];
+ [statType] = statisticOptionsMap[statisticSelect];
+ [, varUnits] = statisticOptionsMap[statisticSelect];
let axisKey = yAxisFormat;
if (yAxisFormat === "Relative frequency") {
axisKey += " (x100)";
@@ -107,46 +124,46 @@ dataHistogram = function (plotParams, plotFunction) {
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
curves[curveIndex].binNum = binNum; // stash the binNum to use it later for bar chart options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.time as avtime, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.time as avtime, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -164,6 +181,7 @@ dataHistogram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/radar/server/dataFunctions/data_perfDiagram.js b/apps/radar/server/dataFunctions/data_perfDiagram.js
index 037bc7324f..a3e1d281df 100644
--- a/apps/radar/server/dataFunctions/data_perfDiagram.js
+++ b/apps/radar/server/dataFunctions/data_perfDiagram.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataPerformanceDiagram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,60 +23,47 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statType;
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const binParam = curve["bin-parameter"];
const binClause = matsCollections["bin-parameter"].findOne({
name: "bin-parameter",
}).optionsMap[binParam];
- var { variable } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
- scaleStr
- );
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
+
let thresholdClause = "";
- let validTimeClause = "";
- let forecastLengthClause = "";
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let dateString = "";
- let dateClause = "";
if (binParam !== "Threshold") {
- var thresholdStr = curve.threshold;
+ const thresholdStr = curve.threshold;
if (thresholdStr === undefined) {
throw new Error(
`INFO: ${label}'s threshold is undefined. Please assign it a value.`
@@ -91,12 +79,25 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
);
thresholdClause = `and m0.trsh = ${threshold / 10000}`;
}
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
+ scaleStr
+ );
+
+ let validTimeClause = "";
if (binParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.time%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (binParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
if (forecastLength === undefined) {
@@ -106,62 +107,79 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
}
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const statisticSelect = "PerformanceDiagram";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ let dateString = "";
+ let dateClause = "";
if (binParam === "Init Date") {
dateString = "m0.time-m0.fcst_len*3600";
} else {
dateString = "m0.time";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const statisticSelect = "PerformanceDiagram";
- var statType = "ctc";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// variable + statistic (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ statType = "ctc";
curves[curveIndex].axisKey = statisticSelect; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{binClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "((sum(m0.yy)+0.00)/sum(m0.yy+m0.yn)) as pod, ((sum(m0.ny)+0.00)/sum(m0.ny+m0.yy)) as far, " +
- "sum(m0.yy+m0.yn) as oy_all, sum(m0.ny+m0.nn) as on_all, group_concat(m0.time, ';', m0.yy, ';', " +
- "m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0 " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by binVal " +
- "order by binVal" +
- ";";
-
- statement = statement.replace("{{binClause}}", binClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "{{binClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "((sum(m0.yy)+0.00)/sum(m0.yy+m0.yn)) as pod, ((sum(m0.ny)+0.00)/sum(m0.ny+m0.yy)) as far, " +
+ "sum(m0.yy+m0.yn) as oy_all, sum(m0.ny+m0.nn) as on_all, group_concat(m0.time, ';', m0.yy, ';', " +
+ "m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0 " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by binVal " +
+ "order by binVal" +
+ ";";
+
+ statement = statement.replace("{{binClause}}", binClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBPerformanceDiagram(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -177,6 +195,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -198,7 +217,6 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -206,7 +224,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
ymax = ymax > d.ymax ? ymax : d.ymax;
}
} else {
- // this is a difference curve -- not supported for ROC plots
+ // this is a difference curve -- not supported for performance diagrams
throw new Error(
"INFO: Difference curves are not supported for performance diagrams, as they do not feature consistent x or y values across all curves."
);
@@ -214,6 +232,7 @@ dataPerformanceDiagram = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/radar/server/dataFunctions/data_series.js b/apps/radar/server/dataFunctions/data_series.js
index efe9d2e739..1711a7d44b 100644
--- a/apps/radar/server/dataFunctions/data_series.js
+++ b/apps/radar/server/dataFunctions/data_series.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSeries = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,52 +24,46 @@ dataSeries = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
- scaleStr
- );
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -78,20 +73,25 @@ dataSeries = function (plotParams, plotFunction) {
] === thresholdStr
);
const thresholdClause = `and m0.trsh = ${threshold / 10000}`;
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
+ scaleStr
+ );
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
}
+
let forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
- const averageStr = curve.average;
- const averageOptionsMap = matsCollections.average.findOne(
- { name: "average" },
- { optionsMap: 1 }
- ).optionsMap;
- const average = averageOptionsMap[averageStr][0];
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -99,11 +99,30 @@ dataSeries = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const averageStr = curve.average;
+ const averageOptionsMap = matsCollections.average.findOne(
+ { name: "average" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const average = averageOptionsMap[averageStr][0];
+
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -111,47 +130,45 @@ dataSeries = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select {{average}} as avtime, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "select {{average}} as avtime, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
- statement = statement.replace("{{average}}", average);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
+ statement = statement.replace("{{average}}", average);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
- // math is done on forecastLength later on -- set all analyses to 0
- if (forecastLength === "-99") {
- forecastLength = "0";
- }
+ // math is done on forecastLength later on -- set all analyses to 0
+ if (forecastLength === "-99") {
+ forecastLength = "0";
+ }
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBTimeSeries(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
model,
forecastLength,
@@ -163,7 +180,9 @@ dataSeries = function (plotParams, plotFunction) {
appParams,
false
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -179,6 +198,7 @@ dataSeries = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -200,7 +220,6 @@ dataSeries = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -225,6 +244,7 @@ dataSeries = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/radar/server/dataFunctions/data_threshold.js b/apps/radar/server/dataFunctions/data_threshold.js
index 7e5d769ea3..c3510c7677 100644
--- a/apps/radar/server/dataFunctions/data_threshold.js
+++ b/apps/radar/server/dataFunctions/data_threshold.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataThreshold = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,59 +24,58 @@ dataThreshold = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
).find(
(key) =>
matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
scaleStr
);
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`;
}
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -83,11 +83,26 @@ dataThreshold = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -95,44 +110,44 @@ dataThreshold = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.trsh as thresh, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by thresh " +
- "order by thresh" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.trsh as thresh, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by thresh " +
+ "order by thresh" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -148,6 +163,7 @@ dataThreshold = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -169,7 +185,6 @@ dataThreshold = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -194,6 +209,7 @@ dataThreshold = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/radar/server/dataFunctions/data_validtime.js b/apps/radar/server/dataFunctions/data_validtime.js
index 006c9be2e6..0ab81c84a5 100644
--- a/apps/radar/server/dataFunctions/data_validtime.js
+++ b/apps/radar/server/dataFunctions/data_validtime.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataValidTime = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,49 +24,42 @@ dataValidTime = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
- var { variable } = curve;
+ const { diffFrom } = curve;
+
+ const { variable } = curve;
const databaseRef = matsCollections.variable.findOne({ name: "variable" })
.optionsMap[variable];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[variable][curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
- scaleStr
- );
- const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`;
- var thresholdStr = curve.threshold;
+
+ const thresholdStr = curve.threshold;
const threshold = Object.keys(
matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable]
).find(
@@ -75,12 +69,19 @@ dataValidTime = function (plotParams, plotFunction) {
] === thresholdStr
);
const thresholdClause = `and m0.trsh = ${threshold / 10000}`;
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable]
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] ===
+ scaleStr
+ );
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -88,11 +89,26 @@ dataValidTime = function (plotParams, plotFunction) {
).optionsMap;
const statisticClause =
"sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0";
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ const queryTableClause = `from ${databaseRef}.${model}_${scale}_${region} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- var statType = statisticOptionsMap[statisticSelect][0];
+ [statType] = statisticOptionsMap[statisticSelect];
const axisKey = statisticOptionsMap[statisticSelect][1];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
const idealVal = statisticOptionsMap[statisticSelect][2];
@@ -100,44 +116,44 @@ dataValidTime = function (plotParams, plotFunction) {
idealValues.push(idealVal);
}
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select floor(m0.time%(24*3600)/3600) as hr_of_day, " +
- "count(distinct m0.time) as N_times, " +
- "min(m0.time) as min_secs, " +
- "max(m0.time) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{thresholdClause}} " +
- "{{forecastLengthClause}} " +
- "group by hr_of_day " +
- "order by hr_of_day" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{thresholdClause}}", thresholdClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select floor(m0.time%(24*3600)/3600) as hr_of_day, " +
+ "count(distinct m0.time) as N_times, " +
+ "min(m0.time) as min_secs, " +
+ "max(m0.time) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{thresholdClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by hr_of_day " +
+ "order by hr_of_day" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{thresholdClause}}", thresholdClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
statisticSelect
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -153,6 +169,7 @@ dataValidTime = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -174,7 +191,6 @@ dataValidTime = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -199,6 +215,7 @@ dataValidTime = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/radar/server/main.js b/apps/radar/server/main.js
index 0a0de69cfb..830a2e1bae 100644
--- a/apps/radar/server/main.js
+++ b/apps/radar/server/main.js
@@ -4,7 +4,9 @@
import { Meteor } from "meteor/meteor";
import { mysql } from "meteor/pcel:mysql";
+import { moment } from "meteor/momentjs:moment";
import {
+ matsMethods,
matsTypes,
matsCollections,
matsDataUtils,
@@ -328,7 +330,7 @@ const doCurveParams = function () {
const params = matsCollections.CurveParamsInfo.find({
curve_params: { $exists: true },
}).fetch()[0].curve_params;
- for (let cp = 0; cp < params.length; cp++) {
+ for (let cp = 0; cp < params.length; cp += 1) {
matsCollections[params[cp]].remove({});
}
}
@@ -339,92 +341,76 @@ const doCurveParams = function () {
const forecastLengthOptionsMap = {};
const thresholdsModelOptionsMap = {};
const scaleModelOptionsMap = {};
- const masterRegionValuesMap = {};
- const masterThresholdValuesMap = {};
- const masterScaleValuesMap = {};
+ const allRegionValuesMap = {};
+ const allThresholdValuesMap = {};
+ const allScaleValuesMap = {};
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- metadataPool,
+ metadataPool, // eslint-disable-line no-undef
"select short_name,description from region_descriptions;"
);
- let masterRegDescription;
- let masterShortName;
- for (var j = 0; j < rows.length; j++) {
- masterRegDescription = rows[j].description.trim();
- masterShortName = rows[j].short_name.trim();
- masterRegionValuesMap[masterShortName] = masterRegDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allRegionValuesMap[rows[j].short_name.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
- let rows;
- let didx;
-
try {
- for (didx = 0; didx < variables.length; didx++) {
- masterThresholdValuesMap[variables[didx]] = {};
- rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ for (let didx = 0; didx < variables.length; didx += 1) {
+ allThresholdValuesMap[variables[didx]] = {};
+ const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
+ sumPool, // eslint-disable-line no-undef
`select trsh,description from ${
variableDBNames[variables[didx]]
}.threshold_descriptions;`
);
- var masterDescription;
- var masterTrsh;
- var trshTemp;
- for (var j = 0; j < rows.length; j++) {
- masterDescription = rows[j].description.trim();
- trshTemp = rows[j].trsh.trim();
- masterTrsh = trshTemp * 10000;
- masterThresholdValuesMap[variables[didx]][masterTrsh] = masterDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allThresholdValuesMap[variables[didx]][rows[j].trsh.trim() * 10000] =
+ rows[j].description.trim();
}
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
- for (didx = 0; didx < variables.length; didx++) {
- masterScaleValuesMap[variables[didx]] = {};
- rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ for (let didx = 0; didx < variables.length; didx += 1) {
+ allScaleValuesMap[variables[didx]] = {};
+ const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
+ sumPool, // eslint-disable-line no-undef
`select scale,description from ${
variableDBNames[variables[didx]]
}.scale_descriptions;`
);
- var masterDescription;
- var masterScale;
- for (var j = 0; j < rows.length; j++) {
- masterDescription = rows[j].description.trim();
- masterScale = rows[j].scale.trim();
- masterScaleValuesMap[variables[didx]][masterScale] = masterDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allScaleValuesMap[variables[didx]][rows[j].scale.trim()] =
+ rows[j].description.trim();
}
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
- for (didx = 0; didx < variables.length; didx++) {
- modelOptionsMap[variables[didx]] = {};
- modelDateRangeMap[variables[didx]] = {};
- forecastLengthOptionsMap[variables[didx]] = {};
- thresholdsModelOptionsMap[variables[didx]] = {};
- scaleModelOptionsMap[variables[didx]] = {};
- regionModelOptionsMap[variables[didx]] = {};
-
- rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
- `select model,regions,display_text,fcst_lens,trsh,scale,mindate,maxdate from ${
- variableDBNames[variables[didx]]
- }.regions_per_model_mats_all_categories order by display_category, display_order;`
+ for (let didx = 0; didx < variables.length; didx += 1) {
+ const variable = variables[didx];
+ modelOptionsMap[variable] = {};
+ modelDateRangeMap[variable] = {};
+ forecastLengthOptionsMap[variable] = {};
+ thresholdsModelOptionsMap[variable] = {};
+ scaleModelOptionsMap[variable] = {};
+ regionModelOptionsMap[variable] = {};
+
+ const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
+ sumPool, // eslint-disable-line no-undef
+ `select model,regions,display_text,fcst_lens,trsh,scale,mindate,maxdate from ${variableDBNames[variable]}.regions_per_model_mats_all_categories order by display_category, display_order;`
);
- for (let i = 0; i < rows.length; i++) {
- const model_value = rows[i].model.trim();
+ for (let i = 0; i < rows.length; i += 1) {
+ const modelValue = rows[i].model.trim();
const model = rows[i].display_text.trim();
- modelOptionsMap[variables[didx]][model] = [model_value];
+ modelOptionsMap[variable][model] = [modelValue];
const rowMinDate = moment
.utc(rows[i].mindate * 1000)
@@ -432,59 +418,48 @@ const doCurveParams = function () {
const rowMaxDate = moment
.utc(rows[i].maxdate * 1000)
.format("MM/DD/YYYY HH:mm");
- modelDateRangeMap[variables[didx]][model] = {
+ modelDateRangeMap[variable][model] = {
minDate: rowMinDate,
maxDate: rowMaxDate,
};
const forecastLengths = rows[i].fcst_lens;
- const forecastLengthArr = forecastLengths
+ forecastLengthOptionsMap[variable][model] = forecastLengths
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (var j = 0; j < forecastLengthArr.length; j++) {
- forecastLengthArr[j] = forecastLengthArr[j].replace(/'|\[|\]/g, "");
- }
- forecastLengthOptionsMap[variables[didx]][model] = forecastLengthArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (fhr) {
+ return fhr.replace(/'|\[|\]/g, "");
+ });
const thresholds = rows[i].trsh;
- const thresholdsArrRaw = thresholds
+ thresholdsModelOptionsMap[variable][model] = thresholds
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const thresholdsArr = [];
- var dummyThresh;
- for (var j = 0; j < thresholdsArrRaw.length; j++) {
- dummyThresh = thresholdsArrRaw[j].replace(/'|\[|\]/g, "") * 10000;
- thresholdsArr.push(masterThresholdValuesMap[variables[didx]][dummyThresh]);
- }
- thresholdsModelOptionsMap[variables[didx]][model] = thresholdsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (threshold) {
+ return allThresholdValuesMap[
+ variable
+ ][threshold.replace(/'|\[|\]/g, "") * 10000];
+ });
const scales = rows[i].scale;
- const scalesArrRaw = scales
+ scaleModelOptionsMap[variable][model] = scales
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const scalesArr = [];
- var dummyScale;
- for (var j = 0; j < scalesArrRaw.length; j++) {
- dummyScale = scalesArrRaw[j].replace(/'|\[|\]/g, "");
- scalesArr.push(masterScaleValuesMap[variables[didx]][dummyScale]);
- }
- scaleModelOptionsMap[variables[didx]][model] = scalesArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (scale) {
+ return allScaleValuesMap[variable][scale.replace(/'|\[|\]/g, "")];
+ });
const { regions } = rows[i];
- const regionsArrRaw = regions
+ regionModelOptionsMap[variable][model] = regions
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const regionsArr = [];
- var dummyRegion;
- for (var j = 0; j < regionsArrRaw.length; j++) {
- dummyRegion = regionsArrRaw[j].replace(/'|\[|\]/g, "");
- regionsArr.push(masterRegionValuesMap[dummyRegion]);
- }
- regionModelOptionsMap[variables[didx]][model] = regionsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (region) {
+ return allRegionValuesMap[region.replace(/'|\[|\]/g, "")];
+ });
}
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
if (matsCollections.label.findOne({ name: "label" }) === undefined) {
@@ -522,7 +497,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.variable.findOne({ name: "variable" });
+ const currentParam = matsCollections.variable.findOne({ name: "variable" });
if (!matsDataUtils.areObjectsEqual(currentParam.dates, modelDateRangeMap)) {
// have to reload variable data
matsCollections.variable.update(
@@ -561,7 +536,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["data-source"].findOne({ name: "data-source" });
+ const currentParam = matsCollections["data-source"].findOne({
+ name: "data-source",
+ });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap)) {
// have to reload model data
matsCollections["data-source"].update(
@@ -586,7 +563,7 @@ const doCurveParams = function () {
regionModelOptionsMap[variables[0]][
Object.keys(regionModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -601,10 +578,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.region.findOne({ name: "region" });
+ const currentParam = matsCollections.region.findOne({ name: "region" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, regionModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterRegionValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allRegionValuesMap)
) {
// have to reload region data
matsCollections.region.update(
@@ -612,7 +589,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: regionModelOptionsMap,
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
options:
regionModelOptionsMap[variables[0]][
Object.keys(regionModelOptionsMap[variables[0]])[0]
@@ -693,7 +670,7 @@ const doCurveParams = function () {
thresholdsModelOptionsMap[variables[0]][
Object.keys(thresholdsModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterThresholdValuesMap,
+ valuesMap: allThresholdValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -708,13 +685,13 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.threshold.findOne({ name: "threshold" });
+ const currentParam = matsCollections.threshold.findOne({ name: "threshold" });
if (
!matsDataUtils.areObjectsEqual(
currentParam.optionsMap,
thresholdsModelOptionsMap
) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterThresholdValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allThresholdValuesMap)
) {
// have to reload threshold data
matsCollections.threshold.update(
@@ -722,7 +699,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: thresholdsModelOptionsMap,
- valuesMap: masterThresholdValuesMap,
+ valuesMap: allThresholdValuesMap,
options:
thresholdsModelOptionsMap[variables[0]][
Object.keys(thresholdsModelOptionsMap[variables[0]])[0]
@@ -746,7 +723,7 @@ const doCurveParams = function () {
scaleModelOptionsMap[variables[0]][
Object.keys(scaleModelOptionsMap[variables[0]])[0]
],
- valuesMap: masterScaleValuesMap,
+ valuesMap: allScaleValuesMap,
superiorNames: ["variable", "data-source"],
controlButtonCovered: true,
unique: false,
@@ -761,10 +738,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.scale.findOne({ name: "scale" });
+ const currentParam = matsCollections.scale.findOne({ name: "scale" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, scaleModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterScaleValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allScaleValuesMap)
) {
// have to reload scale data
matsCollections.scale.update(
@@ -772,7 +749,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: scaleModelOptionsMap,
- valuesMap: masterScaleValuesMap,
+ valuesMap: allScaleValuesMap,
options:
scaleModelOptionsMap[variables[0]][
Object.keys(scaleModelOptionsMap[variables[0]])[0]
@@ -812,7 +789,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["forecast-length"].findOne({
+ const currentParam = matsCollections["forecast-length"].findOne({
name: "forecast-length",
});
if (
@@ -1042,18 +1019,14 @@ const doCurveParams = function () {
}
// determine date defaults for dates and curveDates
- const defaultDb = matsCollections.variable.findOne(
- { name: "variable" },
+ const defaultDataSource = matsCollections["data-source"].findOne(
+ { name: "data-source" },
{ default: 1 }
).default;
modelDateRangeMap = matsCollections.variable.findOne(
{ name: "variable" },
{ dates: 1 }
).dates;
- const defaultDataSource = matsCollections["data-source"].findOne(
- { name: "data-source" },
- { default: 1 }
- ).default;
minDate = modelDateRangeMap[variables[0]][defaultDataSource].minDate;
maxDate = modelDateRangeMap[variables[0]][defaultDataSource].maxDate;
@@ -1094,7 +1067,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["curve-dates"].findOne({ name: "curve-dates" });
+ const currentParam = matsCollections["curve-dates"].findOne({
+ name: "curve-dates",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.startDate, minDate) ||
!matsDataUtils.areObjectsEqual(currentParam.stopDate, maxDate) ||
@@ -1458,7 +1433,8 @@ const doPlotGraph = function () {
Meteor.startup(function () {
matsCollections.Databases.remove({});
if (matsCollections.Databases.find({}).count() < 0) {
- console.log(
+ // eslint-disable-next-line no-console
+ console.warn(
"main startup: corrupted Databases collection: dropping Databases collection"
);
matsCollections.Databases.drop();
@@ -1475,7 +1451,7 @@ Meteor.startup(function () {
databases = Meteor.settings.private.databases;
}
if (databases !== null && databases !== undefined && Array.isArray(databases)) {
- for (let di = 0; di < databases.length; di++) {
+ for (let di = 0; di < databases.length; di += 1) {
matsCollections.Databases.insert(databases[di]);
}
}
@@ -1502,6 +1478,7 @@ Meteor.startup(function () {
);
if (cbConnection) {
// global cbScorecardSettingsPool
+ // eslint-disable-next-line no-undef
cbScorecardSettingsPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1528,6 +1505,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (metadataSettings) {
+ // eslint-disable-next-line no-undef
metadataPool = mysql.createPool(metadataSettings);
allPools.push({ pool: "metadataPool", role: matsTypes.DatabaseRoles.META_DATA });
}
@@ -1548,6 +1526,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (sumSettings) {
+ // eslint-disable-next-line no-undef
sumPool = mysql.createPool(sumSettings);
allPools.push({ pool: "sumPool", role: matsTypes.DatabaseRoles.SUMS_DATA });
}
@@ -1556,7 +1535,7 @@ Meteor.startup(function () {
const mdr = new matsTypes.MetaDataDBRecord("metadataPool", "mats_common", [
"region_descriptions",
]);
- for (let didx = 0; didx < variables.length; didx++) {
+ for (let didx = 0; didx < variables.length; didx += 1) {
mdr.addRecord("sumPool", variableDBNames[variables[didx]], [
"threshold_descriptions",
"scale_descriptions",
@@ -1570,7 +1549,7 @@ Meteor.startup(function () {
appType: matsTypes.AppTypes.mats,
});
} catch (error) {
- console.log(error.message);
+ throw new Error(error.message);
}
});
@@ -1578,6 +1557,7 @@ Meteor.startup(function () {
// These are application specific mongo data - like curve params
// The appSpecificResetRoutines object is a special name,
// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way.
+// eslint-disable-next-line no-undef
appSpecificResetRoutines = [
doPlotGraph,
doCurveParams,
diff --git a/apps/scorecard/.eslintrc.json b/apps/scorecard/.eslintrc.json
index c248c52f7d..79d49c5bb6 100644
--- a/apps/scorecard/.eslintrc.json
+++ b/apps/scorecard/.eslintrc.json
@@ -28,28 +28,6 @@
"space-before-function-paren": "off",
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
- "prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
- "no-undef": "warn",
- "no-plusplus": "warn",
- "vars-on-top": "warn",
- "no-var": "warn",
- "block-scoped-var": "warn",
- "no-loop-func": "warn",
- "no-unused-vars": "warn",
- "prefer-destructuring": "warn",
- "no-param-reassign": "warn",
- "camelcase": "warn",
- "no-redeclare": "warn",
- "no-shadow": "warn",
- "no-useless-escape": "warn",
- "global-require": "warn",
- "default-case": "warn",
- "no-unused-expressions": "warn",
- "no-sequences": "warn"
+ "prefer-arrow-callback": "off"
}
}
diff --git a/apps/scorecard/client/main.js b/apps/scorecard/client/main.js
index a87407a1f4..ecd922b6a2 100644
--- a/apps/scorecard/client/main.js
+++ b/apps/scorecard/client/main.js
@@ -2,6 +2,7 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+// eslint-disable-next-line no-unused-vars
import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common";
import "@fortawesome/fontawesome-free";
import "@fortawesome/fontawesome-free/css/all.css";
diff --git a/apps/scorecard/server/dataFunctions/processScorecard.js b/apps/scorecard/server/dataFunctions/processScorecard.js
index dc3c2f3a1c..84ae4e140a 100644
--- a/apps/scorecard/server/dataFunctions/processScorecard.js
+++ b/apps/scorecard/server/dataFunctions/processScorecard.js
@@ -5,8 +5,8 @@ import { matsTypes, matsParamUtils, matsCollections } from "meteor/randyp:mats-c
/** A function to sanitize JSON keys by replacing the "." character with "__DOT__" */
const sanitizeKeys = function (str) {
- str = str.replace(/\./g, "__DOT__");
- return str;
+ const newStr = str.replace(/\./g, "__DOT__");
+ return newStr;
};
const dealWithUATables = function (
@@ -182,10 +182,13 @@ processScorecard = function (plotParams, plotFunction) {
// get the union of the fcst-length arrays of all the curves
const fcstLengthsSet = new Set();
plotParams.curves.forEach(function (curve) {
- if (!curve["forecast-length"]) curve["forecast-length"] = ["0"];
- curve["forecast-length"].forEach(function (fcl) {
- fcstLengthsSet.add(fcl);
- });
+ if (!curve["forecast-length"]) {
+ fcstLengthsSet.add("0");
+ } else {
+ curve["forecast-length"].forEach(function (fcl) {
+ fcstLengthsSet.add(fcl);
+ });
+ }
});
const fcstLengths = Array.from(fcstLengthsSet);
@@ -383,6 +386,10 @@ processScorecard = function (plotParams, plotFunction) {
// create the empty object for this block
const { label } = curve;
+
+ // duplicate the curve so we're not modifying a function parameter, which the linter doesn't like
+ const scorecardCurve = curve;
+
scorecardDocument.results.blocks[label] = {};
scorecardDocument.queryMap.blocks[label] = {};
// add the top level elements.
@@ -395,76 +402,73 @@ processScorecard = function (plotParams, plotFunction) {
return !notIncludedParams.includes(paramName);
});
- scorecardDocument.results.blocks[curve.label].blockTitle = {
+ scorecardDocument.results.blocks[label].blockTitle = {
label,
- dataSource: curve["data-source"],
- controlDataSource: curve["control-data-source"],
+ dataSource: scorecardCurve["data-source"],
+ controlDataSource: scorecardCurve["control-data-source"],
};
const appName = Meteor.settings.public.app;
const appUrl = `${Meteor.settings.public.home}/${appName}`;
- scorecardDocument.results.blocks[curve.label].blockApplication = appUrl;
- scorecardDocument.results.blocks[curve.label].blockParameters = blockParameters;
- scorecardDocument.results.blocks[curve.label].regions = regions;
- scorecardDocument.results.blocks[curve.label].fcstlens = fcstLengths;
- scorecardDocument.results.blocks[curve.label].data = {};
- scorecardDocument.queryMap.blocks[curve.label].data = {};
- curve.threshold =
- curve.threshold === undefined ? ["threshold_NA"] : curve.threshold;
- curve.level = curve.level === undefined ? ["level_NA"] : curve.level;
+ scorecardDocument.results.blocks[label].blockApplication = appUrl;
+ scorecardDocument.results.blocks[label].blockParameters = blockParameters;
+ scorecardDocument.results.blocks[label].regions = regions;
+ scorecardDocument.results.blocks[label].fcstlens = fcstLengths;
+ scorecardDocument.results.blocks[label].data = {};
+ scorecardDocument.queryMap.blocks[label].data = {};
+ scorecardCurve.threshold =
+ scorecardCurve.threshold === undefined
+ ? ["threshold_NA"]
+ : scorecardCurve.threshold;
+ scorecardCurve.level =
+ scorecardCurve.level === undefined ? ["level_NA"] : scorecardCurve.level;
regions.forEach(function (regionText) {
const region = sanitizeKeys(regionText);
- if (scorecardDocument.results.blocks[curve.label].data[region] === undefined) {
- scorecardDocument.results.blocks[curve.label].data[region] = {};
- scorecardDocument.queryMap.blocks[curve.label].data[region] = {};
+ if (scorecardDocument.results.blocks[label].data[region] === undefined) {
+ scorecardDocument.results.blocks[label].data[region] = {};
+ scorecardDocument.queryMap.blocks[label].data[region] = {};
}
- curve.statistic.forEach(function (statText) {
+ scorecardCurve.statistic.forEach(function (statText) {
const stat = sanitizeKeys(statText);
- if (
- scorecardDocument.results.blocks[curve.label].data[region][stat] === undefined
- ) {
- scorecardDocument.results.blocks[curve.label].data[region][stat] = {};
- scorecardDocument.queryMap.blocks[curve.label].data[region][stat] = {};
+ if (scorecardDocument.results.blocks[label].data[region][stat] === undefined) {
+ scorecardDocument.results.blocks[label].data[region][stat] = {};
+ scorecardDocument.queryMap.blocks[label].data[region][stat] = {};
}
- curve.variable.forEach(function (variableText) {
+ scorecardCurve.variable.forEach(function (variableText) {
const variable = sanitizeKeys(variableText);
if (
- scorecardDocument.results.blocks[curve.label].data[region][stat][
- variable
- ] === undefined
+ scorecardDocument.results.blocks[label].data[region][stat][variable] ===
+ undefined
) {
- scorecardDocument.results.blocks[curve.label].data[region][stat][variable] =
- {};
- scorecardDocument.queryMap.blocks[curve.label].data[region][stat][
- variable
- ] = {};
+ scorecardDocument.results.blocks[label].data[region][stat][variable] = {};
+ scorecardDocument.queryMap.blocks[label].data[region][stat][variable] = {};
}
- curve.threshold.forEach(function (thresholdText) {
+ scorecardCurve.threshold.forEach(function (thresholdText) {
const threshold = sanitizeKeys(thresholdText);
if (
- scorecardDocument.results.blocks[curve.label].data[region][stat][
- variable
- ][threshold] === undefined
+ scorecardDocument.results.blocks[label].data[region][stat][variable][
+ threshold
+ ] === undefined
) {
- scorecardDocument.results.blocks[curve.label].data[region][stat][
- variable
- ][threshold] = {};
- scorecardDocument.queryMap.blocks[curve.label].data[region][stat][
- variable
- ][threshold] = {};
+ scorecardDocument.results.blocks[label].data[region][stat][variable][
+ threshold
+ ] = {};
+ scorecardDocument.queryMap.blocks[label].data[region][stat][variable][
+ threshold
+ ] = {};
}
- curve.level.forEach(function (levelText) {
+ scorecardCurve.level.forEach(function (levelText) {
const level = sanitizeKeys(levelText);
if (
- scorecardDocument.results.blocks[curve.label].data[region][stat][
- variable
- ][threshold][level] === undefined
+ scorecardDocument.results.blocks[label].data[region][stat][variable][
+ threshold
+ ][level] === undefined
) {
- scorecardDocument.results.blocks[curve.label].data[region][stat][
- variable
- ][threshold][level] = {};
- scorecardDocument.queryMap.blocks[curve.label].data[region][stat][
- variable
- ][threshold][level] = {};
+ scorecardDocument.results.blocks[label].data[region][stat][variable][
+ threshold
+ ][level] = {};
+ scorecardDocument.queryMap.blocks[label].data[region][stat][variable][
+ threshold
+ ][level] = {};
}
fcstLengths.forEach(function (fcstlenText) {
const fcstlen = sanitizeKeys(fcstlenText);
@@ -527,7 +531,7 @@ processScorecard = function (plotParams, plotFunction) {
// populate variable in query template -- partial sums
if (localQueryTemplate.includes("{{variable0}}")) {
const variableArray = variableMap[variableText];
- for (let vidx = 0; vidx < variableArray.length; vidx++) {
+ for (let vidx = 0; vidx < variableArray.length; vidx += 1) {
const replaceString = `{{variable${vidx.toString()}}}`;
const regex = new RegExp(replaceString, "g");
localQueryTemplate = localQueryTemplate.replace(
@@ -545,7 +549,7 @@ processScorecard = function (plotParams, plotFunction) {
if (application === "upperair") {
// the upper air tables are unfortuately really inconsistent and need some handling
localQueryTemplate = dealWithUATables(
- curve,
+ scorecardCurve,
regionValue,
databaseValue,
localQueryTemplate
@@ -558,22 +562,23 @@ processScorecard = function (plotParams, plotFunction) {
}
// populate experimental model in query template
- const experimentalModelValue = modelMap[curve["data-source"]];
+ const experimentalModelValue = modelMap[scorecardCurve["data-source"]];
const experimentalQueryTemplate = localQueryTemplate.replace(
/\{\{model\}\}/g,
experimentalModelValue
);
// populate control model in query template
- const controlModelValue = modelMap[curve["control-data-source"]];
+ const controlModelValue =
+ modelMap[scorecardCurve["control-data-source"]];
const controlQueryTemplate = localQueryTemplate.replace(
/\{\{model\}\}/g,
controlModelValue
);
- scorecardDocument.queryMap.blocks[curve.label].data[region][stat][
- variable
- ][threshold][level][fcstlen] = {
+ scorecardDocument.queryMap.blocks[label].data[region][stat][variable][
+ threshold
+ ][level][fcstlen] = {
experimentalQueryTemplate,
controlQueryTemplate,
};
@@ -583,18 +588,16 @@ processScorecard = function (plotParams, plotFunction) {
const sval = -9999;
if (
- scorecardDocument.results.blocks[curve.label].fcstlens.includes(
- fcstlen
- )
+ scorecardDocument.results.blocks[label].fcstlens.includes(fcstlen)
) {
- scorecardDocument.results.blocks[curve.label].data[region][stat][
- variable
- ][threshold][level][fcstlen] = sval;
+ scorecardDocument.results.blocks[label].data[region][stat][variable][
+ threshold
+ ][level][fcstlen] = sval;
} else {
// mark this undefined
- scorecardDocument.results.blocks[curve.label].data[region][stat][
- variable
- ][threshold][level][fcstlen] = "undefined";
+ scorecardDocument.results.blocks[label].data[region][stat][variable][
+ threshold
+ ][level][fcstlen] = "undefined";
}
});
});
@@ -640,10 +643,11 @@ processScorecard = function (plotParams, plotFunction) {
// to be in the public section of the scorecard settings file
// NOTE: For now we do not have scheduled jobs. When we do we will need to change this.
const notifyDataProcessorURL = `${Meteor.settings.public.vxdataProcessorUrl}`;
- const sDocument = `\{"docid": "${id}"\}`;
+ const sDocument = `{"docid": "${id}"}`;
HTTP.post(
notifyDataProcessorURL,
{ content: `${sDocument}` },
+ // eslint-disable-next-line no-unused-vars
function (error, response) {
if (error) {
console.log(error);
diff --git a/apps/scorecard/server/main.js b/apps/scorecard/server/main.js
index 77b1da5ffa..faed40c55d 100644
--- a/apps/scorecard/server/main.js
+++ b/apps/scorecard/server/main.js
@@ -3,10 +3,13 @@
*/
import { Meteor } from "meteor/meteor";
+import { moment } from "meteor/momentjs:moment";
import {
+ matsMethods,
matsTypes,
matsCollections,
matsDataUtils,
+ matsParamUtils,
matsCouchbaseUtils,
} from "meteor/randyp:mats-common";
@@ -619,7 +622,7 @@ const doCurveParams = function () {
const params = matsCollections.CurveParamsInfo.find({
curve_params: { $exists: true },
}).fetch()[0].curve_params;
- for (let cp = 0; cp < params.length; cp++) {
+ for (let cp = 0; cp < params.length; cp += 1) {
matsCollections[params[cp]].remove({});
}
}
@@ -657,8 +660,8 @@ const doCurveParams = function () {
let currentURL;
let queryURL;
let expectedApps = [];
- for (let aidx = 0; aidx < appsToScore.length; aidx++) {
- currentApp = Object.keys(appsToScore[aidx])[0];
+ for (let aidx = 0; aidx < appsToScore.length; aidx += 1) {
+ [currentApp] = Object.keys(appsToScore[aidx]);
currentURL = appsToScore[aidx][currentApp];
// clean up URL if users left a trailing slash or didn't include https://
@@ -677,7 +680,7 @@ const doCurveParams = function () {
);
// store the URL that was used to get each of these apps
- for (let eaidx = 0; eaidx < expectedApps.length; eaidx++) {
+ for (let eaidx = 0; eaidx < expectedApps.length; eaidx += 1) {
const thisApp = expectedApps[eaidx];
applicationSourceMap[thisApp] = currentApp;
}
@@ -910,10 +913,10 @@ const doCurveParams = function () {
// remove excluded stats from the scorecard
// we need to do this after the main metadata loop
// is finished or we don't have the full list of apps
- for (let aidx = 0; aidx < applicationOptions.length; aidx++) {
+ for (let aidx = 0; aidx < applicationOptions.length; aidx += 1) {
// loop through all the applications found inside the app list in the settings
const thisApp = applicationOptions[aidx];
- for (let sidx = statisticOptionsMap[thisApp].length - 1; sidx >= 0; sidx--) {
+ for (let sidx = statisticOptionsMap[thisApp].length - 1; sidx >= 0; sidx -= 1) {
// loop backwards through the statistics for this app
const thisStat = statisticOptionsMap[thisApp][sidx];
if (matsDataUtils.excludeStatFromScorecard(thisStat)) {
@@ -924,7 +927,7 @@ const doCurveParams = function () {
}
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
if (matsCollections.label.findOne({ name: "label" }) === undefined) {
@@ -979,7 +982,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.application.findOne({ name: "application" });
+ const currentParam = matsCollections.application.findOne({ name: "application" });
if (!matsDataUtils.areObjectsEqual(currentParam.dates, dateOptionsMap)) {
// have to reload application data
matsCollections.application.update(
@@ -1023,7 +1026,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["data-source"].findOne({ name: "data-source" });
+ const currentParam = matsCollections["data-source"].findOne({
+ name: "data-source",
+ });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap)) {
// have to reload model data
matsCollections["data-source"].update(
@@ -1069,7 +1074,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["control-data-source"].findOne({
+ const currentParam = matsCollections["control-data-source"].findOne({
name: "control-data-source",
});
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap)) {
@@ -1115,7 +1120,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.region.findOne({ name: "region" });
+ const currentParam = matsCollections.region.findOne({ name: "region" });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, regionOptionsMap)) {
// have to reload region data
matsCollections.region.update(
@@ -1159,7 +1164,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.statistic.findOne({ name: "statistic" });
+ const currentParam = matsCollections.statistic.findOne({ name: "statistic" });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, statisticOptionsMap)) {
// have to reload statistic data
matsCollections.statistic.update(
@@ -1196,7 +1201,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.variable.findOne({ name: "variable" });
+ const currentParam = matsCollections.variable.findOne({ name: "variable" });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, variableOptionsMap)) {
// have to reload variable data
matsCollections.variable.update(
@@ -1244,7 +1249,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.threshold.findOne({ name: "threshold" });
+ const currentParam = matsCollections.threshold.findOne({ name: "threshold" });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, thresholdOptionsMap)) {
// have to reload threshold data
matsCollections.threshold.update(
@@ -1297,7 +1302,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.scale.findOne({ name: "scale" });
+ const currentParam = matsCollections.scale.findOne({ name: "scale" });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, scaleOptionsMap)) {
// have to reload scale data
matsCollections.scale.update(
@@ -1350,7 +1355,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.truth.findOne({ name: "truth" });
+ const currentParam = matsCollections.truth.findOne({ name: "truth" });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, truthOptionsMap)) {
// have to reload truth data
matsCollections.truth.update(
@@ -1403,7 +1408,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["forecast-length"].findOne({
+ const currentParam = matsCollections["forecast-length"].findOne({
name: "forecast-length",
});
if (
@@ -1459,7 +1464,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["forecast-type"].findOne({
+ const currentParam = matsCollections["forecast-type"].findOne({
name: "forecast-type",
});
if (
@@ -1511,7 +1516,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["valid-time"].findOne({ name: "valid-time" });
+ const currentParam = matsCollections["valid-time"].findOne({ name: "valid-time" });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, validTimeOptionsMap)) {
// have to reload valid time data
matsCollections["valid-time"].update(
@@ -1556,7 +1561,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.level.findOne({ name: "level" });
+ const currentParam = matsCollections.level.findOne({ name: "level" });
if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, levelOptionsMap)) {
// have to reload level data
matsCollections.level.update(
@@ -1674,7 +1679,8 @@ const doPlotGraph = function () {
Meteor.startup(function () {
matsCollections.Databases.remove({});
if (matsCollections.Databases.find({}).count() < 0) {
- console.log(
+ // eslint-disable-next-line no-console
+ console.warn(
"main startup: corrupted Databases collection: dropping Databases collection"
);
matsCollections.Databases.drop();
@@ -1691,7 +1697,7 @@ Meteor.startup(function () {
databases = Meteor.settings.private.databases;
}
if (databases !== null && databases !== undefined && Array.isArray(databases)) {
- for (let di = 0; di < databases.length; di++) {
+ for (let di = 0; di < databases.length; di += 1) {
matsCollections.Databases.insert(databases[di]);
}
}
@@ -1723,6 +1729,7 @@ Meteor.startup(function () {
cbConnections.forEach(function (cbConnection) {
if (cbConnection.collection === "METAR") {
// global cbPool
+ // eslint-disable-next-line no-undef
cbPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1735,6 +1742,7 @@ Meteor.startup(function () {
}
if (cbConnection.collection === "SCORECARD") {
// global cbScorecardPool
+ // eslint-disable-next-line no-undef
cbScorecardPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1750,6 +1758,7 @@ Meteor.startup(function () {
}
if (cbConnection.collection === "SCORECARD_SETTINGS") {
// global cbScorecardSettingsPool
+ // eslint-disable-next-line no-undef
cbScorecardSettingsPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1776,7 +1785,7 @@ Meteor.startup(function () {
dbType: matsTypes.DbTypes.couchbase,
});
} catch (error) {
- console.log(error.message);
+ throw new Error(error.message);
}
});
@@ -1784,6 +1793,7 @@ Meteor.startup(function () {
// These are application specific mongo data - like curve params
// The appSpecificResetRoutines object is a special name,
// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way.
+// eslint-disable-next-line no-undef
appSpecificResetRoutines = [
doCurveParams,
doPlotGraph,
diff --git a/apps/surface/.eslintrc.json b/apps/surface/.eslintrc.json
index e5e813ea94..79d49c5bb6 100644
--- a/apps/surface/.eslintrc.json
+++ b/apps/surface/.eslintrc.json
@@ -28,23 +28,6 @@
"space-before-function-paren": "off",
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
- "prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
- "no-undef": "warn",
- "no-plusplus": "warn",
- "vars-on-top": "warn",
- "no-var": "warn",
- "block-scoped-var": "warn",
- "no-loop-func": "warn",
- "no-unused-vars": "warn",
- "prefer-destructuring": "warn",
- "no-param-reassign": "warn",
- "camelcase": "warn",
- "no-redeclare": "warn",
- "no-shadow": "warn"
+ "prefer-arrow-callback": "off"
}
}
diff --git a/apps/surface/client/main.js b/apps/surface/client/main.js
index a87407a1f4..ecd922b6a2 100644
--- a/apps/surface/client/main.js
+++ b/apps/surface/client/main.js
@@ -2,6 +2,7 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+// eslint-disable-next-line no-unused-vars
import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common";
import "@fortawesome/fontawesome-free";
import "@fortawesome/fontawesome-free/css/all.css";
diff --git a/apps/surface/server/dataFunctions/data_contour.js b/apps/surface/server/dataFunctions/data_contour.js
index 52046e6ff7..dcfe1260bd 100644
--- a/apps/surface/server/dataFunctions/data_contour.js
+++ b/apps/surface/server/dataFunctions/data_contour.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContour = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,68 +23,87 @@ dataContour = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
- const totalProcessingStart = moment();
+
+ const curves = JSON.parse(JSON.stringify(plotParams.curves));
+ if (curves.length > 1) {
+ throw new Error("INFO: There must only be one added curve.");
+ }
+
+ const axisMap = Object.create(null);
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- const curves = JSON.parse(JSON.stringify(plotParams.curves));
- if (curves.length > 1) {
- throw new Error("INFO: There must only be one added curve.");
- }
- const dataset = [];
- const axisMap = Object.create(null);
- // initialize variables specific to the curve
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- const metarStringStr = curve.truth;
- const metarString = Object.keys(
- matsCollections.truth.findOne({ name: "truth" }).valuesMap
- ).find(
- (key) =>
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[key] === metarStringStr
- );
- const regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${model}_${metarString}_${region} as m0`;
- // contours are only for predefined regions--no station plots
+
const regionType = "Predefined region";
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[regionType][variableStr];
+
+ const metarStringStr = curve.truth;
+ const metarString = Object.keys(
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[key] === metarStringStr
+ );
+
let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.hour IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ `sum(${variable[0]}) as square_diff_sum, sum(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
+ `group_concat(m0.valid_day+3600*m0.hour, ';', ${variable[0]}, ';', ${variable[1]}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variable[0]}) as N0`;
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -94,106 +114,115 @@ dataContour = function (plotParams, plotFunction) {
dateString = "m0.valid_day+3600*m0.hour";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- `sum(${variable[0]}) as square_diff_sum, sum(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
- `group_concat(m0.valid_day+3600*m0.hour, ';', ${variable[0]}, ';', ${variable[1]}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variable[0]}) as N0`;
- const statType = statisticOptionsMap[statisticSelect];
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+
+ const queryTableClause = `from ${model}_${metarString}_${region} as m0`;
+
+ // For contours, this functions as the colorbar label.
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
+ const statType = statisticOptionsMap[statisticSelect];
const varUnits = statVarUnitMap[statisticSelect][variableStr];
-
- // For contours, this functions as the colorbar label.
curve.unitKey = varUnits;
let d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
-
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- `${statisticSelect}_${variableStr}`
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- if (error.includes("Unknown column")) {
- throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for the model/region [${model} and ${region}].`
- );
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
+
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ `${statisticSelect}_${variableStr}`
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
+ }
+
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
+ // this is NOT an error just a no data condition
+ dataFoundForCurve = false;
} else {
- throw new Error(error);
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ if (error.includes("Unknown column")) {
+ throw new Error(
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for this model and region].`
+ );
+ } else {
+ throw new Error(error);
+ }
}
}
- }
- if (!dataFoundForCurve) {
- // we found no data for any curves so don't bother proceeding
- throw new Error("INFO: No valid data for any curves.");
+ if (!dataFoundForCurve) {
+ // we found no data for any curves so don't bother proceeding
+ throw new Error("INFO: No valid data for any curves.");
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
}
- const postQueryStartMoment = moment();
-
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
diff --git a/apps/surface/server/dataFunctions/data_contour_diff.js b/apps/surface/server/dataFunctions/data_contour_diff.js
index faa62f66ff..957a9924ca 100644
--- a/apps/surface/server/dataFunctions/data_contour_diff.js
+++ b/apps/surface/server/dataFunctions/data_contour_diff.js
@@ -14,6 +14,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContourDiff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -24,36 +25,57 @@ dataContourDiff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
let dataNotFoundForAnyCurve = false;
+
+ let curves = JSON.parse(JSON.stringify(plotParams.curves));
+ const curvesLength = curves.length;
+ if (curvesLength !== 2) {
+ throw new Error("INFO: There must be two added curves.");
+ }
+
+ const axisMap = Object.create(null);
const showSignificance = plotParams.significance !== "none";
- const totalProcessingStart = moment();
+
+ let statType;
+ let statisticSelect;
+ let variableStr;
+
+ let statement = "";
+ let error = "";
+ let dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- let curves = JSON.parse(JSON.stringify(plotParams.curves));
- const curvesLength = curves.length;
- if (curvesLength !== 2) {
- throw new Error("INFO: There must be two added curves.");
- }
- let dataset = [];
- const axisMap = Object.create(null);
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var metarStringStr = curve.truth;
+
+ const regionType = "Predefined region";
+
+ variableStr = curve.variable;
+ const variableOptionsMap = matsCollections.variable.findOne(
+ { name: "variable" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const variable = variableOptionsMap[regionType][variableStr];
+
+ const metarStringStr = curve.truth;
const metarString = Object.keys(
matsCollections.truth.findOne({ name: "truth" }).valuesMap
).find(
@@ -61,36 +83,37 @@ dataContourDiff = function (plotParams, plotFunction) {
matsCollections.truth.findOne({ name: "truth" }).valuesMap[key] ===
metarStringStr
);
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${model}_${metarString}_${region} as m0`;
- // contours are only for predefined regions--no station plots
- const regionType = "Predefined region";
- var variableStr = curve.variable;
- const variableOptionsMap = matsCollections.variable.findOne(
- { name: "variable" },
- { optionsMap: 1 }
- ).optionsMap;
- const variable = variableOptionsMap[regionType][variableStr];
+
let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.hour IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ `sum(${variable[0]}) as square_diff_sum, sum(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
+ `group_concat(m0.valid_day+3600*m0.hour, ';', ${variable[0]}, ';', ${variable[1]}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variable[0]}) as N0`;
+
+ let dateString = "";
+ let dateClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -101,102 +124,108 @@ dataContourDiff = function (plotParams, plotFunction) {
dateString = "m0.valid_day+3600*m0.hour";
}
dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- var statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- `sum(${variable[0]}) as square_diff_sum, sum(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
- `group_concat(m0.valid_day+3600*m0.hour, ';', ${variable[0]}, ';', ${variable[1]}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+
+ const queryTableClause = `from ${model}_${metarString}_${region} as m0`;
+
+ // For contours, this functions as the colorbar label.
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
+ statType = statisticOptionsMap[statisticSelect];
const varUnits = statVarUnitMap[statisticSelect][variableStr];
-
- // For contours, this functions as the colorbar label.
curves[curveIndex].unitKey = varUnits;
- var d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
+ let d;
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- `${statisticSelect}_${variableStr}`
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- if (error.includes("Unknown column")) {
- throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for the model/region [${model} and ${region}].`
- );
- } else {
- throw new Error(error);
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ `${statisticSelect}_${variableStr}`
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
+ }
+
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ if (error.includes("Unknown column")) {
+ throw new Error(
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for this model and region].`
+ );
+ } else {
+ throw new Error(error);
+ }
}
+ dataNotFoundForAnyCurve = true;
}
- dataNotFoundForAnyCurve = true;
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
}
- const postQueryStartMoment = moment();
-
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
@@ -245,8 +274,9 @@ dataContourDiff = function (plotParams, plotFunction) {
statType === "ctc",
statType === "scalar"
);
- plotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
- curves = plotParams.curves;
+ const newPlotParams = plotParams;
+ newPlotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
+ curves = newPlotParams.curves;
dataset[0].name = matsPlotUtils.getCurveText(
matsTypes.PlotTypes.contourDiff,
curves[0]
@@ -262,7 +292,7 @@ dataContourDiff = function (plotParams, plotFunction) {
const result = matsDataProcessUtils.processDataContour(
dataset,
curveInfoParams,
- plotParams,
+ newPlotParams,
bookkeepingParams
);
plotFunction(result);
diff --git a/apps/surface/server/dataFunctions/data_dailymodelcycle.js b/apps/surface/server/dataFunctions/data_dailymodelcycle.js
index 9bb3b5aa3a..c28e0d9868 100644
--- a/apps/surface/server/dataFunctions/data_dailymodelcycle.js
+++ b/apps/surface/server/dataFunctions/data_dailymodelcycle.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDailyModelCycle = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,54 +24,78 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
+
let queryTableClause = "";
const regionType = curve["region-type"];
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[regionType][variableStr];
+
let utcCycleStartClause = "";
+
const forecastLength = curve["forecast-length"];
const forecastLengthClause = "and m0.fcst_len < 24";
- var timeVar;
- var dateClause;
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+
+ let timeVar;
+ let dateClause;
let siteDateClause = "";
let siteMatchClause = "";
let sitesClause = "";
- var NAggregate;
- var NClause;
- var queryPool;
+ let NAggregate;
+ let NClause;
+ let queryPool;
+
if (regionType === "Predefined region") {
timeVar = "m0.valid_day+3600*m0.hour";
- var metarStringStr = curve.truth;
+ dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
+ NAggregate = "sum";
+ [, NClause] = variable;
+
+ const metarStringStr = curve.truth;
const metarString = Object.keys(
matsCollections.truth.findOne({ name: "truth" }).valuesMap
).find(
@@ -78,8 +103,9 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
matsCollections.truth.findOne({ name: "truth" }).valuesMap[key] ===
metarStringStr
);
- var regionStr = curve.region;
- var region = Object.keys(
+
+ const regionStr = curve.region;
+ const region = Object.keys(
matsCollections.region.findOne({ name: "region" }).valuesMap
).find(
(key) =>
@@ -87,13 +113,16 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
regionStr
);
queryTableClause = `from ${model}_${metarString}_${region} as m0`;
- dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
- NAggregate = "sum";
- NClause = variable[1];
- queryPool = sumPool;
+ queryPool = sumPool; // eslint-disable-line no-undef
} else {
timeVar = "m0.time";
- var modelTable;
+ dateClause = `and m0.time >= ${fromSecs} - 900 and m0.time <= ${toSecs} + 900`;
+ siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
+ siteMatchClause = "and m0.sta_id = o.sta_id and m0.time = o.time";
+ NAggregate = "count";
+ NClause = "1";
+
+ let modelTable;
if (forecastLength === 1) {
modelTable = `${model}qp1f`;
} else {
@@ -108,28 +137,20 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
{ optionsMap: 1 }
).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- var thisSite;
- var thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.sta_id in('${querySites.join("','")}')`;
} else {
throw new Error(
"INFO: Please add sites in order to get a single/multi station plot."
);
}
- dateClause = `and m0.time >= ${fromSecs} - 900 and m0.time <= ${toSecs} + 900`;
- siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
- siteMatchClause = "and m0.sta_id = o.sta_id and m0.time = o.time";
- NAggregate = "count";
- NClause = "1";
- queryPool = sitePool;
+ queryPool = sitePool; // eslint-disable-line no-undef
}
+
if (curve["utc-cycle-start"].length !== 1) {
throw new Error(
"INFO: Please select exactly one UTC Cycle Init Hour for this plot type."
@@ -142,72 +163,68 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
} else {
utcCycleStartClause = `and floor(((${timeVar}+1800)-m0.fcst_len*3600)%(24*3600)/3600) IN(${utcCycleStart})`; // adjust by 1800 seconds to center obs at the top of the hour
}
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
+
const statisticClause =
`sum(${variable[0]}) as square_diff_sum, ${NAggregate}(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
`group_concat(${timeVar}, ';', ${variable[0]}, ';', ${NClause}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by ${timeVar}) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
+ // axisKey is used to determine which axis a curve should use.
+ // This axisKeySet object is used like a set and if a curve has the same
+ // units (axisKey) it will use the same axis.
+ // The axis number is assigned to the axisKeySet value, which is the axisKey.
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
+ statType = statisticOptionsMap[statisticSelect];
const varUnits = statVarUnitMap[statisticSelect][variableStr];
- // axisKey is used to determine which axis a curve should use.
- // This axisKeySet object is used like a set and if a curve has the same
- // units (axisKey) it will use the same axis.
- // The axis number is assigned to the axisKeySet value, which is the axisKey.
const axisKey = varUnits;
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select ceil(3600*floor(({{timeVar}}+1800)/3600)) as avtime, " +
- "count(distinct ceil(3600*floor(({{timeVar}}+1800)/3600))) as N_times, " +
- "min(ceil(3600*floor(({{timeVar}}+1800)/3600))) as min_secs, " +
- "max(ceil(3600*floor(({{timeVar}}+1800)/3600))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{utcCycleStartClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- statement = statement.split("{{timeVar}}").join(timeVar);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select ceil(3600*floor(({{timeVar}}+1800)/3600)) as avtime, " +
+ "count(distinct ceil(3600*floor(({{timeVar}}+1800)/3600))) as N_times, " +
+ "min(ceil(3600*floor(({{timeVar}}+1800)/3600))) as min_secs, " +
+ "max(ceil(3600*floor(({{timeVar}}+1800)/3600))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{utcCycleStartClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ statement = statement.split("{{timeVar}}").join(timeVar);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- queryPool,
+ queryPool, // eslint-disable-line no-undef
statement,
appParams,
`${statisticSelect}_${variableStr}`
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -223,6 +240,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -232,7 +250,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
if (error.includes("Unknown column")) {
throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for the model/region [${model} and ${region}].`
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for this model and region].`
);
} else {
throw new Error(error);
@@ -243,7 +261,6 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -268,6 +285,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/surface/server/dataFunctions/data_dieoff.js b/apps/surface/server/dataFunctions/data_dieoff.js
index fc82e69855..d64e6ddb29 100644
--- a/apps/surface/server/dataFunctions/data_dieoff.js
+++ b/apps/surface/server/dataFunctions/data_dieoff.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDieoff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,57 +24,80 @@ dataDieoff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
+
let queryTableClause = "";
const regionType = curve["region-type"];
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[regionType][variableStr];
+
const forecastLengthStr = curve["dieoff-type"];
const forecastLengthOptionsMap = matsCollections["dieoff-type"].findOne(
{ name: "dieoff-type" },
{ optionsMap: 1 }
).optionsMap;
const forecastLength = forecastLengthOptionsMap[forecastLengthStr][0];
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
- var timeVar;
- var dateClause;
+
+ let timeVar;
+ let dateClause;
let siteDateClause = "";
let siteMatchClause = "";
let sitesClause = "";
- var NAggregate;
- var NClause;
- var queryPool;
+ let NAggregate;
+ let NClause;
+ let queryPool;
+
if (regionType === "Predefined region") {
timeVar = "m0.valid_day+3600*m0.hour";
- var metarStringStr = curve.truth;
+ dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
+ NAggregate = "sum";
+ [, NClause] = variable;
+
+ const metarStringStr = curve.truth;
const metarString = Object.keys(
matsCollections.truth.findOne({ name: "truth" }).valuesMap
).find(
@@ -81,8 +105,9 @@ dataDieoff = function (plotParams, plotFunction) {
matsCollections.truth.findOne({ name: "truth" }).valuesMap[key] ===
metarStringStr
);
- var regionStr = curve.region;
- var region = Object.keys(
+
+ const regionStr = curve.region;
+ const region = Object.keys(
matsCollections.region.findOne({ name: "region" }).valuesMap
).find(
(key) =>
@@ -90,12 +115,15 @@ dataDieoff = function (plotParams, plotFunction) {
regionStr
);
queryTableClause = `from ${model}_${metarString}_${region} as m0`;
- dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
- NAggregate = "sum";
- NClause = variable[1];
- queryPool = sumPool;
+ queryPool = sumPool; // eslint-disable-line no-undef
} else {
timeVar = "m0.time";
+ dateClause = `and m0.time >= ${fromSecs} - 900 and m0.time <= ${toSecs} + 900`;
+ siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
+ siteMatchClause = "and m0.sta_id = o.sta_id and m0.time = o.time";
+ NAggregate = "count";
+ NClause = "1";
+
const modelTable =
model.includes("ret_") || model.includes("Ret_") ? `${model}p` : `${model}qp`;
const obsTable =
@@ -106,32 +134,26 @@ dataDieoff = function (plotParams, plotFunction) {
{ optionsMap: 1 }
).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- var thisSite;
- var thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.sta_id in('${querySites.join("','")}')`;
} else {
throw new Error(
"INFO: Please add sites in order to get a single/multi station plot."
);
}
- dateClause = `and m0.time >= ${fromSecs} - 900 and m0.time <= ${toSecs} + 900`;
- siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
- siteMatchClause = "and m0.sta_id = o.sta_id and m0.time = o.time";
- NAggregate = "count";
- NClause = "1";
- queryPool = sitePool;
+ queryPool = sitePool; // eslint-disable-line no-undef
}
- var validTimes;
+
+ let validTimes;
let validTimeClause = "";
- var utcCycleStart;
+
+ let utcCycleStart;
let utcCycleStartClause = "";
+
if (forecastLength === matsTypes.ForecastTypes.dieoff) {
validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
@@ -151,72 +173,69 @@ dataDieoff = function (plotParams, plotFunction) {
} else {
dateClause = `and ${timeVar}-m0.fcst_len*3600 = ${fromSecs}`;
}
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
+
const statisticClause =
`sum(${variable[0]}) as square_diff_sum, ${NAggregate}(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
`group_concat(${timeVar}, ';', ${variable[0]}, ';', ${NClause}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by ${timeVar}) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
+
+ // axisKey is used to determine which axis a curve should use.
+ // This axisKeySet object is used like a set and if a curve has the same
+ // units (axisKey) it will use the same axis.
+ // The axis number is assigned to the axisKeySet value, which is the axisKey.
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
+ statType = statisticOptionsMap[statisticSelect];
const varUnits = statVarUnitMap[statisticSelect][variableStr];
- // axisKey is used to determine which axis a curve should use.
- // This axisKeySet object is used like a set and if a curve has the same
- // units (axisKey) it will use the same axis.
- // The axis number is assigned to the axisKeySet value, which is the axisKey.
const axisKey = varUnits;
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.fcst_len as fcst_lead, " +
- "count(distinct ceil(3600*floor(({{timeVar}}+1800)/3600))) as N_times, " +
- "min(ceil(3600*floor(({{timeVar}}+1800)/3600))) as min_secs, " +
- "max(ceil(3600*floor(({{timeVar}}+1800)/3600))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{validTimeClause}} " +
- "{{utcCycleStartClause}} " +
- "group by fcst_lead " +
- "order by fcst_lead" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- statement = statement.split("{{timeVar}}").join(timeVar);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.fcst_len as fcst_lead, " +
+ "count(distinct ceil(3600*floor(({{timeVar}}+1800)/3600))) as N_times, " +
+ "min(ceil(3600*floor(({{timeVar}}+1800)/3600))) as min_secs, " +
+ "max(ceil(3600*floor(({{timeVar}}+1800)/3600))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{validTimeClause}} " +
+ "{{utcCycleStartClause}} " +
+ "group by fcst_lead " +
+ "order by fcst_lead" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ statement = statement.split("{{timeVar}}").join(timeVar);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- queryPool,
+ queryPool, // eslint-disable-line no-undef
statement,
appParams,
`${statisticSelect}_${variableStr}`
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -232,6 +251,7 @@ dataDieoff = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -241,7 +261,7 @@ dataDieoff = function (plotParams, plotFunction) {
error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
if (error.includes("Unknown column")) {
throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for the model/region [${model} and ${region}].`
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for this model and region].`
);
} else {
throw new Error(error);
@@ -252,7 +272,6 @@ dataDieoff = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -277,6 +296,7 @@ dataDieoff = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/surface/server/dataFunctions/data_histogram.js b/apps/surface/server/dataFunctions/data_histogram.js
index 4d6298a4a7..1d674000cc 100644
--- a/apps/surface/server/dataFunctions/data_histogram.js
+++ b/apps/surface/server/dataFunctions/data_histogram.js
@@ -11,6 +11,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataHistogram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -21,57 +22,82 @@ dataHistogram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
- const alreadyMatched = false;
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
const dataFoundForCurve = [];
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+ const alreadyMatched = false;
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
+
+ const axisMap = Object.create(null);
+ let statType;
+ let varUnits;
+
+ let statement = "";
+ let error = "";
const dataset = [];
const allReturnedSubStats = [];
const allReturnedSubSecs = [];
- const axisMap = Object.create(null);
// process user bin customizations
const binParams = matsDataUtils.setHistogramParameters(plotParams);
const { yAxisFormat } = binParams;
const { binNum } = binParams;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
dataFoundForCurve[curveIndex] = true;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
+
let queryTableClause = "";
const regionType = curve["region-type"];
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[regionType][variableStr];
+
let validTimeClause = "";
+
const forecastLength = curve["forecast-length"];
let forecastLengthClause = "";
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
- var timeVar;
- var dateClause;
+
+ let timeVar;
+ let dateClause;
let siteDateClause = "";
let siteMatchClause = "";
let sitesClause = "";
- var NAggregate;
- var NClause;
- var queryPool;
+ let NAggregate;
+ let NClause;
+ let queryPool;
+
if (regionType === "Predefined region") {
timeVar = "m0.valid_day+3600*m0.hour";
- var metarStringStr = curve.truth;
+ forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
+ dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
+ NAggregate = "sum";
+ [, NClause] = variable;
+
+ const metarStringStr = curve.truth;
const metarString = Object.keys(
matsCollections.truth.findOne({ name: "truth" }).valuesMap
).find(
@@ -79,8 +105,9 @@ dataHistogram = function (plotParams, plotFunction) {
matsCollections.truth.findOne({ name: "truth" }).valuesMap[key] ===
metarStringStr
);
- var regionStr = curve.region;
- var region = Object.keys(
+
+ const regionStr = curve.region;
+ const region = Object.keys(
matsCollections.region.findOne({ name: "region" }).valuesMap
).find(
(key) =>
@@ -88,14 +115,16 @@ dataHistogram = function (plotParams, plotFunction) {
regionStr
);
queryTableClause = `from ${model}_${metarString}_${region} as m0`;
- forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
- NAggregate = "sum";
- NClause = variable[1];
- queryPool = sumPool;
+ queryPool = sumPool; // eslint-disable-line no-undef
} else {
timeVar = "m0.time";
- var modelTable;
+ dateClause = `and m0.time >= ${fromSecs} - 900 and m0.time <= ${toSecs} + 900`;
+ siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
+ siteMatchClause = "and m0.sta_id = o.sta_id and m0.time = o.time";
+ NAggregate = "count";
+ NClause = "1";
+
+ let modelTable;
if (forecastLength === 1) {
modelTable = `${model}qp1f`;
forecastLengthClause = "";
@@ -112,50 +141,38 @@ dataHistogram = function (plotParams, plotFunction) {
{ optionsMap: 1 }
).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- var thisSite;
- var thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.sta_id in('${querySites.join("','")}')`;
} else {
throw new Error(
"INFO: Please add sites in order to get a single/multi station plot."
);
}
- dateClause = `and m0.time >= ${fromSecs} - 900 and m0.time <= ${toSecs} + 900`;
- siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
- siteMatchClause = "and m0.sta_id = o.sta_id and m0.time = o.time";
- NAggregate = "count";
- NClause = "1";
- queryPool = sitePool;
+ queryPool = sitePool; // eslint-disable-line no-undef
}
+
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((${timeVar}+1800)%(24*3600)/3600) IN(${validTimes})`; // adjust by 1800 seconds to center obs at the top of the hour
}
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
+
const statisticClause =
`sum(${variable[0]}) as square_diff_sum, ${NAggregate}(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
`group_concat(${timeVar}, ';', ${variable[0]}, ';', ${NClause}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by ${timeVar}) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
- const { statVarUnitMap } = matsCollections.variable.findOne(
- { name: "variable" },
- { statVarUnitMap: 1 }
- );
- var varUnits = statVarUnitMap[statisticSelect][variableStr];
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ const { statVarUnitMap } = matsCollections.variable.findOne(
+ { name: "variable" },
+ { statVarUnitMap: 1 }
+ );
+ statType = statisticOptionsMap[statisticSelect];
+ varUnits = statVarUnitMap[statisticSelect][variableStr];
let axisKey = yAxisFormat;
if (yAxisFormat === "Relative frequency") {
axisKey += " (x100)";
@@ -163,51 +180,51 @@ dataHistogram = function (plotParams, plotFunction) {
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
curves[curveIndex].binNum = binNum; // stash the binNum to use it later for bar chart options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select ceil(3600*floor(({{timeVar}}+1800)/3600)) as avtime, " +
- "count(distinct ceil(3600*floor(({{timeVar}}+1800)/3600))) as N_times, " +
- "min(ceil(3600*floor(({{timeVar}}+1800)/3600))) as min_secs, " +
- "max(ceil(3600*floor(({{timeVar}}+1800)/3600))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- statement = statement.split("{{timeVar}}").join(timeVar);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select ceil(3600*floor(({{timeVar}}+1800)/3600)) as avtime, " +
+ "count(distinct ceil(3600*floor(({{timeVar}}+1800)/3600))) as N_times, " +
+ "min(ceil(3600*floor(({{timeVar}}+1800)/3600))) as min_secs, " +
+ "max(ceil(3600*floor(({{timeVar}}+1800)/3600))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ statement = statement.split("{{timeVar}}").join(timeVar);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- queryPool,
+ queryPool, // eslint-disable-line no-undef
statement,
appParams,
`${statisticSelect}_${variableStr}`
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -225,6 +242,7 @@ dataHistogram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -234,7 +252,7 @@ dataHistogram = function (plotParams, plotFunction) {
error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
if (error.includes("Unknown column")) {
throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for the model/region [${model} and ${region}].`
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for this model and region].`
);
} else {
throw new Error(error);
diff --git a/apps/surface/server/dataFunctions/data_map.js b/apps/surface/server/dataFunctions/data_map.js
index 8c5ade2115..e1c17713e1 100644
--- a/apps/surface/server/dataFunctions/data_map.js
+++ b/apps/surface/server/dataFunctions/data_map.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataMap = function (plotParams, plotFunction) {
const appParams = {
plotType: matsTypes.PlotTypes.map,
@@ -21,38 +22,52 @@ dataMap = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
- const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
+
const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+ const dataRequests = {}; // used to store data queries
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
if (curves.length > 1) {
throw new Error("INFO: There must only be one added curve.");
}
+
+ let statement = "";
+ let error = "";
const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- // map plots are only for stations--no predefined regions
+
const regionType = "Select stations";
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[regionType][variableStr];
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
- validTimeClause = `and floor((m0.time+1800)%(24*3600)/3600) IN(${validTimes})`; // adjust by 1800 seconds to center obs at the top of the hour
+ validTimeClause = `and floor((m0.time+1800)%(24*3600)/3600) IN(${validTimes})`;
}
+
const forecastLength = curve["forecast-length"];
let forecastLengthClause = "";
+
+ const statisticSelect = curve.statistic;
+
let sitesClause = "";
+
let modelTable;
if (forecastLength === 1) {
modelTable = `${model}qp1f`;
@@ -70,15 +85,11 @@ dataMap = function (plotParams, plotFunction) {
{ optionsMap: 1 }
).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- let thisSite;
- let thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.sta_id in('${querySites.join("','")}')`;
} else {
throw new Error(
@@ -88,103 +99,114 @@ dataMap = function (plotParams, plotFunction) {
const dateClause = `and m0.time >= ${fromSecs} - 900 and m0.time <= ${toSecs} + 900`;
const siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
const siteMatchClause = "and m0.sta_id = o.sta_id and m0.time = o.time";
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
+
const statisticClause =
`sum(${variable[0]}) as square_diff_sum, count(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
`group_concat(m0.time, ';', ${variable[0]}, ';', 1, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.time) as sub_data, count(${variable[0]}) as N0`;
- const statType = statisticOptionsMap[statisticSelect];
+
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
const varUnits = statVarUnitMap[statisticSelect][variableStr];
- let statement =
- "select m0.sta_id as sta_id, " +
- "count(distinct ceil(3600*floor((m0.time+1800)/3600))) as N_times, " +
- "min(ceil(3600*floor((m0.time+1800)/3600))) as min_secs, " +
- "max(ceil(3600*floor((m0.time+1800)/3600))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by sta_id " +
- "order by sta_id" +
- ";";
+ let d;
+ let dLowest;
+ let dLow;
+ let dModerate;
+ let dHigh;
+ let dHighest;
+ let valueLimits;
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "select m0.sta_id as sta_id, " +
+ "count(distinct ceil(3600*floor((m0.time+1800)/3600))) as N_times, " +
+ "min(ceil(3600*floor((m0.time+1800)/3600))) as min_secs, " +
+ "max(ceil(3600*floor((m0.time+1800)/3600))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by sta_id " +
+ "order by sta_id" +
+ ";";
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- dataRequests[label] = statement;
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ dataRequests[label] = statement;
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBMapScalar(
- sitePool,
- statement,
- model,
- statisticSelect,
- variableStr,
- varUnits,
- siteMap,
- appParams
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.length,
- };
- // get the data back from the query
- var d = queryResult.data;
- var dLowest = queryResult.dataLowest;
- var dLow = queryResult.dataLow;
- var dModerate = queryResult.dataModerate;
- var dHigh = queryResult.dataHigh;
- var dHighest = queryResult.dataHighest;
- var { valueLimits } = queryResult;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- if (error.includes("Unknown column")) {
- throw new Error(
- `INFO: The variable [${variableStr}] is not supported by the database for the model/sites [${model} and ${sitesList}].`
- );
- } else {
- throw new Error(error);
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBMapScalar(
+ sitePool, // eslint-disable-line no-undef
+ statement,
+ model,
+ statisticSelect,
+ variableStr,
+ varUnits,
+ siteMap,
+ appParams
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = "Station plot -- no one query.";
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ dLowest = queryResult.dataLowest;
+ dLow = queryResult.dataLow;
+ dModerate = queryResult.dataModerate;
+ dHigh = queryResult.dataHigh;
+ dHighest = queryResult.dataHighest;
+ valueLimits = queryResult.valueLimits;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
+ }
+
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ if (error.includes("Unknown column")) {
+ throw new Error(
+ `INFO: The variable [${variableStr}] is not supported by the database for the model/sites [${model} and ${sitesList}].`
+ );
+ } else {
+ throw new Error(error);
+ }
}
}
+ } else {
+ // this is a difference curve -- not supported for maps
+ throw new Error(
+ "INFO: Difference curves are not supported for maps, as there is only one curve."
+ );
}
+ const postQueryStartMoment = moment();
let cOptions = matsDataCurveOpsUtils.generateMapCurveOptions(
curve,
d,
@@ -252,6 +274,15 @@ dataMap = function (plotParams, plotFunction) {
); // generate highest text layer
dataset.push(cOptions);
+ const postQueryFinishMoment = moment();
+ dataRequests[`post data retrieval (query) process time - ${label}`] = {
+ begin: postQueryStartMoment.format(),
+ finish: postQueryFinishMoment.format(),
+ duration: `${moment
+ .duration(postQueryFinishMoment.diff(postQueryStartMoment))
+ .asSeconds()} seconds`,
+ };
+
const resultOptions = matsDataPlotOpsUtils.generateMapPlotOptions(false);
const totalProcessingFinish = moment();
dataRequests["total retrieval and processing time for curve set"] = {
diff --git a/apps/surface/server/dataFunctions/data_series.js b/apps/surface/server/dataFunctions/data_series.js
index 1fc2ea65be..b9c9d3d06f 100644
--- a/apps/surface/server/dataFunctions/data_series.js
+++ b/apps/surface/server/dataFunctions/data_series.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSeries = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,54 +24,85 @@ dataSeries = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
+
let queryTableClause = "";
const regionType = curve["region-type"];
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[regionType][variableStr];
+
let validTimeClause = "";
let forecastLength = curve["forecast-length"];
let forecastLengthClause = "";
- var timeVar;
- var dateClause;
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+
+ const averageStr = curve.average;
+ const averageOptionsMap = matsCollections.average.findOne(
+ { name: "average" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const average = averageOptionsMap[averageStr][0];
+
+ let timeVar;
+ let dateClause;
let siteDateClause = "";
let siteMatchClause = "";
let sitesClause = "";
- var NAggregate;
- var NClause;
- var queryPool;
+ let NAggregate;
+ let NClause;
+ let queryPool;
+
if (regionType === "Predefined region") {
timeVar = "m0.valid_day+3600*m0.hour";
- var metarStringStr = curve.truth;
+ forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
+ dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
+ NAggregate = "sum";
+ [, NClause] = variable;
+
+ const metarStringStr = curve.truth;
const metarString = Object.keys(
matsCollections.truth.findOne({ name: "truth" }).valuesMap
).find(
@@ -78,8 +110,9 @@ dataSeries = function (plotParams, plotFunction) {
matsCollections.truth.findOne({ name: "truth" }).valuesMap[key] ===
metarStringStr
);
- var regionStr = curve.region;
- var region = Object.keys(
+
+ const regionStr = curve.region;
+ const region = Object.keys(
matsCollections.region.findOne({ name: "region" }).valuesMap
).find(
(key) =>
@@ -87,14 +120,16 @@ dataSeries = function (plotParams, plotFunction) {
regionStr
);
queryTableClause = `from ${model}_${metarString}_${region} as m0`;
- forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
- NAggregate = "sum";
- NClause = variable[1];
- queryPool = sumPool;
+ queryPool = sumPool; // eslint-disable-line no-undef
} else {
timeVar = "m0.time";
- var modelTable;
+ dateClause = `and m0.time >= ${fromSecs} - 900 and m0.time <= ${toSecs} + 900`;
+ siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
+ siteMatchClause = "and m0.sta_id = o.sta_id and m0.time = o.time";
+ NAggregate = "count";
+ NClause = "1";
+
+ let modelTable;
if (forecastLength === 1) {
modelTable = `${model}qp1f`;
forecastLengthClause = "";
@@ -111,105 +146,86 @@ dataSeries = function (plotParams, plotFunction) {
{ optionsMap: 1 }
).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- var thisSite;
- var thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.sta_id in('${querySites.join("','")}')`;
} else {
throw new Error(
"INFO: Please add sites in order to get a single/multi station plot."
);
}
- dateClause = `and m0.time >= ${fromSecs} - 900 and m0.time <= ${toSecs} + 900`;
- siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
- siteMatchClause = "and m0.sta_id = o.sta_id and m0.time = o.time";
- NAggregate = "count";
- NClause = "1";
- queryPool = sitePool;
+ queryPool = sitePool; // eslint-disable-line no-undef
}
+
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and floor((${timeVar}+1800)%(24*3600)/3600) IN(${validTimes})`; // adjust by 1800 seconds to center obs at the top of the hour
}
- const averageStr = curve.average;
- const averageOptionsMap = matsCollections.average.findOne(
- { name: "average" },
- { optionsMap: 1 }
- ).optionsMap;
- const average = averageOptionsMap[averageStr][0];
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
+
const statisticClause =
`sum(${variable[0]}) as square_diff_sum, ${NAggregate}(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
`group_concat(${timeVar}, ';', ${variable[0]}, ';', ${NClause}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by ${timeVar}) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
+
+ // axisKey is used to determine which axis a curve should use.
+ // This axisKeySet object is used like a set and if a curve has the same
+ // units (axisKey) it will use the same axis.
+ // The axis number is assigned to the axisKeySet value, which is the axisKey.
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
+ statType = statisticOptionsMap[statisticSelect];
const varUnits = statVarUnitMap[statisticSelect][variableStr];
- // axisKey is used to determine which axis a curve should use.
- // This axisKeySet object is used like a set and if a curve has the same
- // units (axisKey) it will use the same axis.
- // The axis number is assigned to the axisKeySet value, which is the axisKey.
const axisKey = varUnits;
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select {{average}} as avtime, " +
- "count(distinct ceil(3600*floor(({{timeVar}}+1800)/3600))) as N_times, " +
- "min(ceil(3600*floor(({{timeVar}}+1800)/3600))) as min_secs, " +
- "max(ceil(3600*floor(({{timeVar}}+1800)/3600))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{average}}", average);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- statement = statement.split("{{timeVar}}").join(timeVar);
- dataRequests[label] = statement;
-
- // math is done on forecastLength later on -- set all analyses to 0
- if (forecastLength === "-99") {
- forecastLength = "0";
- }
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select {{average}} as avtime, " +
+ "count(distinct ceil(3600*floor(({{timeVar}}+1800)/3600))) as N_times, " +
+ "min(ceil(3600*floor(({{timeVar}}+1800)/3600))) as min_secs, " +
+ "max(ceil(3600*floor(({{timeVar}}+1800)/3600))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{average}}", average);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ statement = statement.split("{{timeVar}}").join(timeVar);
+ dataRequests[label] = statement;
+
+ // math is done on forecastLength later on -- set all analyses to 0
+ if (forecastLength === "-99") {
+ forecastLength = "0";
+ }
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBTimeSeries(
- queryPool,
+ queryPool, // eslint-disable-line no-undef
statement,
model,
forecastLength,
@@ -221,7 +237,9 @@ dataSeries = function (plotParams, plotFunction) {
appParams,
false
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -237,6 +255,7 @@ dataSeries = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -246,7 +265,7 @@ dataSeries = function (plotParams, plotFunction) {
error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
if (error.includes("Unknown column")) {
throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for the model/region [${model} and ${region}].`
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for this model and region].`
);
} else {
throw new Error(error);
@@ -257,7 +276,6 @@ dataSeries = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -282,6 +300,7 @@ dataSeries = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/surface/server/dataFunctions/data_simple_scatter.js b/apps/surface/server/dataFunctions/data_simple_scatter.js
index bba6d2e206..34a7d37525 100644
--- a/apps/surface/server/dataFunctions/data_simple_scatter.js
+++ b/apps/surface/server/dataFunctions/data_simple_scatter.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSimpleScatter = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,14 +23,15 @@ dataSimpleScatter = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
+
const axisXMap = Object.create(null);
const axisYMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
@@ -37,35 +39,29 @@ dataSimpleScatter = function (plotParams, plotFunction) {
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statType;
+ let varUnitsX;
+ let varUnitsY;
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const binParam = curve["bin-parameter"];
const binClause = matsCollections["bin-parameter"].findOne({
name: "bin-parameter",
}).optionsMap[binParam];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var metarStringStr = curve.truth;
- const metarString = Object.keys(
- matsCollections.truth.findOne({ name: "truth" }).valuesMap
- ).find(
- (key) =>
- matsCollections.truth.findOne({ name: "truth" }).valuesMap[key] ===
- metarStringStr
- );
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- const queryTableClause = `from ${model}_${metarString}_${region} as m0`;
- // scatterplots are only for predefined regions--no station plots
+
const regionType = "Predefined region";
+
const variableXStr = curve["x-variable"];
const variableYStr = curve["y-variable"];
const variableOptionsMap = matsCollections.variable.findOne(
@@ -74,19 +70,25 @@ dataSimpleScatter = function (plotParams, plotFunction) {
).optionsMap;
const variableX = variableOptionsMap[regionType][variableXStr];
const variableY = variableOptionsMap[regionType][variableYStr];
+
+ const metarStringStr = curve.truth;
+ const metarString = Object.keys(
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.truth.findOne({ name: "truth" }).valuesMap[key] ===
+ metarStringStr
+ );
+
let validTimeClause = "";
- let forecastLengthClause = "";
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let dateString = "";
- let dateClause = "";
if (binParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and m0.hour IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (binParam !== "Fcst lead time") {
const forecastLength = curve["forecast-length"];
if (forecastLength === undefined) {
@@ -96,12 +98,7 @@ dataSimpleScatter = function (plotParams, plotFunction) {
}
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
- if (binParam === "Init Date" && binParam !== "Valid Date") {
- dateString = "m0.valid_day+3600*m0.hour-m0.fcst_len*3600";
- } else {
- dateString = "m0.valid_day+3600*m0.hour";
- }
- dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
+
const statisticXSelect = curve["x-statistic"];
const statisticYSelect = curve["y-statistic"];
const statisticOptionsMap = matsCollections.statistic.findOne(
@@ -112,55 +109,78 @@ dataSimpleScatter = function (plotParams, plotFunction) {
`sum(${variableX[0]}) as square_diff_sumX, sum(${variableX[1]}) as N_sumX, sum(${variableX[2]}) as obs_model_diff_sumX, sum(${variableX[3]}) as model_sumX, sum(${variableX[4]}) as obs_sumX, sum(${variableX[5]}) as abs_sumX, ` +
`sum(${variableY[0]}) as square_diff_sumY, sum(${variableY[1]}) as N_sumY, sum(${variableY[2]}) as obs_model_diff_sumY, sum(${variableY[3]}) as model_sumY, sum(${variableY[4]}) as obs_sumY, sum(${variableY[5]}) as abs_sumY, ` +
`group_concat(m0.valid_day+3600*m0.hour, ';', ${variableX[0]}, ';', ${variableX[1]}, ';', ${variableX[2]}, ';', ${variableX[3]}, ';', ${variableX[4]}, ';', ${variableX[5]}, ';', ${variableY[0]}, ';', ${variableY[1]}, ';', ${variableY[2]}, ';', ${variableY[3]}, ';', ${variableY[4]}, ';', ${variableY[5]} order by m0.valid_day+3600*m0.hour) as sub_data, count(${variableX[0]}) as N0`;
- var statType = statisticOptionsMap[statisticXSelect];
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ let dateString = "";
+ let dateClause = "";
+ if (binParam === "Init Date" && binParam !== "Valid Date") {
+ dateString = "m0.valid_day+3600*m0.hour-m0.fcst_len*3600";
+ } else {
+ dateString = "m0.valid_day+3600*m0.hour";
+ }
+ dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+
+ const queryTableClause = `from ${model}_${metarString}_${region} as m0`;
+
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
- const varUnitsX = statVarUnitMap[statisticXSelect][variableXStr];
- const varUnitsY = statVarUnitMap[statisticYSelect][variableYStr];
+ statType = statisticOptionsMap[statisticXSelect];
+ varUnitsX = statVarUnitMap[statisticXSelect][variableXStr];
+ varUnitsY = statVarUnitMap[statisticYSelect][variableYStr];
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{binClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "group by binVal " +
- "order by binVal" +
- ";";
-
- statement = statement.replace("{{binClause}}", binClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "{{binClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by binVal " +
+ "order by binVal" +
+ ";";
+
+ statement = statement.replace("{{binClause}}", binClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSimpleScatter(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
`${statisticXSelect}_${variableXStr}`,
`${statisticYSelect}_${variableYStr}`
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -176,6 +196,7 @@ dataSimpleScatter = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -185,7 +206,7 @@ dataSimpleScatter = function (plotParams, plotFunction) {
error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
if (error.includes("Unknown column")) {
throw new Error(
- `INFO: The statistic/variable combination [${statisticXSelect}/${variableXStr} and ${statisticYSelect}/${variableYStr}] is not supported by the database for the model/region [${model} and ${region}].`
+ `INFO: The statistic/variable combination [${statisticXSelect}/${variableXStr} and ${statisticYSelect}/${variableYStr}] is not supported by the database for this model and region].`
);
} else {
throw new Error(error);
@@ -196,7 +217,6 @@ dataSimpleScatter = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -204,7 +224,7 @@ dataSimpleScatter = function (plotParams, plotFunction) {
ymax = ymax > d.ymax ? ymax : d.ymax;
}
} else {
- // this is a difference curve -- not supported for ROC plots
+ // this is a difference curve -- not supported for scatter plots
throw new Error(
"INFO: Difference curves are not supported for performance diagrams, as they do not feature consistent x or y values across all curves."
);
@@ -212,6 +232,7 @@ dataSimpleScatter = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/surface/server/dataFunctions/data_simple_scatter_scratch.js b/apps/surface/server/dataFunctions/data_simple_scatter_scratch.js
deleted file mode 100644
index f83318468d..0000000000
--- a/apps/surface/server/dataFunctions/data_simple_scatter_scratch.js
+++ /dev/null
@@ -1,282 +0,0 @@
-// /*
-// * Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
-// */
-//
-// import {matsCollections} from 'meteor/randyp:mats-common';
-// import {matsTypes} from 'meteor/randyp:mats-common';
-// import {matsDataUtils} from 'meteor/randyp:mats-common';
-// import {matsDataQueryUtils} from 'meteor/randyp:mats-common';
-// import {matsDataCurveOpsUtils} from 'meteor/randyp:mats-common';
-// import {matsDataProcessUtils} from 'meteor/randyp:mats-common';
-// import {moment} from 'meteor/momentjs:moment';
-//
-// dataSimpleScatter = function (plotParams, plotFunction) {
-// // initialize variables common to all curves
-// const appParams = {
-// "plotType": matsTypes.PlotTypes.simpleScatter,
-// "matching": plotParams['plotAction'] === matsTypes.PlotActions.matched,
-// "completeness": plotParams['completeness'],
-// "outliers": plotParams['outliers'],
-// "hideGaps": plotParams['noGapsCheck'],
-// "hasLevels": false
-// };
-// var dataRequests = {}; // used to store data queries
-// var dataFoundForCurve = true;
-// var dataFoundForAnyCurve = false;
-// var totalProcessingStart = moment();
-// var error = "";
-// var curves = JSON.parse(JSON.stringify(plotParams.curves));
-// var curvesLength = curves.length;
-// var dataset = [];
-// var axisXMap = Object.create(null);
-// var axisYMap = Object.create(null);
-// var xmax = -1 * Number.MAX_VALUE;
-// var ymax = -1 * Number.MAX_VALUE;
-// var xmin = Number.MAX_VALUE;
-// var ymin = Number.MAX_VALUE;
-//
-// for (var curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
-// // initialize variables specific to each curve
-// var curve = curves[curveIndex];
-// var diffFrom = curve.diffFrom;
-// var label = curve['label'];
-// var regionType = curve['region-type'];
-// var binParam = curve['bin-parameter'];
-// var binClause = matsCollections['bin-parameter'].findOne({name: 'bin-parameter'}).optionsMap[regionType][binParam];
-// var model = matsCollections['data-source'].findOne({name: 'data-source'}).optionsMap[curve['data-source']][0];
-// var queryTableClause = "";
-// var variableXStr = curve['x-variable'];
-// var variableYStr = curve['y-variable'];
-// var variableOptionsMap = matsCollections['variable'].findOne({name: 'variable'}, {optionsMap: 1})['optionsMap'];
-// var variableX = variableOptionsMap[regionType][variableXStr];
-// var variableY = variableOptionsMap[regionType][variableYStr];
-// var validTimeClause = "";
-// var forecastLength = curve['forecast-length'];
-// var forecastLengthClause = "";
-// var dateRange = matsDataUtils.getDateRange(curve['curve-dates']);
-// var fromSecs = dateRange.fromSeconds;
-// var toSecs = dateRange.toSeconds;
-// var timeVar;
-// var dateString = "";
-// var dateClause = "";
-// var siteDateClause = "";
-// var siteMatchClause = "";
-// var sitesClause = "";
-// var NAggregate;
-// var NClauseX;
-// var NClauseY;
-// var queryPool;
-// if (regionType === 'Predefined region') {
-// timeVar = "m0.valid_day+3600*m0.hour";
-// var metarStringStr = curve['truth'];
-// var metarString = Object.keys(matsCollections['truth'].findOne({name: 'truth'}).valuesMap).find(key => matsCollections['truth'].findOne({name: 'truth'}).valuesMap[key] === metarStringStr);
-// var regionStr = curve['region'];
-// var region = Object.keys(matsCollections['region'].findOne({name: 'region'}).valuesMap).find(key => matsCollections['region'].findOne({name: 'region'}).valuesMap[key] === regionStr);
-// queryTableClause = "from " + model + "_" + metarString + "_" + region + " as m0";
-// if (binParam !== 'Fcst lead time') {
-// if (forecastLength === undefined) {
-// throw new Error("INFO: " + label + "'s forecast lead time is undefined. Please assign it a value.");
-// }
-// forecastLengthClause = "and m0.fcst_len = " + forecastLength;
-// }
-// if ((binParam === 'Init Date') && (binParam !== 'Valid Date')) {
-// dateString = "m0.valid_day+3600*m0.hour-m0.fcst_len*3600";
-// } else {
-// dateString = "m0.valid_day+3600*m0.hour";
-// }
-// dateClause = "and " + dateString + " >= " + fromSecs + " and " + dateString + " <= " + toSecs;
-// NAggregate = 'sum';
-// NClauseX = variableX[1];
-// NClauseY = variableY[1];
-// queryPool = sumPool;
-// } else {
-// timeVar = "m0.time";
-// var modelTable;
-// if (binParam !== 'Fcst lead time') {
-// if (forecastLength === undefined) {
-// throw new Error("INFO: " + label + "'s forecast lead time is undefined. Please assign it a value.");
-// }
-// if (forecastLength === 1) {
-// modelTable = model + "qp1f";
-// forecastLengthClause = "";
-// } else {
-// modelTable = (model.includes('ret_') || model.includes('Ret_')) ? model + "p" : model + "qp";
-// forecastLengthClause = "and m0.fcst_len = " + forecastLength + " "
-// }
-// } else {
-// modelTable = (model.includes('ret_') || model.includes('Ret_')) ? model + "p" : model + "qp";
-// }
-// var obsTable = (model.includes('ret_') || model.includes('Ret_')) ? 'obs_retro' : 'obs';
-// queryTableClause = "from " + obsTable + " as o, " + modelTable + " as m0 ";
-// var siteMap = matsCollections.StationMap.findOne({name: 'stations'}, {optionsMap: 1})['optionsMap'];
-// var sitesList = curve['sites'] === undefined ? [] : curve['sites'];
-// var querySites = [];
-// if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
-// var thisSite;
-// var thisSiteObj;
-// for (var sidx = 0; sidx < sitesList.length; sidx++) {
-// thisSite = sitesList[sidx];
-// thisSiteObj = siteMap.find(obj => {
-// return obj.origName === thisSite;
-// });
-// querySites.push(thisSiteObj.options.id);
-// }
-// sitesClause = " and m0.sta_id in('" + querySites.join("','") + "')";
-// } else {
-// throw new Error("INFO: Please add sites in order to get a single/multi station plot.");
-// }
-// if ((binParam === 'Init Date') && (binParam !== 'Valid Date')) {
-// dateString = "m0.time-m0.fcst_len*3600";
-// } else {
-// dateString = "m0.time";
-// }
-// dateClause = "and " + dateString + " >= " + fromSecs + " - 900 and " + dateString + " <= " + toSecs + " + 900";
-// siteDateClause = "and o.time >= " + fromSecs + " - 900 and o.time <= " + toSecs + " + 900";
-// siteMatchClause = "and m0.sta_id = o.sta_id and m0.time = o.time";
-// NAggregate = 'count';
-// NClauseX = '1';
-// NClauseY = '1';
-// queryPool = sitePool;
-// }
-// if (binParam !== 'Valid UTC hour') {
-// var validTimes = curve['valid-time'] === undefined ? [] : curve['valid-time'];
-// if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
-// validTimeClause = "and floor((" + timeVar + "+1800)%(24*3600)/3600) IN(" + validTimes + ")"; // adjust by 1800 seconds to center obs at the top of the hour
-// }
-// }
-// var statisticXSelect = curve['x-statistic'];
-// var statisticYSelect = curve['y-statistic'];
-// var statisticOptionsMap = matsCollections['statistic'].findOne({name: 'statistic'}, {optionsMap: 1})['optionsMap'];
-// var statisticClause = "sum(" + variableX[0] + ") as square_diff_sumX, " + NAggregate + "(" + variableX[1] + ") as N_sumX, sum(" + variableX[2] + ") as obs_model_diff_sumX, sum(" + variableX[3] + ") as model_sumX, sum(" + variableX[4] + ") as obs_sumX, sum(" + variableX[5] + ") as abs_sumX, " +
-// "sum(" + variableY[0] + ") as square_diff_sumY, " + NAggregate + "(" + variableY[1] + ") as N_sumY, sum(" + variableY[2] + ") as obs_model_diff_sumY, sum(" + variableY[3] + ") as model_sumY, sum(" + variableY[4] + ") as obs_sumY, sum(" + variableY[5] + ") as abs_sumY, " +
-// "group_concat(" + timeVar + ", ';', " + variableX[0] + ", ';', " + NClauseX + ", ';', " + variableX[2] + ", ';', " + variableX[3] + ", ';', " + variableX[4] + ", ';', " + variableX[5] + ", ';', " +
-// variableY[0] + ", ';', " + NClauseY + ", ';', " + variableY[2] + ", ';', " + variableY[3] + ", ';', " + variableY[4] + ", ';', " + variableY[5] + " order by " + timeVar + ") as sub_data, count(" + variableX[0] + ") as N0";
-// var statType = statisticOptionsMap[statisticXSelect];
-// var statVarUnitMap = matsCollections['variable'].findOne({name: 'variable'}, {statVarUnitMap: 1})['statVarUnitMap'];
-// var varUnitsX = statVarUnitMap[statisticXSelect][variableXStr];
-// var varUnitsY = statVarUnitMap[statisticYSelect][variableYStr];
-//
-// var d;
-// if (!diffFrom) {
-// // this is a database driven curve, not a difference curve
-// // prepare the query from the above parameters
-// var statement = "{{binClause}} " +
-// "count(distinct ceil(3600*floor(({{timeVar}}+1800)/3600))) as N_times, " +
-// "min(ceil(3600*floor(({{timeVar}}+1800)/3600))) as min_secs, " +
-// "max(ceil(3600*floor(({{timeVar}}+1800)/3600))) as max_secs, " +
-// "{{statisticClause}} " +
-// "{{queryTableClause}} " +
-// "where 1=1 " +
-// "{{siteMatchClause}} " +
-// "{{sitesClause}} " +
-// "{{dateClause}} " +
-// "{{siteDateClause}} " +
-// "{{validTimeClause}} " +
-// "{{forecastLengthClause}} " +
-// "group by binVal " +
-// "order by binVal" +
-// ";";
-//
-// statement = statement.replace('{{binClause}}', binClause);
-// statement = statement.replace('{{statisticClause}}', statisticClause);
-// statement = statement.replace('{{queryTableClause}}', queryTableClause);
-// statement = statement.replace('{{siteMatchClause}}', siteMatchClause);
-// statement = statement.replace('{{sitesClause}}', sitesClause);
-// statement = statement.replace('{{validTimeClause}}', validTimeClause);
-// statement = statement.replace('{{forecastLengthClause}}', forecastLengthClause);
-// statement = statement.replace('{{dateClause}}', dateClause);
-// statement = statement.replace('{{siteDateClause}}', siteDateClause);
-// statement = statement.split('{{timeVar}}').join(timeVar);
-// dataRequests[label] = statement;
-//
-// var queryResult;
-// var startMoment = moment();
-// var finishMoment;
-// try {
-// // send the query statement to the query function
-// queryResult = matsDataQueryUtils.queryDBSimpleScatter(queryPool, statement, appParams, statisticXSelect + "_" + variableXStr, statisticYSelect + "_" + variableYStr);
-// finishMoment = moment();
-// dataRequests["data retrieval (query) time - " + label] = {
-// begin: startMoment.format(),
-// finish: finishMoment.format(),
-// duration: moment.duration(finishMoment.diff(startMoment)).asSeconds() + " seconds",
-// recordCount: queryResult.data.x.length
-// };
-// // get the data back from the query
-// d = queryResult.data;
-// } catch (e) {
-// // this is an error produced by a bug in the query function, not an error returned by the mysql database
-// e.message = "Error in queryDB: " + e.message + " for statement: " + statement;
-// throw new Error(e.message);
-// }
-// if (queryResult.error !== undefined && queryResult.error !== "") {
-// if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
-// // this is NOT an error just a no data condition
-// dataFoundForCurve = false;
-// } else {
-// // this is an error returned by the mysql database
-// error += "Error from verification query:
" + queryResult.error + "
query:
" + statement + "
";
-// if (error.includes('Unknown column')) {
-// throw new Error("INFO: The statistic/variable combination [" + statisticXSelect + "/" + variableXStr + " and " + statisticYSelect + "/" + variableYStr + "] is not supported by the database for the model/region [" + model + " and " + region + "].");
-// } else {
-// throw new Error(error);
-// }
-// }
-// } else {
-// dataFoundForAnyCurve = true;
-// }
-//
-// // set axis limits based on returned data
-// var postQueryStartMoment = moment();
-// if (dataFoundForCurve) {
-// xmin = xmin < d.xmin ? xmin : d.xmin;
-// xmax = xmax > d.xmax ? xmax : d.xmax;
-// ymin = ymin < d.ymin ? ymin : d.ymin;
-// ymax = ymax > d.ymax ? ymax : d.ymax;
-// }
-// } else {
-// // this is a difference curve -- not supported for ROC plots
-// throw new Error("INFO: Difference curves are not supported for performance diagrams, as they do not feature consistent x or y values across all curves.");
-// }
-//
-// // set curve annotation to be the curve mean -- may be recalculated later
-// // also pass previously calculated axis stats to curve options
-// const mean = d.sum / d.x.length;
-// const annotation = mean === undefined ? label + "- mean = NoData" : label + "- mean = " + mean.toPrecision(4);
-// curve['annotation'] = annotation;
-// curve['xmin'] = d.xmin;
-// curve['xmax'] = d.xmax;
-// curve['ymin'] = d.ymin;
-// curve['ymax'] = d.ymax;
-// curve['axisXKey'] = varUnitsX;
-// curve['axisYKey'] = varUnitsY;
-// curve['binParam'] = binParam;
-// const cOptions = matsDataCurveOpsUtils.generateScatterCurveOptions(curve, curveIndex, axisXMap, axisYMap, d, appParams); // generate plot with data, curve annotation, axis labels, etc.
-// dataset.push(cOptions);
-// var postQueryFinishMoment = moment();
-// dataRequests["post data retrieval (query) process time - " + label] = {
-// begin: postQueryStartMoment.format(),
-// finish: postQueryFinishMoment.format(),
-// duration: moment.duration(postQueryFinishMoment.diff(postQueryStartMoment)).asSeconds() + ' seconds'
-// };
-// } // end for curves
-//
-// if (!dataFoundForAnyCurve) {
-// // we found no data for any curves so don't bother proceeding
-// throw new Error("INFO: No valid data for any curves.");
-// }
-//
-// // process the data returned by the query
-// const curveInfoParams = {
-// "curves": curves,
-// "curvesLength": curvesLength,
-// "statType": statType,
-// "axisXMap": axisXMap,
-// "axisYMap": axisYMap,
-// "xmax": xmax,
-// "xmin": xmin
-// };
-// const bookkeepingParams = {"dataRequests": dataRequests, "totalProcessingStart": totalProcessingStart};
-// var result = matsDataProcessUtils.processDataSimpleScatter(dataset, appParams, curveInfoParams, plotParams, bookkeepingParams);
-// plotFunction(result);
-// };
diff --git a/apps/surface/server/dataFunctions/data_validtime.js b/apps/surface/server/dataFunctions/data_validtime.js
index 6016b1fbd5..a08ae0d493 100644
--- a/apps/surface/server/dataFunctions/data_validtime.js
+++ b/apps/surface/server/dataFunctions/data_validtime.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataValidTime = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,55 +24,80 @@ dataValidTime = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
+
let queryTableClause = "";
const regionType = curve["region-type"];
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[regionType][variableStr];
- var validTimeVar;
+
+ let validTimeVar;
+
const forecastLength = curve["forecast-length"];
let forecastLengthClause = "";
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+
const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
- var timeVar;
- var dateClause;
+
+ let timeVar;
+ let dateClause;
let siteDateClause = "";
let siteMatchClause = "";
let sitesClause = "";
- var NAggregate;
- var NClause;
- var queryPool;
+ let NAggregate;
+ let NClause;
+ let queryPool;
+
if (regionType === "Predefined region") {
timeVar = "m0.valid_day+3600*m0.hour";
validTimeVar = "m0.hour";
- var metarStringStr = curve.truth;
+ forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
+ dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
+ NAggregate = "sum";
+ [, NClause] = variable;
+
+ const metarStringStr = curve.truth;
const metarString = Object.keys(
matsCollections.truth.findOne({ name: "truth" }).valuesMap
).find(
@@ -79,8 +105,9 @@ dataValidTime = function (plotParams, plotFunction) {
matsCollections.truth.findOne({ name: "truth" }).valuesMap[key] ===
metarStringStr
);
- var regionStr = curve.region;
- var region = Object.keys(
+
+ const regionStr = curve.region;
+ const region = Object.keys(
matsCollections.region.findOne({ name: "region" }).valuesMap
).find(
(key) =>
@@ -88,15 +115,17 @@ dataValidTime = function (plotParams, plotFunction) {
regionStr
);
queryTableClause = `from ${model}_${metarString}_${region} as m0`;
- forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- dateClause = `and m0.valid_day+3600*m0.hour >= ${fromSecs} and m0.valid_day+3600*m0.hour <= ${toSecs}`;
- NAggregate = "sum";
- NClause = variable[1];
- queryPool = sumPool;
+ queryPool = sumPool; // eslint-disable-line no-undef
} else {
timeVar = "m0.time";
validTimeVar = `floor((${timeVar}+1800)%(24*3600)/3600)`; // adjust by 1800 seconds to center obs at the top of the hour
- var modelTable;
+ dateClause = `and m0.time >= ${fromSecs} - 900 and m0.time <= ${toSecs} + 900`;
+ siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
+ siteMatchClause = "and m0.sta_id = o.sta_id and m0.time = o.time";
+ NAggregate = "count";
+ NClause = "1";
+
+ let modelTable;
if (forecastLength === 1) {
modelTable = `${model}qp1f`;
forecastLengthClause = "";
@@ -113,93 +142,81 @@ dataValidTime = function (plotParams, plotFunction) {
{ optionsMap: 1 }
).optionsMap;
const sitesList = curve.sites === undefined ? [] : curve.sites;
- const querySites = [];
+ let querySites = [];
if (sitesList.length > 0 && sitesList !== matsTypes.InputTypes.unused) {
- var thisSite;
- var thisSiteObj;
- for (let sidx = 0; sidx < sitesList.length; sidx++) {
- thisSite = sitesList[sidx];
- thisSiteObj = siteMap.find((obj) => obj.origName === thisSite);
- querySites.push(thisSiteObj.options.id);
- }
+ querySites = sitesList.map(function (site) {
+ return siteMap.find((obj) => obj.origName === site).options.id;
+ });
sitesClause = ` and m0.sta_id in('${querySites.join("','")}')`;
} else {
throw new Error(
"INFO: Please add sites in order to get a single/multi station plot."
);
}
- dateClause = `and m0.time >= ${fromSecs} - 900 and m0.time <= ${toSecs} + 900`;
- siteDateClause = `and o.time >= ${fromSecs} - 900 and o.time <= ${toSecs} + 900`;
- siteMatchClause = "and m0.sta_id = o.sta_id and m0.time = o.time";
- NAggregate = "count";
- NClause = "1";
- queryPool = sitePool;
+ queryPool = sitePool; // eslint-disable-line no-undef
}
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
+
const statisticClause =
`sum(${variable[0]}) as square_diff_sum, ${NAggregate}(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
`group_concat(${timeVar}, ';', ${variable[0]}, ';', ${NClause}, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by ${timeVar}) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
+
+ // axisKey is used to determine which axis a curve should use.
+ // This axisKeySet object is used like a set and if a curve has the same
+ // units (axisKey) it will use the same axis.
+ // The axis number is assigned to the axisKeySet value, which is the axisKey.
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
+ statType = statisticOptionsMap[statisticSelect];
const varUnits = statVarUnitMap[statisticSelect][variableStr];
- // axisKey is used to determine which axis a curve should use.
- // This axisKeySet object is used like a set and if a curve has the same
- // units (axisKey) it will use the same axis.
- // The axis number is assigned to the axisKeySet value, which is the axisKey.
const axisKey = varUnits;
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select {{validTimeVar}} as hr_of_day, " +
- "count(distinct ceil(3600*floor(({{timeVar}}+1800)/3600))) as N_times, " +
- "min(ceil(3600*floor(({{timeVar}}+1800)/3600))) as min_secs, " +
- "max(ceil(3600*floor(({{timeVar}}+1800)/3600))) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{siteMatchClause}} " +
- "{{sitesClause}} " +
- "{{dateClause}} " +
- "{{siteDateClause}} " +
- "{{forecastLengthClause}} " +
- "group by hr_of_day " +
- "order by hr_of_day" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
- statement = statement.replace("{{sitesClause}}", sitesClause);
- statement = statement.replace("{{validTimeVar}}", validTimeVar);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.replace("{{siteDateClause}}", siteDateClause);
- statement = statement.split("{{timeVar}}").join(timeVar);
- dataRequests[label] = statement;
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select {{validTimeVar}} as hr_of_day, " +
+ "count(distinct ceil(3600*floor(({{timeVar}}+1800)/3600))) as N_times, " +
+ "min(ceil(3600*floor(({{timeVar}}+1800)/3600))) as min_secs, " +
+ "max(ceil(3600*floor(({{timeVar}}+1800)/3600))) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{siteMatchClause}} " +
+ "{{sitesClause}} " +
+ "{{dateClause}} " +
+ "{{siteDateClause}} " +
+ "{{forecastLengthClause}} " +
+ "group by hr_of_day " +
+ "order by hr_of_day" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{siteMatchClause}}", siteMatchClause);
+ statement = statement.replace("{{sitesClause}}", sitesClause);
+ statement = statement.replace("{{validTimeVar}}", validTimeVar);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.replace("{{siteDateClause}}", siteDateClause);
+ statement = statement.split("{{timeVar}}").join(timeVar);
+ dataRequests[label] = statement;
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- queryPool,
+ queryPool, // eslint-disable-line no-undef
statement,
appParams,
`${statisticSelect}_${variableStr}`
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -215,6 +232,7 @@ dataValidTime = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -224,7 +242,7 @@ dataValidTime = function (plotParams, plotFunction) {
error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
if (error.includes("Unknown column")) {
throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for the model/region [${model} and ${region}].`
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is not supported by the database for this model and region].`
);
} else {
throw new Error(error);
@@ -235,7 +253,6 @@ dataValidTime = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -260,6 +277,7 @@ dataValidTime = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/surface/server/main.js b/apps/surface/server/main.js
index ab05927b1f..1655857e5e 100644
--- a/apps/surface/server/main.js
+++ b/apps/surface/server/main.js
@@ -4,7 +4,9 @@
import { Meteor } from "meteor/meteor";
import { mysql } from "meteor/pcel:mysql";
+import { moment } from "meteor/momentjs:moment";
import {
+ matsMethods,
matsTypes,
matsCollections,
matsDataUtils,
@@ -319,140 +321,132 @@ const doCurveParams = function () {
const params = matsCollections.CurveParamsInfo.find({
curve_params: { $exists: true },
}).fetch()[0].curve_params;
- for (let cp = 0; cp < params.length; cp++) {
+ for (let cp = 0; cp < params.length; cp += 1) {
matsCollections[params[cp]].remove({});
}
}
+
const modelOptionsMap = {};
const forecastLengthOptionsMap = {};
const regionModelOptionsMap = {};
const siteOptionsMap = {};
const sitesLocationMap = [];
- const masterRegionValuesMap = {};
- const masterMETARValuesMap = {};
+ const allRegionValuesMap = {};
+ const allMETARValuesMap = {};
let modelDateRangeMap = {};
const metarModelOptionsMap = {};
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- metadataPool,
+ metadataPool, // eslint-disable-line no-undef
"select short_name,description from region_descriptions;"
);
- let masterRegDescription;
- let masterShortName;
- for (var j = 0; j < rows.length; j++) {
- masterRegDescription = rows[j].description.trim();
- masterShortName = rows[j].short_name.trim();
- masterRegionValuesMap[masterShortName] = masterRegDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allRegionValuesMap[rows[j].short_name.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select metar_string,description from metar_string_descriptions;"
);
- let masterMETARDescription;
- let masterMETARString;
- for (var j = 0; j < rows.length; j++) {
- masterMETARDescription = rows[j].description.trim();
- masterMETARString = rows[j].metar_string.trim();
- masterMETARValuesMap[masterMETARString] = masterMETARDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allMETARValuesMap[rows[j].metar_string.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select model,metar_string,regions,display_text,fcst_lens,mindate,maxdate from regions_per_model_mats_all_categories order by display_category, display_order;"
);
- for (var i = 0; i < rows.length; i++) {
- const model_value = rows[i].model.trim();
+ for (let i = 0; i < rows.length; i += 1) {
+ const modelValue = rows[i].model.trim();
const model = rows[i].display_text.trim();
- modelOptionsMap[model] = [model_value];
+ modelOptionsMap[model] = [modelValue];
const rowMinDate = moment.utc(rows[i].mindate * 1000).format("MM/DD/YYYY HH:mm");
const rowMaxDate = moment.utc(rows[i].maxdate * 1000).format("MM/DD/YYYY HH:mm");
- modelDateRangeMap[model] = { minDate: rowMinDate, maxDate: rowMaxDate };
+ modelDateRangeMap[model] = {
+ minDate: rowMinDate,
+ maxDate: rowMaxDate,
+ };
- const metarStrings = rows[i].metar_string;
- const metarStringsArr = metarStrings
+ const metars = rows[i].metar_string;
+ metarModelOptionsMap[model] = metars
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const metarArr = [];
- var dummyMETAR;
- for (var j = 0; j < metarStringsArr.length; j++) {
- dummyMETAR = metarStringsArr[j].replace(/'|\[|\]/g, "");
- metarArr.push(masterMETARValuesMap[dummyMETAR]);
- }
- metarModelOptionsMap[model] = metarArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (metar) {
+ return allMETARValuesMap[metar.replace(/'|\[|\]/g, "")];
+ });
const forecastLengths = rows[i].fcst_lens;
- const forecastLengthArr = forecastLengths
+ forecastLengthOptionsMap[model] = forecastLengths
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (var j = 0; j < forecastLengthArr.length; j++) {
- forecastLengthArr[j] = forecastLengthArr[j].replace(/'|\[|\]/g, "");
- }
- forecastLengthOptionsMap[model] = forecastLengthArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (fhr) {
+ return fhr.replace(/'|\[|\]/g, "");
+ });
const { regions } = rows[i];
- const regionsArrRaw = regions
+ regionModelOptionsMap[model] = regions
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const regionsArr = [];
- var dummyRegion;
- for (var j = 0; j < regionsArrRaw.length; j++) {
- dummyRegion = regionsArrRaw[j].replace(/'|\[|\]/g, "");
- regionsArr.push(masterRegionValuesMap[dummyRegion]);
- }
- regionModelOptionsMap[model] = regionsArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (region) {
+ return allRegionValuesMap[region.replace(/'|\[|\]/g, "")];
+ });
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
matsCollections.SiteMap.remove({});
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sitePool,
- "select madis_id,name,lat,lon,elev,description from metars_mats_global where lat > -16380 and lat < 16380 and lon > -32760 and lon < 32760 order by name;"
+ sumPool, // eslint-disable-line no-undef
+ "select madis_id,name,lat,lon,elev,description from madis3.metars_mats_global where lat > -16380 and lat < 16380 and lon > -32760 and lon < 32760 order by name;"
);
- for (var i = 0; i < rows.length; i++) {
- const site_name = rows[i].name;
- const site_description = rows[i].description;
- const site_id = rows[i].madis_id;
- const site_lat = rows[i].lat / 182;
- const site_lon = rows[i].lon / 182;
- const site_elev = rows[i].elev;
- siteOptionsMap[site_name] = [site_id];
-
- const point = [site_lat, site_lon];
- const obj = {
- name: site_name,
- origName: site_name,
- point,
- elevation: site_elev,
- options: {
- title: site_description,
- color: "red",
- size: 5,
- network: "METAR",
- peerOption: site_name,
- id: site_id,
- highLightColor: "blue",
- },
- };
- sitesLocationMap.push(obj);
-
- matsCollections.SiteMap.insert({ siteName: site_name, siteId: site_id });
+ for (let i = 0; i < rows.length; i += 1) {
+ const siteName = rows[i].name === undefined ? "unknown" : rows[i].name;
+ const siteDescription =
+ rows[i].description === undefined ? "unknown" : rows[i].description;
+ const siteId = rows[i].madis_id;
+ const siteLat = rows[i].lat === undefined ? -90 : rows[i].lat / 182;
+ const siteLon = rows[i].lon === undefined ? 0 : rows[i].lon / 182;
+ const siteElev = rows[i].elev === undefined ? 0 : rows[i].elev;
+
+ // There's one station right at the south pole that the map doesn't know how to render at all, so exclude it.
+ // Also exclude stations with missing data
+ if (siteLat < 90 && siteLat > -90) {
+ siteOptionsMap[siteName] = [siteId];
+
+ const point = [siteLat, siteLon];
+ const obj = {
+ name: siteName,
+ origName: siteName,
+ point,
+ elevation: siteElev,
+ options: {
+ title: siteDescription,
+ color: "red",
+ size: 5,
+ network: "METAR",
+ peerOption: siteName,
+ id: siteId,
+ highLightColor: "blue",
+ },
+ };
+ sitesLocationMap.push(obj);
+ matsCollections.SiteMap.insert({ siteName, siteId });
+ }
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
matsCollections.StationMap.remove({});
@@ -517,7 +511,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["data-source"].findOne({ name: "data-source" });
+ const currentParam = matsCollections["data-source"].findOne({
+ name: "data-source",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap) ||
!matsDataUtils.areObjectsEqual(currentParam.dates, modelDateRangeMap)
@@ -543,7 +539,7 @@ const doCurveParams = function () {
type: matsTypes.InputTypes.select,
optionsMap: regionModelOptionsMap,
options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]],
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
superiorNames: ["data-source"],
controlButtonCovered: true,
unique: false,
@@ -555,10 +551,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.region.findOne({ name: "region" });
+ const currentParam = matsCollections.region.findOne({ name: "region" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, regionModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterRegionValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allRegionValuesMap)
) {
// have to reload region data
matsCollections.region.update(
@@ -566,7 +562,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: regionModelOptionsMap,
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]],
default: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]][0],
},
@@ -575,7 +571,7 @@ const doCurveParams = function () {
}
}
- const optionsMap = {
+ const statOptionsMap = {
RMSE: "scalar",
"Bias (Model - Obs)": "scalar",
@@ -595,11 +591,11 @@ const doCurveParams = function () {
matsCollections.statistic.insert({
name: "statistic",
type: matsTypes.InputTypes.select,
- optionsMap,
- options: Object.keys(optionsMap),
+ optionsMap: statOptionsMap,
+ options: Object.keys(statOptionsMap),
controlButtonCovered: true,
unique: false,
- default: Object.keys(optionsMap)[0],
+ default: Object.keys(statOptionsMap)[0],
controlButtonVisibility: "block",
displayOrder: 2,
displayPriority: 1,
@@ -611,11 +607,11 @@ const doCurveParams = function () {
matsCollections["x-statistic"].insert({
name: "x-statistic",
type: matsTypes.InputTypes.select,
- optionsMap,
- options: Object.keys(optionsMap),
+ optionsMap: statOptionsMap,
+ options: Object.keys(statOptionsMap),
controlButtonCovered: true,
unique: false,
- default: Object.keys(optionsMap)[0],
+ default: Object.keys(statOptionsMap)[0],
controlButtonVisibility: "block",
displayOrder: 4,
displayPriority: 1,
@@ -627,11 +623,11 @@ const doCurveParams = function () {
matsCollections["y-statistic"].insert({
name: "y-statistic",
type: matsTypes.InputTypes.select,
- optionsMap,
- options: Object.keys(optionsMap),
+ optionsMap: statOptionsMap,
+ options: Object.keys(statOptionsMap),
controlButtonCovered: true,
unique: false,
- default: Object.keys(optionsMap)[0],
+ default: Object.keys(statOptionsMap)[0],
controlButtonVisibility: "block",
displayOrder: 4,
displayPriority: 1,
@@ -818,7 +814,7 @@ const doCurveParams = function () {
type: matsTypes.InputTypes.select,
optionsMap: metarModelOptionsMap,
options: metarModelOptionsMap[Object.keys(metarModelOptionsMap)[0]],
- valuesMap: masterMETARValuesMap,
+ valuesMap: allMETARValuesMap,
superiorNames: ["data-source"],
controlButtonCovered: true,
unique: false,
@@ -830,10 +826,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.truth.findOne({ name: "truth" });
+ const currentParam = matsCollections.truth.findOne({ name: "truth" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, metarModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterMETARValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allMETARValuesMap)
) {
// have to reload truth data
matsCollections.truth.update(
@@ -841,7 +837,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: metarModelOptionsMap,
- valuesMap: masterMETARValuesMap,
+ valuesMap: allMETARValuesMap,
options: metarModelOptionsMap[Object.keys(metarModelOptionsMap)[0]],
},
}
@@ -871,7 +867,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["forecast-length"].findOne({
+ const currentParam = matsCollections["forecast-length"].findOne({
name: "forecast-length",
});
if (
@@ -1188,7 +1184,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["curve-dates"].findOne({ name: "curve-dates" });
+ const currentParam = matsCollections["curve-dates"].findOne({
+ name: "curve-dates",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.startDate, minDate) ||
!matsDataUtils.areObjectsEqual(currentParam.stopDate, maxDate) ||
@@ -1558,7 +1556,8 @@ const doPlotGraph = function () {
Meteor.startup(function () {
matsCollections.Databases.remove({});
if (matsCollections.Databases.find({}).count() < 0) {
- console.log(
+ // eslint-disable-next-line no-console
+ console.warn(
"main startup: corrupted Databases collection: dropping Databases collection"
);
matsCollections.Databases.drop();
@@ -1575,7 +1574,7 @@ Meteor.startup(function () {
databases = Meteor.settings.private.databases;
}
if (databases !== null && databases !== undefined && Array.isArray(databases)) {
- for (let di = 0; di < databases.length; di++) {
+ for (let di = 0; di < databases.length; di += 1) {
matsCollections.Databases.insert(databases[di]);
}
}
@@ -1602,6 +1601,7 @@ Meteor.startup(function () {
);
if (cbConnection) {
// global cbScorecardSettingsPool
+ // eslint-disable-next-line no-undef
cbScorecardSettingsPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1628,6 +1628,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (metadataSettings) {
+ // eslint-disable-next-line no-undef
metadataPool = mysql.createPool(metadataSettings);
allPools.push({ pool: "metadataPool", role: matsTypes.DatabaseRoles.META_DATA });
}
@@ -1648,6 +1649,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (sumSettings) {
+ // eslint-disable-next-line no-undef
sumPool = mysql.createPool(sumSettings);
allPools.push({ pool: "sumPool", role: matsTypes.DatabaseRoles.SUMS_DATA });
}
@@ -1668,6 +1670,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (siteSettings) {
+ // eslint-disable-next-line no-undef
sitePool = mysql.createPool(siteSettings);
allPools.push({ pool: "sitePool", role: matsTypes.DatabaseRoles.SITE_DATA });
}
@@ -1684,7 +1687,7 @@ Meteor.startup(function () {
appType: matsTypes.AppTypes.mats,
});
} catch (error) {
- console.log(error.message);
+ throw new Error(error.message);
}
});
@@ -1692,6 +1695,7 @@ Meteor.startup(function () {
// These are application specific mongo data - like curve params
// The appSpecificResetRoutines object is a special name,
// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way.
+// eslint-disable-next-line no-undef
appSpecificResetRoutines = [
doPlotGraph,
doCurveParams,
diff --git a/apps/surfrad/.eslintrc.json b/apps/surfrad/.eslintrc.json
index b6823a8810..79d49c5bb6 100644
--- a/apps/surfrad/.eslintrc.json
+++ b/apps/surfrad/.eslintrc.json
@@ -28,22 +28,6 @@
"space-before-function-paren": "off",
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
- "prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
- "no-undef": "warn",
- "no-plusplus": "warn",
- "vars-on-top": "warn",
- "no-var": "warn",
- "block-scoped-var": "warn",
- "no-loop-func": "warn",
- "no-unused-vars": "warn",
- "no-param-reassign": "warn",
- "camelcase": "warn",
- "no-redeclare": "warn",
- "no-shadow": "warn"
+ "prefer-arrow-callback": "off"
}
}
diff --git a/apps/surfrad/client/main.js b/apps/surfrad/client/main.js
index a87407a1f4..ecd922b6a2 100644
--- a/apps/surfrad/client/main.js
+++ b/apps/surfrad/client/main.js
@@ -2,6 +2,7 @@
* Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved.
*/
+// eslint-disable-next-line no-unused-vars
import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common";
import "@fortawesome/fontawesome-free";
import "@fortawesome/fontawesome-free/css/all.css";
diff --git a/apps/surfrad/server/dataFunctions/data_contour.js b/apps/surfrad/server/dataFunctions/data_contour.js
index ab03418aa2..e8a5839d46 100644
--- a/apps/surfrad/server/dataFunctions/data_contour.js
+++ b/apps/surfrad/server/dataFunctions/data_contour.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContour = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,78 +23,95 @@ dataContour = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
- const totalProcessingStart = moment();
+
+ const curves = JSON.parse(JSON.stringify(plotParams.curves));
+ if (curves.length > 1) {
+ throw new Error("INFO: There must only be one added curve.");
+ }
+
+ const axisMap = Object.create(null);
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- const curves = JSON.parse(JSON.stringify(plotParams.curves));
- if (curves.length > 1) {
- throw new Error("INFO: There must only be one added curve.");
- }
- const dataset = [];
- const axisMap = Object.create(null);
- // initialize variables specific to the curve
+ // initialize variables specific to this curve
const curve = curves[0];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- const regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- let regionClause;
- if (region === "all_stat") {
- regionClause = "";
- } else if (region === "all_surf") {
- regionClause = "and m0.id in(1,2,3,4,5,6,7) ";
- } else if (region === "all_sol") {
- regionClause = "and m0.id in(8,9,10,11,12,13,14) ";
- } else {
- regionClause = `and m0.id in(${region}) `;
- }
- const scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const scaleClause = `and m0.scale = ${grid_scale}`;
- const queryTableClause = `from surfrad as o, ${model} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
+
+ let scaleClause = "";
+ const scaleStr = curve.scale;
+ if (xAxisParam !== "Grid scale" && yAxisParam !== "Grid scale") {
+ if (scaleStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s grid scale is undefined. Please assign it a value.`
+ );
+ }
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+ scaleClause = `and m0.scale = ${scale} `;
+ }
+
let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
- let matchClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and (m0.secs)%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = Number(curve["forecast-length"]) * 60;
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ const statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ `sum(${variable[0]}) as square_diff_sum, count(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
+ `group_concat(m0.secs, ';', ${variable[0]}, ';', 1, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.secs) as sub_data, count(${variable[0]}) as N0`;
+
+ let dateString = "";
+ let dateClause = "";
+ let matchClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -103,119 +121,137 @@ dataContour = function (plotParams, plotFunction) {
} else {
dateString = "m0.secs";
}
- dateClause = `and o.secs >= ${fromSecs} and o.secs <= ${toSecs}`;
- dateClause = `${dateClause} and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
+ dateClause = `and o.secs >= ${fromSecs} and o.secs <= ${toSecs} and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
matchClause = "and m0.id = o.id and m0.secs = o.secs";
- const statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- `sum(${variable[0]}) as square_diff_sum, count(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
- `group_concat(m0.secs, ';', ${variable[0]}, ';', 1, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.secs) as sub_data, count(${variable[0]}) as N0`;
- const statType = statisticOptionsMap[statisticSelect];
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ let regionClause;
+ if (region === "all_stat") {
+ regionClause = "";
+ } else if (region === "all_surf") {
+ regionClause = "and m0.id in(1,2,3,4,5,6,7) ";
+ } else if (region === "all_sol") {
+ regionClause = "and m0.id in(8,9,10,11,12,13,14) ";
+ } else {
+ regionClause = `and m0.id in(${region}) `;
+ }
+
+ const queryTableClause = `from surfrad as o, ${model} as m0`;
+
+ // For contours, this functions as the colorbar label.
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
+ const statType = statisticOptionsMap[statisticSelect];
const varUnits = statVarUnitMap[statisticSelect][variableStr];
-
- // For contours, this functions as the colorbar label.
curve.unitKey = varUnits;
let d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{matchClause}} " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{scaleClause}} " +
- "{{regionClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{matchClause}} " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{scaleClause}} " +
+ "{{regionClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{scaleClause}}", scaleClause);
- statement = statement.replace("{{regionClause}}", regionClause);
- statement = statement.replace("{{matchClause}}", matchClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{scaleClause}}", scaleClause);
+ statement = statement.replace("{{regionClause}}", regionClause);
+ statement = statement.replace("{{matchClause}}", matchClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
- if (
- model !== "HRRR" &&
- variableStr !== "dswrf" &&
- statisticSelect !== "Obs average"
- ) {
- throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is only available for the HRRR data-source.`
- );
- }
+ if (
+ model !== "HRRR" &&
+ variableStr !== "dswrf" &&
+ statisticSelect !== "Obs average"
+ ) {
+ throw new Error(
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is only available for the HRRR data-source.`
+ );
+ }
- let queryResult;
- const startMoment = moment();
- let finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- `${statisticSelect}_${variableStr}`
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ `${statisticSelect}_${variableStr}`
+ );
+
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
- }
- if (!dataFoundForCurve) {
- // we found no data for any curves so don't bother proceeding
- throw new Error("INFO: No valid data for any curves.");
- }
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
+ // this is NOT an error just a no data condition
+ dataFoundForCurve = false;
+ } else {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ }
- const postQueryStartMoment = moment();
+ if (!dataFoundForCurve) {
+ // we found no data for any curves so don't bother proceeding
+ throw new Error("INFO: No valid data for any curves.");
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
+ }
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
diff --git a/apps/surfrad/server/dataFunctions/data_contour_diff.js b/apps/surfrad/server/dataFunctions/data_contour_diff.js
index c72228140b..ae6f0c2be7 100644
--- a/apps/surfrad/server/dataFunctions/data_contour_diff.js
+++ b/apps/surfrad/server/dataFunctions/data_contour_diff.js
@@ -14,6 +14,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataContourDiff = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -24,82 +25,102 @@ dataContourDiff = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
- let dataFoundForCurve = true;
let dataNotFoundForAnyCurve = false;
+
+ let curves = JSON.parse(JSON.stringify(plotParams.curves));
+ const curvesLength = curves.length;
+ if (curvesLength !== 2) {
+ throw new Error("INFO: There must be two added curves.");
+ }
+
+ const axisMap = Object.create(null);
const showSignificance = plotParams.significance !== "none";
- const totalProcessingStart = moment();
+
+ let statType;
+ let statisticSelect;
+ let variableStr;
+
+ let statement = "";
+ let error = "";
+ let dataset = [];
+
const dateRange = matsDataUtils.getDateRange(plotParams.dates);
const fromSecs = dateRange.fromSeconds;
const toSecs = dateRange.toSeconds;
+
const xAxisParam = plotParams["x-axis-parameter"];
const yAxisParam = plotParams["y-axis-parameter"];
const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" })
.optionsMap[xAxisParam];
const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" })
.optionsMap[yAxisParam];
- let error = "";
- let curves = JSON.parse(JSON.stringify(plotParams.curves));
- const curvesLength = curves.length;
- if (curvesLength !== 2) {
- throw new Error("INFO: There must be two added curves.");
- }
- let dataset = [];
- const axisMap = Object.create(null);
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var regionClause;
- if (region === "all_stat") {
- regionClause = "";
- } else if (region === "all_surf") {
- regionClause = "and m0.id in(1,2,3,4,5,6,7) ";
- } else if (region === "all_sol") {
- regionClause = "and m0.id in(8,9,10,11,12,13,14) ";
- } else {
- regionClause = `and m0.id in(${region}) `;
- }
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const scaleClause = `and m0.scale = ${grid_scale}`;
- const queryTableClause = `from surfrad as o, ${model} as m0`;
- var variableStr = curve.variable;
+
+ variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
+
+ let scaleClause = "";
+ const scaleStr = curve.scale;
+ if (xAxisParam !== "Grid scale" && yAxisParam !== "Grid scale") {
+ if (scaleStr === undefined) {
+ throw new Error(
+ `INFO: ${label}'s grid scale is undefined. Please assign it a value.`
+ );
+ }
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+ scaleClause = `and m0.scale = ${scale} `;
+ }
+
let validTimeClause = "";
- let forecastLengthClause = "";
- let dateString = "";
- let dateClause = "";
- let matchClause = "";
if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and (m0.secs)%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") {
const forecastLength = Number(curve["forecast-length"]) * 60;
+ if (forecastLength === undefined) {
+ throw new Error(
+ `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.`
+ );
+ }
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
+
+ statisticSelect = curve.statistic;
+ const statisticOptionsMap = matsCollections.statistic.findOne(
+ { name: "statistic" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const statisticClause =
+ `sum(${variable[0]}) as square_diff_sum, count(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
+ `group_concat(m0.secs, ';', ${variable[0]}, ';', 1, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.secs) as sub_data, count(${variable[0]}) as N0`;
+
+ let dateString = "";
+ let dateClause = "";
+ let matchClause = "";
if (
(xAxisParam === "Init Date" || yAxisParam === "Init Date") &&
xAxisParam !== "Valid Date" &&
@@ -109,115 +130,130 @@ dataContourDiff = function (plotParams, plotFunction) {
} else {
dateString = "m0.secs";
}
- dateClause = `and o.secs >= ${fromSecs} and o.secs <= ${toSecs}`;
- dateClause = `${dateClause} and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
+ dateClause = `and o.secs >= ${fromSecs} and o.secs <= ${toSecs} and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
matchClause = "and m0.id = o.id and m0.secs = o.secs";
- var statisticSelect = curve.statistic;
- const statisticOptionsMap = matsCollections.statistic.findOne(
- { name: "statistic" },
- { optionsMap: 1 }
- ).optionsMap;
- const statisticClause =
- `sum(${variable[0]}) as square_diff_sum, count(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
- `group_concat(m0.secs, ';', ${variable[0]}, ';', 1, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.secs) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ let regionClause;
+ if (region === "all_stat") {
+ regionClause = "";
+ } else if (region === "all_surf") {
+ regionClause = "and m0.id in(1,2,3,4,5,6,7) ";
+ } else if (region === "all_sol") {
+ regionClause = "and m0.id in(8,9,10,11,12,13,14) ";
+ } else {
+ regionClause = `and m0.id in(${region}) `;
+ }
+
+ const queryTableClause = `from surfrad as o, ${model} as m0`;
+
+ // For contours, this functions as the colorbar label.
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
+ statType = statisticOptionsMap[statisticSelect];
const varUnits = statVarUnitMap[statisticSelect][variableStr];
+ curves[curveIndex].unitKey = varUnits;
- // For contours, this functions as the colorbar label.
- curve.unitKey = varUnits;
+ let d;
+ if (!diffFrom) {
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{xValClause}} " +
+ "{{yValClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{matchClause}} " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{scaleClause}} " +
+ "{{regionClause}} " +
+ "group by xVal,yVal " +
+ "order by xVal,yVal" +
+ ";";
- var d;
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{xValClause}} " +
- "{{yValClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{matchClause}} " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{scaleClause}} " +
- "{{regionClause}} " +
- "group by xVal,yVal " +
- "order by xVal,yVal" +
- ";";
+ statement = statement.replace("{{xValClause}}", xValClause);
+ statement = statement.replace("{{yValClause}}", yValClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{scaleClause}}", scaleClause);
+ statement = statement.replace("{{regionClause}}", regionClause);
+ statement = statement.replace("{{matchClause}}", matchClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
- statement = statement.replace("{{xValClause}}", xValClause);
- statement = statement.replace("{{yValClause}}", yValClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{scaleClause}}", scaleClause);
- statement = statement.replace("{{regionClause}}", regionClause);
- statement = statement.replace("{{matchClause}}", matchClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
+ if (
+ model !== "HRRR" &&
+ variableStr !== "dswrf" &&
+ statisticSelect !== "Obs average"
+ ) {
+ throw new Error(
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is only available for the HRRR data-source.`
+ );
+ }
- if (
- model !== "HRRR" &&
- variableStr !== "dswrf" &&
- statisticSelect !== "Obs average"
- ) {
- throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is only available for the HRRR data-source.`
- );
- }
+ // send the query statement to the query function
+ queryResult = matsDataQueryUtils.queryDBContour(
+ sumPool, // eslint-disable-line no-undef
+ statement,
+ appParams,
+ `${statisticSelect}_${variableStr}`
+ );
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
- // send the query statement to the query function
- queryResult = matsDataQueryUtils.queryDBContour(
- sumPool,
- statement,
- appParams,
- `${statisticSelect}_${variableStr}`
- );
- finishMoment = moment();
- dataRequests[`data retrieval (query) time - ${label}`] = {
- begin: startMoment.format(),
- finish: finishMoment.format(),
- duration: `${moment
- .duration(finishMoment.diff(startMoment))
- .asSeconds()} seconds`,
- recordCount: queryResult.data.xTextOutput.length,
- };
- // get the data back from the query
- d = queryResult.data;
- } catch (e) {
- // this is an error produced by a bug in the query function, not an error returned by the mysql database
- e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
- throw new Error(e.message);
- }
- if (queryResult.error !== undefined && queryResult.error !== "") {
- if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
- // this is NOT an error just a no data condition
- dataFoundForCurve = false;
- } else {
- // this is an error returned by the mysql database
- error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
- throw new Error(error);
+ finishMoment = moment();
+ dataRequests[label] = statement;
+ dataRequests[`data retrieval (query) time - ${label}`] = {
+ begin: startMoment.format(),
+ finish: finishMoment.format(),
+ duration: `${moment
+ .duration(finishMoment.diff(startMoment))
+ .asSeconds()} seconds`,
+ recordCount: queryResult.data.xTextOutput.length,
+ };
+ // get the data back from the query
+ d = queryResult.data;
+ } catch (e) {
+ // this is an error produced by a bug in the query function, not an error returned by the mysql database
+ e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
+ throw new Error(e.message);
}
- dataNotFoundForAnyCurve = true;
- }
- const postQueryStartMoment = moment();
+ if (queryResult.error !== undefined && queryResult.error !== "") {
+ if (queryResult.error !== matsTypes.Messages.NO_DATA_FOUND) {
+ // this is an error returned by the mysql database
+ error += `Error from verification query:
${queryResult.error}
query:
${statement}
`;
+ throw new Error(error);
+ }
+ dataNotFoundForAnyCurve = true;
+ }
+ } else {
+ // this is a difference curve -- not supported for contours
+ throw new Error(
+ "INFO: Difference curves are not supported for contours, as there is only one curve."
+ );
+ }
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const { mean } = d.glob_stats;
const annotation =
mean === undefined
@@ -266,8 +302,9 @@ dataContourDiff = function (plotParams, plotFunction) {
statType === "ctc",
statType === "scalar"
);
- plotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
- curves = plotParams.curves;
+ const newPlotParams = plotParams;
+ newPlotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves);
+ curves = newPlotParams.curves;
dataset[0].name = matsPlotUtils.getCurveText(
matsTypes.PlotTypes.contourDiff,
curves[0]
@@ -283,7 +320,7 @@ dataContourDiff = function (plotParams, plotFunction) {
const result = matsDataProcessUtils.processDataContour(
dataset,
curveInfoParams,
- plotParams,
+ newPlotParams,
bookkeepingParams
);
plotFunction(result);
diff --git a/apps/surfrad/server/dataFunctions/data_dailymodelcycle.js b/apps/surfrad/server/dataFunctions/data_dailymodelcycle.js
index 11b354ff91..abac793260 100644
--- a/apps/surfrad/server/dataFunctions/data_dailymodelcycle.js
+++ b/apps/surfrad/server/dataFunctions/data_dailymodelcycle.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataDailyModelCycle = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,71 +24,63 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var regionClause;
- if (region === "all_stat") {
- regionClause = "";
- } else if (region === "all_surf") {
- regionClause = "and m0.id in(1,2,3,4,5,6,7) ";
- } else if (region === "all_sol") {
- regionClause = "and m0.id in(8,9,10,11,12,13,14) ";
- } else {
- regionClause = `and m0.id in(${region}) `;
- }
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const scaleClause = `and m0.scale = ${grid_scale}`;
- const queryTableClause = `from surfrad as o, ${model} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
- const utcCycleStart = Number(curve["utc-cycle-start"]);
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+ const scaleClause = `and m0.scale = ${scale}`;
+
+ const utcCycleStart = Number(curve["utc-cycle-start"][0]);
utcCycleStarts[curveIndex] = utcCycleStart;
const utcCycleStartClause = `and floor(((m0.secs - m0.fcst_len*60))%(24*3600)/900)/4 IN(${utcCycleStart})`;
+
const forecastLengthClause = "and m0.fcst_len < 24 * 60";
- let dateClause = `and o.secs >= ${fromSecs} and o.secs <= ${toSecs}`;
- dateClause = `${dateClause} and m0.secs >= ${fromSecs} and m0.secs <= ${toSecs}`;
- const matchClause = "and m0.id = o.id and m0.secs = o.secs";
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -96,73 +89,96 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
const statisticClause =
`sum(${variable[0]}) as square_diff_sum, count(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
`group_concat(m0.secs, ';', ${variable[0]}, ';', 1, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.secs) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
- const { statVarUnitMap } = matsCollections.variable.findOne(
- { name: "variable" },
- { statVarUnitMap: 1 }
+
+ const dateClause = `and o.secs >= ${fromSecs} and o.secs <= ${toSecs} and m0.secs >= ${fromSecs} and m0.secs <= ${toSecs}`;
+ const matchClause = "and m0.id = o.id and m0.secs = o.secs";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
);
- const varUnits = statVarUnitMap[statisticSelect][variableStr];
+ let regionClause;
+ if (region === "all_stat") {
+ regionClause = "";
+ } else if (region === "all_surf") {
+ regionClause = "and m0.id in(1,2,3,4,5,6,7) ";
+ } else if (region === "all_sol") {
+ regionClause = "and m0.id in(8,9,10,11,12,13,14) ";
+ } else {
+ regionClause = `and m0.id in(${region}) `;
+ }
+
+ const queryTableClause = `from surfrad as o, ${model} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- const axisKey = varUnits;
+ const { statVarUnitMap } = matsCollections.variable.findOne(
+ { name: "variable" },
+ { statVarUnitMap: 1 }
+ );
+ statType = statisticOptionsMap[statisticSelect];
+ const axisKey = statVarUnitMap[statisticSelect][variableStr];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.secs as avtime, " +
- "count(distinct m0.secs) as N_times, " +
- "min(m0.secs) as min_secs, " +
- "max(m0.secs) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{matchClause}} " +
- "{{dateClause}} " +
- "{{utcCycleStartClause}} " +
- "{{forecastLengthClause}} " +
- "{{scaleClause}} " +
- "{{regionClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "select m0.secs as avtime, " +
+ "count(distinct m0.secs) as N_times, " +
+ "min(m0.secs) as min_secs, " +
+ "max(m0.secs) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{matchClause}} " +
+ "{{dateClause}} " +
+ "{{utcCycleStartClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{scaleClause}} " +
+ "{{regionClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{scaleClause}}", scaleClause);
- statement = statement.replace("{{regionClause}}", regionClause);
- statement = statement.replace("{{matchClause}}", matchClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{scaleClause}}", scaleClause);
+ statement = statement.replace("{{regionClause}}", regionClause);
+ statement = statement.replace("{{matchClause}}", matchClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
- if (
- model !== "HRRR" &&
- variableStr !== "dswrf" &&
- statisticSelect !== "Obs average"
- ) {
- throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is only available for the HRRR data-source.`
- );
- }
+ if (
+ model !== "HRRR" &&
+ variableStr !== "dswrf" &&
+ statisticSelect !== "Obs average"
+ ) {
+ throw new Error(
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is only available for the HRRR data-source.`
+ );
+ }
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
`${statisticSelect}_${variableStr}`
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -178,6 +194,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -192,7 +209,6 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -217,6 +233,7 @@ dataDailyModelCycle = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/surfrad/server/dataFunctions/data_histogram.js b/apps/surfrad/server/dataFunctions/data_histogram.js
index d349041731..333884b0fe 100644
--- a/apps/surfrad/server/dataFunctions/data_histogram.js
+++ b/apps/surfrad/server/dataFunctions/data_histogram.js
@@ -11,6 +11,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataHistogram = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -21,77 +22,65 @@ dataHistogram = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
- const alreadyMatched = false;
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
const dataFoundForCurve = [];
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+ const alreadyMatched = false;
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
+
+ const axisMap = Object.create(null);
+ let statType;
+ let varUnits;
+
+ let statement = "";
+ let error = "";
const dataset = [];
const allReturnedSubStats = [];
const allReturnedSubSecs = [];
- const axisMap = Object.create(null);
// process user bin customizations
const binParams = matsDataUtils.setHistogramParameters(plotParams);
const { yAxisFormat } = binParams;
const { binNum } = binParams;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
dataFoundForCurve[curveIndex] = true;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var regionClause;
- if (region === "all_stat") {
- regionClause = "";
- } else if (region === "all_surf") {
- regionClause = "and m0.id in(1,2,3,4,5,6,7) ";
- } else if (region === "all_sol") {
- regionClause = "and m0.id in(8,9,10,11,12,13,14) ";
- } else {
- regionClause = `and m0.id in(${region}) `;
- }
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const scaleClause = `and m0.scale = ${grid_scale}`;
- const queryTableClause = `from surfrad as o, ${model} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+ const scaleClause = `and m0.scale = ${scale}`;
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and (m0.secs)%(24*3600)/3600 IN(${validTimes})`;
}
+
const forecastLength = Number(curve["forecast-length"]) * 60;
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let dateClause = `and o.secs >= ${fromSecs} and o.secs <= ${toSecs}`;
- dateClause = `${dateClause} and m0.secs >= ${fromSecs} and m0.secs <= ${toSecs}`;
- const matchClause = "and m0.id = o.id and m0.secs = o.secs";
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -100,16 +89,43 @@ dataHistogram = function (plotParams, plotFunction) {
const statisticClause =
`sum(${variable[0]}) as square_diff_sum, count(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
`group_concat(m0.secs, ';', ${variable[0]}, ';', 1, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.secs) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
- const { statVarUnitMap } = matsCollections.variable.findOne(
- { name: "variable" },
- { statVarUnitMap: 1 }
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and o.secs >= ${fromSecs} and o.secs <= ${toSecs} and m0.secs >= ${fromSecs} and m0.secs <= ${toSecs}`;
+ const matchClause = "and m0.id = o.id and m0.secs = o.secs";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
);
- var varUnits = statVarUnitMap[statisticSelect][variableStr];
+ let regionClause;
+ if (region === "all_stat") {
+ regionClause = "";
+ } else if (region === "all_surf") {
+ regionClause = "and m0.id in(1,2,3,4,5,6,7) ";
+ } else if (region === "all_sol") {
+ regionClause = "and m0.id in(8,9,10,11,12,13,14) ";
+ } else {
+ regionClause = `and m0.id in(${region}) `;
+ }
+
+ const queryTableClause = `from surfrad as o, ${model} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
+ const { statVarUnitMap } = matsCollections.variable.findOne(
+ { name: "variable" },
+ { statVarUnitMap: 1 }
+ );
+ statType = statisticOptionsMap[statisticSelect];
+ varUnits = statVarUnitMap[statisticSelect][variableStr];
let axisKey = yAxisFormat;
if (yAxisFormat === "Relative frequency") {
axisKey += " (x100)";
@@ -117,60 +133,60 @@ dataHistogram = function (plotParams, plotFunction) {
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
curves[curveIndex].binNum = binNum; // stash the binNum to use it later for bar chart options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select m0.secs as avtime, " +
- "count(distinct m0.secs) as N_times, " +
- "min(m0.secs) as min_secs, " +
- "max(m0.secs) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{matchClause}} " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{scaleClause}} " +
- "{{regionClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
-
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{scaleClause}}", scaleClause);
- statement = statement.replace("{{regionClause}}", regionClause);
- statement = statement.replace("{{matchClause}}", matchClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
-
- if (
- model !== "HRRR" &&
- variableStr !== "dswrf" &&
- statisticSelect !== "Obs average"
- ) {
- throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is only available for the HRRR data-source.`
- );
- }
-
- var queryResult;
+ let queryResult;
const startMoment = moment();
- var finishMoment;
+ let finishMoment;
try {
+ statement =
+ "select m0.secs as avtime, " +
+ "count(distinct m0.secs) as N_times, " +
+ "min(m0.secs) as min_secs, " +
+ "max(m0.secs) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{matchClause}} " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{scaleClause}} " +
+ "{{regionClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
+
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{scaleClause}}", scaleClause);
+ statement = statement.replace("{{regionClause}}", regionClause);
+ statement = statement.replace("{{matchClause}}", matchClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
+
+ if (
+ model !== "HRRR" &&
+ variableStr !== "dswrf" &&
+ statisticSelect !== "Obs average"
+ ) {
+ throw new Error(
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is only available for the HRRR data-source.`
+ );
+ }
+
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
`${statisticSelect}_${variableStr}`
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -188,6 +204,7 @@ dataHistogram = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
diff --git a/apps/surfrad/server/dataFunctions/data_series.js b/apps/surfrad/server/dataFunctions/data_series.js
index 27676e430a..cfa67b09c8 100644
--- a/apps/surfrad/server/dataFunctions/data_series.js
+++ b/apps/surfrad/server/dataFunctions/data_series.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSeries = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,80 +24,66 @@ dataSeries = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- const dateRange = matsDataUtils.getDateRange(plotParams.dates);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ const dateRange = matsDataUtils.getDateRange(plotParams.dates);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var regionClause;
- if (region === "all_stat") {
- regionClause = "";
- } else if (region === "all_surf") {
- regionClause = "and m0.id in(1,2,3,4,5,6,7) ";
- } else if (region === "all_sol") {
- regionClause = "and m0.id in(8,9,10,11,12,13,14) ";
- } else {
- regionClause = `and m0.id in(${region}) `;
- }
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const scaleClause = `and m0.scale = ${grid_scale}`;
- const queryTableClause = `from surfrad as o, ${model} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+ const scaleClause = `and m0.scale = ${scale}`;
+
let validTimeClause = "";
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and (m0.secs)%(24*3600)/3600 IN(${validTimes})`;
}
+
let forecastLength = Number(curve["forecast-length"]) * 60;
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- let dateClause = `and o.secs >= ${fromSecs} and o.secs <= ${toSecs}`;
- dateClause = `${dateClause} and m0.secs >= ${fromSecs} and m0.secs <= ${toSecs}`;
- const matchClause = "and m0.id = o.id and m0.secs = o.secs";
- const averageStr = curve.average;
- const averageOptionsMap = matsCollections.average.findOne(
- { name: "average" },
- { optionsMap: 1 }
- ).optionsMap;
- const average = averageOptionsMap[averageStr][0];
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -105,74 +92,102 @@ dataSeries = function (plotParams, plotFunction) {
const statisticClause =
`sum(${variable[0]}) as square_diff_sum, count(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
`group_concat(m0.secs, ';', ${variable[0]}, ';', 1, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.secs) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
- const { statVarUnitMap } = matsCollections.variable.findOne(
- { name: "variable" },
- { statVarUnitMap: 1 }
+
+ const averageStr = curve.average;
+ const averageOptionsMap = matsCollections.average.findOne(
+ { name: "average" },
+ { optionsMap: 1 }
+ ).optionsMap;
+ const average = averageOptionsMap[averageStr][0];
+
+ const dateClause = `and o.secs >= ${fromSecs} and o.secs <= ${toSecs} and m0.secs >= ${fromSecs} and m0.secs <= ${toSecs}`;
+ const matchClause = "and m0.id = o.id and m0.secs = o.secs";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
);
- const varUnits = statVarUnitMap[statisticSelect][variableStr];
+ let regionClause;
+ if (region === "all_stat") {
+ regionClause = "";
+ } else if (region === "all_surf") {
+ regionClause = "and m0.id in(1,2,3,4,5,6,7) ";
+ } else if (region === "all_sol") {
+ regionClause = "and m0.id in(8,9,10,11,12,13,14) ";
+ } else {
+ regionClause = `and m0.id in(${region}) `;
+ }
+
+ const queryTableClause = `from surfrad as o, ${model} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- const axisKey = varUnits;
+ const { statVarUnitMap } = matsCollections.variable.findOne(
+ { name: "variable" },
+ { statVarUnitMap: 1 }
+ );
+ statType = statisticOptionsMap[statisticSelect];
+ const axisKey = statVarUnitMap[statisticSelect][variableStr];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select {{average}} as avtime, " +
- "count(distinct m0.secs) as N_times, " +
- "min(m0.secs) as min_secs, " +
- "max(m0.secs) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{matchClause}} " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{scaleClause}} " +
- "{{regionClause}} " +
- "group by avtime " +
- "order by avtime" +
- ";";
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "select {{average}} as avtime, " +
+ "count(distinct m0.secs) as N_times, " +
+ "min(m0.secs) as min_secs, " +
+ "max(m0.secs) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{matchClause}} " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{scaleClause}} " +
+ "{{regionClause}} " +
+ "group by avtime " +
+ "order by avtime" +
+ ";";
- statement = statement.replace("{{average}}", average);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{scaleClause}}", scaleClause);
- statement = statement.replace("{{regionClause}}", regionClause);
- statement = statement.replace("{{matchClause}}", matchClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
+ statement = statement.replace("{{average}}", average);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{scaleClause}}", scaleClause);
+ statement = statement.replace("{{regionClause}}", regionClause);
+ statement = statement.replace("{{matchClause}}", matchClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
- if (
- model !== "HRRR" &&
- variableStr !== "dswrf" &&
- statisticSelect !== "Obs average"
- ) {
- throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is only available for the HRRR data-source.`
- );
- }
+ if (
+ model !== "HRRR" &&
+ variableStr !== "dswrf" &&
+ statisticSelect !== "Obs average"
+ ) {
+ throw new Error(
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is only available for the HRRR data-source.`
+ );
+ }
- // math is done on forecastLength later on -- set all analyses to 0
- if (forecastLength === "-99") {
- forecastLength = "0";
- }
+ // math is done on forecastLength later on -- set all analyses to 0
+ if (forecastLength === "-99") {
+ forecastLength = "0";
+ }
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBTimeSeries(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
model,
forecastLength,
@@ -184,7 +199,9 @@ dataSeries = function (plotParams, plotFunction) {
appParams,
false
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -200,6 +217,7 @@ dataSeries = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -214,7 +232,6 @@ dataSeries = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -239,6 +256,7 @@ dataSeries = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/surfrad/server/dataFunctions/data_simple_scatter.js b/apps/surfrad/server/dataFunctions/data_simple_scatter.js
index 6e5c1134e6..4193a83304 100644
--- a/apps/surfrad/server/dataFunctions/data_simple_scatter.js
+++ b/apps/surfrad/server/dataFunctions/data_simple_scatter.js
@@ -12,6 +12,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataSimpleScatter = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -22,14 +23,15 @@ dataSimpleScatter = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
+
const axisXMap = Object.create(null);
const axisYMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
@@ -37,43 +39,27 @@ dataSimpleScatter = function (plotParams, plotFunction) {
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statType;
+ let varUnitsX;
+ let varUnitsY;
+
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
+
const binParam = curve["bin-parameter"];
const binClause = matsCollections["bin-parameter"].findOne({
name: "bin-parameter",
}).optionsMap[binParam];
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var regionClause;
- if (region === "all_stat") {
- regionClause = "";
- } else if (region === "all_surf") {
- regionClause = "and m0.id in(1,2,3,4,5,6,7) ";
- } else if (region === "all_sol") {
- regionClause = "and m0.id in(8,9,10,11,12,13,14) ";
- } else {
- regionClause = `and m0.id in(${region}) `;
- }
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const scaleClause = `and m0.scale = ${grid_scale}`;
- const queryTableClause = `from surfrad as o, ${model} as m0`;
+
const variableXStr = curve["x-variable"];
const variableYStr = curve["y-variable"];
const variableOptionsMap = matsCollections.variable.findOne(
@@ -82,20 +68,25 @@ dataSimpleScatter = function (plotParams, plotFunction) {
).optionsMap;
const variableX = variableOptionsMap[variableXStr];
const variableY = variableOptionsMap[variableYStr];
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+ const scaleClause = `and m0.scale = ${scale}`;
+
let validTimeClause = "";
- let forecastLengthClause = "";
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let dateString = "";
- let dateClause = "";
- let matchClause = "";
if (binParam !== "Valid UTC hour") {
const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"];
- if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) {
+ if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) {
validTimeClause = `and (m0.secs)%(24*3600)/3600 IN(${validTimes})`;
}
}
+
+ let forecastLengthClause = "";
if (binParam !== "Fcst lead time") {
const forecastLength = Number(curve["forecast-length"]) * 60;
if (forecastLength === undefined) {
@@ -105,14 +96,7 @@ dataSimpleScatter = function (plotParams, plotFunction) {
}
forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
}
- if (binParam === "Init Date" && binParam !== "Valid Date") {
- dateString = "m0.secs-m0.fcst_len*60";
- } else {
- dateString = "m0.secs";
- }
- dateClause = `and o.secs >= ${fromSecs} and o.secs <= ${toSecs}`;
- dateClause = `${dateClause} and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
- matchClause = "and m0.id = o.id and m0.secs = o.secs";
+
const statisticXSelect = curve["x-statistic"];
const statisticYSelect = curve["y-statistic"];
const statisticOptionsMap = matsCollections.statistic.findOne(
@@ -123,79 +107,114 @@ dataSimpleScatter = function (plotParams, plotFunction) {
`sum(${variableX[0]}) as square_diff_sumX, count(${variableX[1]}) as N_sumX, sum(${variableX[2]}) as obs_model_diff_sumX, sum(${variableX[3]}) as model_sumX, sum(${variableX[4]}) as obs_sumX, sum(${variableX[5]}) as abs_sumX, ` +
`sum(${variableY[0]}) as square_diff_sumY, count(${variableY[1]}) as N_sumY, sum(${variableY[2]}) as obs_model_diff_sumY, sum(${variableY[3]}) as model_sumY, sum(${variableY[4]}) as obs_sumY, sum(${variableY[5]}) as abs_sumY, ` +
`group_concat(m0.secs, ';', ${variableX[0]}, ';', 1, ';', ${variableX[2]}, ';', ${variableX[3]}, ';', ${variableX[4]}, ';', ${variableX[5]}, ';', ${variableY[0]}, ';', 1, ';', ${variableY[2]}, ';', ${variableY[3]}, ';', ${variableY[4]}, ';', ${variableY[5]} order by m0.secs) as sub_data, count(${variableX[0]}) as N0`;
- var statType = statisticOptionsMap[statisticXSelect];
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ let dateString = "";
+ let dateClause = "";
+ let matchClause = "";
+ if (binParam === "Init Date" && binParam !== "Valid Date") {
+ dateString = "m0.secs-m0.fcst_len*60";
+ } else {
+ dateString = "m0.secs";
+ }
+ dateClause = `and o.secs >= ${fromSecs} and o.secs <= ${toSecs} and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`;
+ matchClause = "and m0.id = o.id and m0.secs = o.secs";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
+ );
+ let regionClause;
+ if (region === "all_stat") {
+ regionClause = "";
+ } else if (region === "all_surf") {
+ regionClause = "and m0.id in(1,2,3,4,5,6,7) ";
+ } else if (region === "all_sol") {
+ regionClause = "and m0.id in(8,9,10,11,12,13,14) ";
+ } else {
+ regionClause = `and m0.id in(${region}) `;
+ }
+
+ const queryTableClause = `from surfrad as o, ${model} as m0`;
+
const { statVarUnitMap } = matsCollections.variable.findOne(
{ name: "variable" },
{ statVarUnitMap: 1 }
);
- const varUnitsX = statVarUnitMap[statisticXSelect][variableXStr];
- const varUnitsY = statVarUnitMap[statisticYSelect][variableYStr];
+ statType = statisticOptionsMap[statisticXSelect];
+ varUnitsX = statVarUnitMap[statisticXSelect][variableXStr];
+ varUnitsY = statVarUnitMap[statisticYSelect][variableYStr];
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "{{binClause}} " +
- "count(distinct {{dateString}}) as N_times, " +
- "min({{dateString}}) as min_secs, " +
- "max({{dateString}}) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{matchClause}} " +
- "{{dateClause}} " +
- "{{validTimeClause}} " +
- "{{forecastLengthClause}} " +
- "{{scaleClause}} " +
- "{{regionClause}} " +
- "group by binVal " +
- "order by binVal" +
- ";";
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "{{binClause}} " +
+ "count(distinct {{dateString}}) as N_times, " +
+ "min({{dateString}}) as min_secs, " +
+ "max({{dateString}}) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{matchClause}} " +
+ "{{dateClause}} " +
+ "{{validTimeClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{scaleClause}} " +
+ "{{regionClause}} " +
+ "group by binVal " +
+ "order by binVal" +
+ ";";
- statement = statement.replace("{{binClause}}", binClause);
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{validTimeClause}}", validTimeClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{scaleClause}}", scaleClause);
- statement = statement.replace("{{regionClause}}", regionClause);
- statement = statement.replace("{{matchClause}}", matchClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- statement = statement.split("{{dateString}}").join(dateString);
- dataRequests[label] = statement;
+ statement = statement.replace("{{binClause}}", binClause);
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{validTimeClause}}", validTimeClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{scaleClause}}", scaleClause);
+ statement = statement.replace("{{regionClause}}", regionClause);
+ statement = statement.replace("{{matchClause}}", matchClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ statement = statement.split("{{dateString}}").join(dateString);
+ dataRequests[label] = statement;
- if (
- model !== "HRRR" &&
- variableXStr !== "dswrf" &&
- statisticXSelect !== "Obs average"
- ) {
- throw new Error(
- `INFO: The statistic/variable combination [${statisticXSelect} and ${variableXStr}] is only available for the HRRR data-source.`
- );
- } else if (
- model !== "HRRR" &&
- variableYStr !== "dswrf" &&
- statisticYSelect !== "Obs average"
- ) {
- throw new Error(
- `INFO: The statistic/variable combination [${statisticYSelect} and ${variableYStr}] is only available for the HRRR data-source.`
- );
- }
+ if (
+ model !== "HRRR" &&
+ variableXStr !== "dswrf" &&
+ statisticXSelect !== "Obs average"
+ ) {
+ throw new Error(
+ `INFO: The statistic/variable combination [${statisticXSelect} and ${variableXStr}] is only available for the HRRR data-source.`
+ );
+ } else if (
+ model !== "HRRR" &&
+ variableYStr !== "dswrf" &&
+ statisticYSelect !== "Obs average"
+ ) {
+ throw new Error(
+ `INFO: The statistic/variable combination [${statisticYSelect} and ${variableYStr}] is only available for the HRRR data-source.`
+ );
+ }
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSimpleScatter(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
`${statisticXSelect}_${variableXStr}`,
`${statisticYSelect}_${variableYStr}`
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -211,6 +230,7 @@ dataSimpleScatter = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -225,7 +245,6 @@ dataSimpleScatter = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -233,7 +252,7 @@ dataSimpleScatter = function (plotParams, plotFunction) {
ymax = ymax > d.ymax ? ymax : d.ymax;
}
} else {
- // this is a difference curve -- not supported for ROC plots
+ // this is a difference curve -- not supported for scatter plots
throw new Error(
"INFO: Difference curves are not supported for performance diagrams, as they do not feature consistent x or y values across all curves."
);
@@ -241,6 +260,7 @@ dataSimpleScatter = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/surfrad/server/dataFunctions/data_validtime.js b/apps/surfrad/server/dataFunctions/data_validtime.js
index bc0c4cff22..d2eaf27344 100644
--- a/apps/surfrad/server/dataFunctions/data_validtime.js
+++ b/apps/surfrad/server/dataFunctions/data_validtime.js
@@ -13,6 +13,7 @@ import {
} from "meteor/randyp:mats-common";
import { moment } from "meteor/momentjs:moment";
+// eslint-disable-next-line no-undef
dataValidTime = function (plotParams, plotFunction) {
// initialize variables common to all curves
const appParams = {
@@ -23,69 +24,56 @@ dataValidTime = function (plotParams, plotFunction) {
hideGaps: plotParams.noGapsCheck,
hasLevels: false,
};
+
+ const totalProcessingStart = moment();
const dataRequests = {}; // used to store data queries
let dataFoundForCurve = true;
let dataFoundForAnyCurve = false;
- const totalProcessingStart = moment();
- let error = "";
+
const curves = JSON.parse(JSON.stringify(plotParams.curves));
const curvesLength = curves.length;
- const dataset = [];
- const utcCycleStarts = [];
+
const axisMap = Object.create(null);
let xmax = -1 * Number.MAX_VALUE;
let ymax = -1 * Number.MAX_VALUE;
let xmin = Number.MAX_VALUE;
let ymin = Number.MAX_VALUE;
+
+ let statType;
+ const utcCycleStarts = [];
const idealValues = [];
- for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) {
+ let statement = "";
+ let error = "";
+ const dataset = [];
+
+ for (let curveIndex = 0; curveIndex < curvesLength; curveIndex += 1) {
// initialize variables specific to each curve
const curve = curves[curveIndex];
- const { diffFrom } = curve;
const { label } = curve;
+ const { diffFrom } = curve;
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[curve["data-source"]][0];
- var regionStr = curve.region;
- const region = Object.keys(
- matsCollections.region.findOne({ name: "region" }).valuesMap
- ).find(
- (key) =>
- matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
- );
- var regionClause;
- if (region === "all_stat") {
- regionClause = "";
- } else if (region === "all_surf") {
- regionClause = "and m0.id in(1,2,3,4,5,6,7) ";
- } else if (region === "all_sol") {
- regionClause = "and m0.id in(8,9,10,11,12,13,14) ";
- } else {
- regionClause = `and m0.id in(${region}) `;
- }
- var scaleStr = curve.scale;
- const grid_scale = Object.keys(
- matsCollections.scale.findOne({ name: "scale" }).valuesMap
- ).find(
- (key) =>
- matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
- );
- const scaleClause = `and m0.scale = ${grid_scale}`;
- const queryTableClause = `from surfrad as o, ${model} as m0`;
+
const variableStr = curve.variable;
const variableOptionsMap = matsCollections.variable.findOne(
{ name: "variable" },
{ optionsMap: 1 }
).optionsMap;
const variable = variableOptionsMap[variableStr];
+
+ const scaleStr = curve.scale;
+ const scale = Object.keys(
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.scale.findOne({ name: "scale" }).valuesMap[key] === scaleStr
+ );
+ const scaleClause = `and m0.scale = ${scale}`;
+
const forecastLength = Number(curve["forecast-length"]) * 60;
const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`;
- const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
- const fromSecs = dateRange.fromSeconds;
- const toSecs = dateRange.toSeconds;
- let dateClause = `and o.secs >= ${fromSecs} and o.secs <= ${toSecs}`;
- dateClause = `${dateClause} and m0.secs >= ${fromSecs} and m0.secs <= ${toSecs}`;
- const matchClause = "and m0.id = o.id and m0.secs = o.secs";
+
const statisticSelect = curve.statistic;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
@@ -94,71 +82,97 @@ dataValidTime = function (plotParams, plotFunction) {
const statisticClause =
`sum(${variable[0]}) as square_diff_sum, count(${variable[1]}) as N_sum, sum(${variable[2]}) as obs_model_diff_sum, sum(${variable[3]}) as model_sum, sum(${variable[4]}) as obs_sum, sum(${variable[5]}) as abs_sum, ` +
`group_concat(m0.secs, ';', ${variable[0]}, ';', 1, ';', ${variable[2]}, ';', ${variable[3]}, ';', ${variable[4]}, ';', ${variable[5]} order by m0.secs) as sub_data, count(${variable[0]}) as N0`;
- var statType = statisticOptionsMap[statisticSelect];
- const { statVarUnitMap } = matsCollections.variable.findOne(
- { name: "variable" },
- { statVarUnitMap: 1 }
+
+ const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]);
+ const fromSecs = dateRange.fromSeconds;
+ const toSecs = dateRange.toSeconds;
+ const dateClause = `and o.secs >= ${fromSecs} and o.secs <= ${toSecs} and m0.secs >= ${fromSecs} and m0.secs <= ${toSecs}`;
+ const matchClause = "and m0.id = o.id and m0.secs = o.secs";
+
+ const regionStr = curve.region;
+ const region = Object.keys(
+ matsCollections.region.findOne({ name: "region" }).valuesMap
+ ).find(
+ (key) =>
+ matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr
);
- const varUnits = statVarUnitMap[statisticSelect][variableStr];
+ let regionClause;
+ if (region === "all_stat") {
+ regionClause = "";
+ } else if (region === "all_surf") {
+ regionClause = "and m0.id in(1,2,3,4,5,6,7) ";
+ } else if (region === "all_sol") {
+ regionClause = "and m0.id in(8,9,10,11,12,13,14) ";
+ } else {
+ regionClause = `and m0.id in(${region}) `;
+ }
+
+ const queryTableClause = `from surfrad as o, ${model} as m0`;
+
// axisKey is used to determine which axis a curve should use.
// This axisKeySet object is used like a set and if a curve has the same
// units (axisKey) it will use the same axis.
// The axis number is assigned to the axisKeySet value, which is the axisKey.
- const axisKey = varUnits;
+ const { statVarUnitMap } = matsCollections.variable.findOne(
+ { name: "variable" },
+ { statVarUnitMap: 1 }
+ );
+ statType = statisticOptionsMap[statisticSelect];
+ const axisKey = statVarUnitMap[statisticSelect][variableStr];
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options
- var d;
+ let d;
if (!diffFrom) {
- // this is a database driven curve, not a difference curve
- // prepare the query from the above parameters
- let statement =
- "select floor((m0.secs)%(24*3600)/900)/4 as hr_of_day, " +
- "count(distinct m0.secs) as N_times, " +
- "min(m0.secs) as min_secs, " +
- "max(m0.secs) as max_secs, " +
- "{{statisticClause}} " +
- "{{queryTableClause}} " +
- "where 1=1 " +
- "{{matchClause}} " +
- "{{dateClause}} " +
- "{{forecastLengthClause}} " +
- "{{scaleClause}} " +
- "{{regionClause}} " +
- "group by hr_of_day " +
- "order by hr_of_day" +
- ";";
+ let queryResult;
+ const startMoment = moment();
+ let finishMoment;
+ try {
+ statement =
+ "select floor((m0.secs)%(24*3600)/900)/4 as hr_of_day, " +
+ "count(distinct m0.secs) as N_times, " +
+ "min(m0.secs) as min_secs, " +
+ "max(m0.secs) as max_secs, " +
+ "{{statisticClause}} " +
+ "{{queryTableClause}} " +
+ "where 1=1 " +
+ "{{matchClause}} " +
+ "{{dateClause}} " +
+ "{{forecastLengthClause}} " +
+ "{{scaleClause}} " +
+ "{{regionClause}} " +
+ "group by hr_of_day " +
+ "order by hr_of_day" +
+ ";";
- statement = statement.replace("{{statisticClause}}", statisticClause);
- statement = statement.replace("{{queryTableClause}}", queryTableClause);
- statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
- statement = statement.replace("{{scaleClause}}", scaleClause);
- statement = statement.replace("{{regionClause}}", regionClause);
- statement = statement.replace("{{matchClause}}", matchClause);
- statement = statement.replace("{{dateClause}}", dateClause);
- dataRequests[label] = statement;
+ statement = statement.replace("{{statisticClause}}", statisticClause);
+ statement = statement.replace("{{queryTableClause}}", queryTableClause);
+ statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause);
+ statement = statement.replace("{{scaleClause}}", scaleClause);
+ statement = statement.replace("{{regionClause}}", regionClause);
+ statement = statement.replace("{{matchClause}}", matchClause);
+ statement = statement.replace("{{dateClause}}", dateClause);
+ dataRequests[label] = statement;
- if (
- model !== "HRRR" &&
- variableStr !== "dswrf" &&
- statisticSelect !== "Obs average"
- ) {
- throw new Error(
- `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is only available for the HRRR data-source.`
- );
- }
+ if (
+ model !== "HRRR" &&
+ variableStr !== "dswrf" &&
+ statisticSelect !== "Obs average"
+ ) {
+ throw new Error(
+ `INFO: The statistic/variable combination [${statisticSelect} and ${variableStr}] is only available for the HRRR data-source.`
+ );
+ }
- var queryResult;
- const startMoment = moment();
- var finishMoment;
- try {
// send the query statement to the query function
queryResult = matsDataQueryUtils.queryDBSpecialtyCurve(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
statement,
appParams,
`${statisticSelect}_${variableStr}`
);
+
finishMoment = moment();
+ dataRequests[label] = statement;
dataRequests[`data retrieval (query) time - ${label}`] = {
begin: startMoment.format(),
finish: finishMoment.format(),
@@ -174,6 +188,7 @@ dataValidTime = function (plotParams, plotFunction) {
e.message = `Error in queryDB: ${e.message} for statement: ${statement}`;
throw new Error(e.message);
}
+
if (queryResult.error !== undefined && queryResult.error !== "") {
if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) {
// this is NOT an error just a no data condition
@@ -188,7 +203,6 @@ dataValidTime = function (plotParams, plotFunction) {
}
// set axis limits based on returned data
- var postQueryStartMoment = moment();
if (dataFoundForCurve) {
xmin = xmin < d.xmin ? xmin : d.xmin;
xmax = xmax > d.xmax ? xmax : d.xmax;
@@ -213,6 +227,7 @@ dataValidTime = function (plotParams, plotFunction) {
// set curve annotation to be the curve mean -- may be recalculated later
// also pass previously calculated axis stats to curve options
+ const postQueryStartMoment = moment();
const mean = d.sum / d.x.length;
const annotation =
mean === undefined
diff --git a/apps/surfrad/server/main.js b/apps/surfrad/server/main.js
index b35b513cc4..6d020e2238 100644
--- a/apps/surfrad/server/main.js
+++ b/apps/surfrad/server/main.js
@@ -4,7 +4,9 @@
import { Meteor } from "meteor/meteor";
import { mysql } from "meteor/pcel:mysql";
+import { moment } from "meteor/momentjs:moment";
import {
+ matsMethods,
matsTypes,
matsCollections,
matsDataUtils,
@@ -317,104 +319,93 @@ const doCurveParams = function () {
const params = matsCollections.CurveParamsInfo.find({
curve_params: { $exists: true },
}).fetch()[0].curve_params;
- for (let cp = 0; cp < params.length; cp++) {
+ for (let cp = 0; cp < params.length; cp += 1) {
matsCollections[params[cp]].remove({});
}
}
+
const modelOptionsMap = {};
let modelDateRangeMap = {};
const regionModelOptionsMap = {};
const forecastLengthOptionsMap = {};
const scaleModelOptionsMap = {};
- const masterRegionValuesMap = {};
- const masterScaleValuesMap = {};
+ const allRegionValuesMap = {};
+ const allScaleValuesMap = {};
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select station,description from station_descriptions;"
);
- let masterRegDescription;
- let masterShortName;
- for (var j = 0; j < rows.length; j++) {
- masterRegDescription = rows[j].description.trim();
- masterShortName = rows[j].station.trim();
- masterRegionValuesMap[masterShortName] = masterRegDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allRegionValuesMap[rows[j].station.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select scle,description from scale_descriptions;"
);
- let masterDescription;
- let masterScale;
- for (var j = 0; j < rows.length; j++) {
- masterDescription = rows[j].description.trim();
- masterScale = rows[j].scle.trim();
- masterScaleValuesMap[masterScale] = masterDescription;
+ for (let j = 0; j < rows.length; j += 1) {
+ allScaleValuesMap[rows[j].scle.trim()] = rows[j].description.trim();
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
try {
const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous(
- sumPool,
+ sumPool, // eslint-disable-line no-undef
"select model,regions,display_text,fcst_lens,scle,mindate,maxdate from regions_per_model_mats_all_categories order by display_category, display_order;"
);
- for (let i = 0; i < rows.length; i++) {
- const model_value = rows[i].model.trim();
+ for (let i = 0; i < rows.length; i += 1) {
+ const modelValue = rows[i].model.trim();
const model = rows[i].display_text.trim();
- modelOptionsMap[model] = [model_value];
+ modelOptionsMap[model] = [modelValue];
const rowMinDate = moment.utc(rows[i].mindate * 1000).format("MM/DD/YYYY HH:mm");
const rowMaxDate = moment.utc(rows[i].maxdate * 1000).format("MM/DD/YYYY HH:mm");
- modelDateRangeMap[model] = { minDate: rowMinDate, maxDate: rowMaxDate };
+ modelDateRangeMap[model] = {
+ minDate: rowMinDate,
+ maxDate: rowMaxDate,
+ };
const forecastLengths = rows[i].fcst_lens;
- const forecastLengthArr = forecastLengths
+ forecastLengthOptionsMap[model] = forecastLengths
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- for (var j = 0; j < forecastLengthArr.length; j++) {
- forecastLengthArr[j] = (
- Number(forecastLengthArr[j].replace(/'|\[|\]/g, "")) / 60
- ).toString();
- }
- forecastLengthOptionsMap[model] = forecastLengthArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (fhr) {
+ return Number(fhr.replace(/'|\[|\]/g, "")) / 60;
+ });
const scales = rows[i].scle;
- const scalesArrRaw = scales
+ scaleModelOptionsMap[model] = scales
.split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const scalesArr = [];
- var dummyScale;
- for (var j = 0; j < scalesArrRaw.length; j++) {
- dummyScale = scalesArrRaw[j].replace(/'|\[|\]/g, "");
- scalesArr.push(masterScaleValuesMap[dummyScale]);
- }
- scaleModelOptionsMap[model] = scalesArr;
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (scale) {
+ return allScaleValuesMap[scale.replace(/'|\[|\]/g, "")];
+ });
const { regions } = rows[i];
- const regionsArrRaw = regions
- .split(",")
- .map(Function.prototype.call, String.prototype.trim);
- const regionsArr = [];
- regionsArr.push(masterRegionValuesMap.all_stat);
- regionsArr.push(masterRegionValuesMap.all_surf);
- regionsArr.push(masterRegionValuesMap.all_sol);
- var dummyRegion;
- for (var j = 0; j < regionsArrRaw.length; j++) {
- dummyRegion = regionsArrRaw[j].replace(/'|\[|\]/g, "");
- regionsArr.push(masterRegionValuesMap[dummyRegion]);
- }
- regionModelOptionsMap[model] = regionsArr;
+ regionModelOptionsMap[model] = [
+ allRegionValuesMap.all_stat,
+ allRegionValuesMap.all_surf,
+ allRegionValuesMap.all_sol,
+ ];
+ regionModelOptionsMap[model] = regionModelOptionsMap[model].concat(
+ regions
+ .split(",")
+ .map(Function.prototype.call, String.prototype.trim)
+ .map(function (region) {
+ return allRegionValuesMap[region.replace(/'|\[|\]/g, "")];
+ })
+ );
}
} catch (err) {
- console.log(err.message);
+ throw new Error(err.message);
}
if (matsCollections.label.findOne({ name: "label" }) === undefined) {
@@ -452,7 +443,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["data-source"].findOne({ name: "data-source" });
+ const currentParam = matsCollections["data-source"].findOne({
+ name: "data-source",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap) ||
!matsDataUtils.areObjectsEqual(currentParam.dates, modelDateRangeMap)
@@ -478,7 +471,7 @@ const doCurveParams = function () {
type: matsTypes.InputTypes.select,
optionsMap: regionModelOptionsMap,
options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]],
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
superiorNames: ["data-source"],
controlButtonCovered: true,
controlButtonText: "site",
@@ -491,10 +484,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.region.findOne({ name: "region" });
+ const currentParam = matsCollections.region.findOne({ name: "region" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, regionModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterRegionValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allRegionValuesMap)
) {
// have to reload region data
matsCollections.region.update(
@@ -502,7 +495,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: regionModelOptionsMap,
- valuesMap: masterRegionValuesMap,
+ valuesMap: allRegionValuesMap,
options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]],
default: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]][0],
},
@@ -511,7 +504,7 @@ const doCurveParams = function () {
}
}
- const optionsMap = {
+ const statOptionsMap = {
RMSE: "scalar",
"Bias (Model - Obs)": "scalar",
@@ -531,11 +524,11 @@ const doCurveParams = function () {
matsCollections.statistic.insert({
name: "statistic",
type: matsTypes.InputTypes.select,
- optionsMap,
- options: Object.keys(optionsMap),
+ optionsMap: statOptionsMap,
+ options: Object.keys(statOptionsMap),
controlButtonCovered: true,
unique: false,
- default: Object.keys(optionsMap)[0],
+ default: Object.keys(statOptionsMap)[0],
controlButtonVisibility: "block",
displayOrder: 1,
displayPriority: 1,
@@ -547,11 +540,11 @@ const doCurveParams = function () {
matsCollections["x-statistic"].insert({
name: "x-statistic",
type: matsTypes.InputTypes.select,
- optionsMap,
- options: Object.keys(optionsMap),
+ optionsMap: statOptionsMap,
+ options: Object.keys(statOptionsMap),
controlButtonCovered: true,
unique: false,
- default: Object.keys(optionsMap)[0],
+ default: Object.keys(statOptionsMap)[0],
controlButtonVisibility: "block",
displayOrder: 3,
displayPriority: 1,
@@ -563,11 +556,11 @@ const doCurveParams = function () {
matsCollections["y-statistic"].insert({
name: "y-statistic",
type: matsTypes.InputTypes.select,
- optionsMap,
- options: Object.keys(optionsMap),
+ optionsMap: statOptionsMap,
+ options: Object.keys(statOptionsMap),
controlButtonCovered: true,
unique: false,
- default: Object.keys(optionsMap)[0],
+ default: Object.keys(statOptionsMap)[0],
controlButtonVisibility: "block",
displayOrder: 1,
displayPriority: 1,
@@ -733,7 +726,7 @@ const doCurveParams = function () {
type: matsTypes.InputTypes.select,
optionsMap: scaleModelOptionsMap,
options: scaleModelOptionsMap[Object.keys(scaleModelOptionsMap)[0]],
- valuesMap: masterScaleValuesMap,
+ valuesMap: allScaleValuesMap,
superiorNames: ["data-source"],
controlButtonCovered: true,
unique: false,
@@ -745,10 +738,10 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections.scale.findOne({ name: "scale" });
+ const currentParam = matsCollections.scale.findOne({ name: "scale" });
if (
!matsDataUtils.areObjectsEqual(currentParam.optionsMap, scaleModelOptionsMap) ||
- !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterScaleValuesMap)
+ !matsDataUtils.areObjectsEqual(currentParam.valuesMap, allScaleValuesMap)
) {
// have to reload scale data
matsCollections.scale.update(
@@ -756,7 +749,7 @@ const doCurveParams = function () {
{
$set: {
optionsMap: scaleModelOptionsMap,
- valuesMap: masterScaleValuesMap,
+ valuesMap: allScaleValuesMap,
options: scaleModelOptionsMap[Object.keys(scaleModelOptionsMap)[0]],
default: scaleModelOptionsMap[Object.keys(scaleModelOptionsMap)[0]][1],
},
@@ -787,7 +780,7 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["forecast-length"].findOne({
+ const currentParam = matsCollections["forecast-length"].findOne({
name: "forecast-length",
});
if (
@@ -1006,7 +999,9 @@ const doCurveParams = function () {
});
} else {
// it is defined but check for necessary update
- var currentParam = matsCollections["curve-dates"].findOne({ name: "curve-dates" });
+ const currentParam = matsCollections["curve-dates"].findOne({
+ name: "curve-dates",
+ });
if (
!matsDataUtils.areObjectsEqual(currentParam.startDate, minDate) ||
!matsDataUtils.areObjectsEqual(currentParam.stopDate, maxDate) ||
@@ -1293,7 +1288,8 @@ const doPlotGraph = function () {
Meteor.startup(function () {
matsCollections.Databases.remove({});
if (matsCollections.Databases.find({}).count() < 0) {
- console.log(
+ // eslint-disable-next-line no-console
+ console.warn(
"main startup: corrupted Databases collection: dropping Databases collection"
);
matsCollections.Databases.drop();
@@ -1310,7 +1306,7 @@ Meteor.startup(function () {
databases = Meteor.settings.private.databases;
}
if (databases !== null && databases !== undefined && Array.isArray(databases)) {
- for (let di = 0; di < databases.length; di++) {
+ for (let di = 0; di < databases.length; di += 1) {
matsCollections.Databases.insert(databases[di]);
}
}
@@ -1337,6 +1333,7 @@ Meteor.startup(function () {
);
if (cbConnection) {
// global cbScorecardSettingsPool
+ // eslint-disable-next-line no-undef
cbScorecardSettingsPool = new matsCouchbaseUtils.CBUtilities(
cbConnection.host,
cbConnection.bucket,
@@ -1363,6 +1360,7 @@ Meteor.startup(function () {
);
// the pool is intended to be global
if (sumSettings) {
+ // eslint-disable-next-line no-undef
sumPool = mysql.createPool(sumSettings);
allPools.push({ pool: "sumPool", role: matsTypes.DatabaseRoles.SUMS_DATA });
}
@@ -1380,7 +1378,7 @@ Meteor.startup(function () {
appType: matsTypes.AppTypes.mats,
});
} catch (error) {
- console.log(error.message);
+ throw new Error(error.message);
}
});
@@ -1388,6 +1386,7 @@ Meteor.startup(function () {
// These are application specific mongo data - like curve params
// The appSpecificResetRoutines object is a special name,
// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way.
+// eslint-disable-next-line no-undef
appSpecificResetRoutines = [
doPlotGraph,
doCurveParams,
diff --git a/apps/upperair/.eslintrc.json b/apps/upperair/.eslintrc.json
index 243e6f82c6..80b2c78142 100644
--- a/apps/upperair/.eslintrc.json
+++ b/apps/upperair/.eslintrc.json
@@ -29,11 +29,6 @@
// for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications
"func-names": "off",
"prefer-arrow-callback": "off",
-
- // Vx Team modifications - Warn on rules that would require refactoring to implement.
- // We want to be able to turn these back into "error"'s at some point. However, for
- // our first pass, we'll only consider the checks that ESLint can auto-fix as errors.
- // https://eslint.org/docs/latest/use/configure/rules#rule-severities
"no-undef": "warn",
"no-plusplus": "warn",
"vars-on-top": "warn",
diff --git a/tests/package-lock.json b/tests/package-lock.json
index 2285841cd5..dbc9e4ec8c 100644
--- a/tests/package-lock.json
+++ b/tests/package-lock.json
@@ -25,7 +25,7 @@
"@wdio/spec-reporter": "^7.16.14",
"@wdio/static-server-service": "^7.16.14",
"@wdio/sync": "^7.16.14",
- "chromedriver": "^116.0.0",
+ "chromedriver": "^118.0.0",
"eslint": "^8.9.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.25.4",
@@ -79,12 +79,13 @@
}
},
"node_modules/@babel/code-frame": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
- "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==",
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+ "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
"dev": true,
"dependencies": {
- "@babel/highlight": "^7.16.7"
+ "@babel/highlight": "^7.22.13",
+ "chalk": "^2.4.2"
},
"engines": {
"node": ">=6.9.0"
@@ -130,9 +131,9 @@
}
},
"node_modules/@babel/core/node_modules/semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
@@ -188,28 +189,43 @@
}
},
"node_modules/@babel/eslint-parser/node_modules/semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@babel/generator": {
- "version": "7.17.10",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.10.tgz",
- "integrity": "sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
+ "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.17.10",
- "@jridgewell/gen-mapping": "^0.1.0",
+ "@babel/types": "^7.23.0",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
},
"engines": {
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
+ "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/@babel/helper-annotate-as-pure": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz",
@@ -254,9 +270,9 @@
}
},
"node_modules/@babel/helper-compilation-targets/node_modules/semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
@@ -319,22 +335,19 @@
}
},
"node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@babel/helper-environment-visitor": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz",
- "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
+ "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
"dev": true,
- "dependencies": {
- "@babel/types": "^7.16.7"
- },
"engines": {
"node": ">=6.9.0"
}
@@ -352,25 +365,25 @@
}
},
"node_modules/@babel/helper-function-name": {
- "version": "7.17.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz",
- "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
+ "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"dev": true,
"dependencies": {
- "@babel/template": "^7.16.7",
- "@babel/types": "^7.17.0"
+ "@babel/template": "^7.22.15",
+ "@babel/types": "^7.23.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-hoist-variables": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz",
- "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+ "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.16.7"
+ "@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
@@ -495,21 +508,30 @@
}
},
"node_modules/@babel/helper-split-export-declaration": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz",
- "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==",
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+ "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.16.7"
+ "@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
+ "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
- "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+ "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
"dev": true,
"engines": {
"node": ">=6.9.0"
@@ -554,13 +576,13 @@
}
},
"node_modules/@babel/highlight": {
- "version": "7.17.9",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz",
- "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
+ "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"dev": true,
"dependencies": {
- "@babel/helper-validator-identifier": "^7.16.7",
- "chalk": "^2.0.0",
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "chalk": "^2.4.2",
"js-tokens": "^4.0.0"
},
"engines": {
@@ -568,9 +590,9 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.17.10",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz",
- "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
+ "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"dev": true,
"bin": {
"parser": "bin/babel-parser.js"
@@ -1662,9 +1684,9 @@
}
},
"node_modules/@babel/preset-env/node_modules/semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
@@ -1718,33 +1740,33 @@
}
},
"node_modules/@babel/template": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
- "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==",
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+ "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
"dev": true,
"dependencies": {
- "@babel/code-frame": "^7.16.7",
- "@babel/parser": "^7.16.7",
- "@babel/types": "^7.16.7"
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.17.10",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.10.tgz",
- "integrity": "sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.16.7",
- "@babel/generator": "^7.17.10",
- "@babel/helper-environment-visitor": "^7.16.7",
- "@babel/helper-function-name": "^7.17.9",
- "@babel/helper-hoist-variables": "^7.16.7",
- "@babel/helper-split-export-declaration": "^7.16.7",
- "@babel/parser": "^7.17.10",
- "@babel/types": "^7.17.10",
+ "version": "7.23.2",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
+ "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/generator": "^7.23.0",
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-function-name": "^7.23.0",
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/parser": "^7.23.0",
+ "@babel/types": "^7.23.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@@ -1753,82 +1775,98 @@
}
},
"node_modules/@babel/types": {
- "version": "7.17.10",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.10.tgz",
- "integrity": "sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
+ "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"dev": true,
"dependencies": {
- "@babel/helper-validator-identifier": "^7.16.7",
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0"
},
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@cspotcode/source-map-consumer": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
- "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==",
+ "node_modules/@colors/colors": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
+ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
"dev": true,
+ "optional": true,
"engines": {
- "node": ">= 12"
+ "node": ">=0.1.90"
}
},
"node_modules/@cspotcode/source-map-support": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz",
- "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"dependencies": {
- "@cspotcode/source-map-consumer": "0.8.0"
+ "@jridgewell/trace-mapping": "0.3.9"
},
"engines": {
"node": ">=12"
}
},
+ "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
"node_modules/@cucumber/ci-environment": {
- "version": "9.0.4",
- "resolved": "https://registry.npmjs.org/@cucumber/ci-environment/-/ci-environment-9.0.4.tgz",
- "integrity": "sha512-da6H/wtVerhGUP4OCWTOmbNd4+gC1FhAcLzYgn6O68HgQbMwkmV3M8AwtbQWZkfF+Ph7z0M/UQYYdNIDu5V5MA==",
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/@cucumber/ci-environment/-/ci-environment-9.1.0.tgz",
+ "integrity": "sha512-jdnF6APXP3GawMue8kdMxhu6TBhyRUO4KDRxTowf06NtclLjIw2Ybpo9IcIOMvE8kHukvJyM00uxWX+CfS7JgQ==",
"dev": true
},
"node_modules/@cucumber/cucumber": {
- "version": "8.1.2",
- "resolved": "https://registry.npmjs.org/@cucumber/cucumber/-/cucumber-8.1.2.tgz",
- "integrity": "sha512-HaAkGa40P8YNCkT6D4hVNFdvTHL3eIJbZmvPI9XKszQA+A7tkBxKjHva8esI4dfdLeZuq5ksNkyjEiHobPxfIA==",
+ "version": "8.6.0",
+ "resolved": "https://registry.npmjs.org/@cucumber/cucumber/-/cucumber-8.6.0.tgz",
+ "integrity": "sha512-htkP/MlaYmgDId1Z2+7OQnH9aBd4Ui/Lk6PEmvMvP52ixPSUOv0MrP4/HUSECVXY0TI8GG7Ho03uLf6lieiFvw==",
"dev": true,
"dependencies": {
- "@cspotcode/source-map-support": "^0.7.0",
- "@cucumber/ci-environment": "9.0.4",
- "@cucumber/cucumber-expressions": "15.0.2",
- "@cucumber/gherkin": "23.0.1",
+ "@cspotcode/source-map-support": "^0.8.0",
+ "@cucumber/ci-environment": "9.1.0",
+ "@cucumber/cucumber-expressions": "16.0.0",
+ "@cucumber/gherkin": "24.0.0",
"@cucumber/gherkin-streams": "5.0.1",
- "@cucumber/gherkin-utils": "7.0.0",
- "@cucumber/html-formatter": "19.1.0",
+ "@cucumber/gherkin-utils": "8.0.0",
+ "@cucumber/html-formatter": "20.0.0",
"@cucumber/message-streams": "4.0.1",
- "@cucumber/messages": "18.0.0",
+ "@cucumber/messages": "19.1.2",
"@cucumber/tag-expressions": "4.1.0",
"assertion-error-formatter": "^3.0.0",
"capital-case": "^1.0.4",
"chalk": "^4.1.2",
- "cli-table3": "0.6.1",
+ "cli-table3": "0.6.2",
"commander": "^9.0.0",
+ "debug": "^4.3.4",
"duration": "^0.2.2",
"durations": "^3.4.2",
"figures": "^3.2.0",
"glob": "^7.1.6",
+ "has-ansi": "^4.0.1",
"indent-string": "^4.0.0",
+ "is-installed-globally": "^0.4.0",
"is-stream": "^2.0.0",
"knuth-shuffle-seeded": "^1.0.6",
"lodash.merge": "^4.6.2",
"lodash.mergewith": "^4.6.2",
"mz": "^2.7.0",
"progress": "^2.0.3",
- "resolve": "^1.19.0",
"resolve-pkg": "^2.0.0",
- "semver": "7.3.5",
+ "semver": "7.3.7",
"stack-chain": "^2.0.0",
"string-argv": "^0.3.1",
+ "strip-ansi": "6.0.1",
+ "supports-color": "^8.1.1",
"tmp": "^0.2.1",
"util-arity": "^1.1.0",
"verror": "^1.10.0",
@@ -1842,14 +1880,44 @@
}
},
"node_modules/@cucumber/cucumber-expressions": {
- "version": "15.0.2",
- "resolved": "https://registry.npmjs.org/@cucumber/cucumber-expressions/-/cucumber-expressions-15.0.2.tgz",
- "integrity": "sha512-ppN9JL1C5lw3InvM7WnoKZV9La5PW5Vr8c/8J0ZGzdlC8Y+PB7kskGzx7/tzl9kGjq7USQ7MZfwFz5el2sB/GA==",
+ "version": "16.0.0",
+ "resolved": "https://registry.npmjs.org/@cucumber/cucumber-expressions/-/cucumber-expressions-16.0.0.tgz",
+ "integrity": "sha512-HTh+Pg7oQ5aLuCkSbD2Q6jBaE40M3R/XaLEz+UqD5d9dZRu6P38W4LTooV5bV6dZgBunlMLK8+6ug2ziYvRddw==",
"dev": true,
"dependencies": {
"regexp-match-indices": "1.0.2"
}
},
+ "node_modules/@cucumber/cucumber/node_modules/@cucumber/gherkin": {
+ "version": "24.0.0",
+ "resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-24.0.0.tgz",
+ "integrity": "sha512-b7OsnvX1B8myDAKMc+RAiUX9bzgtNdjGsiMj10O13xu2HBWIOQ19EqBJ4xLO5CFG/lGk1J/+L0lANQVowxLVBg==",
+ "dev": true,
+ "dependencies": {
+ "@cucumber/messages": "^19.0.0"
+ }
+ },
+ "node_modules/@cucumber/cucumber/node_modules/@cucumber/messages": {
+ "version": "19.1.2",
+ "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-19.1.2.tgz",
+ "integrity": "sha512-vhWkNmQco+7tk/DWqpN0/R9KTNvsKsXVfZ7IsJs+dEeWmTuRztklHq8lJalwMSQBl71+2/KqGHzOO4BMTC9wIQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/uuid": "8.3.4",
+ "class-transformer": "0.5.1",
+ "reflect-metadata": "0.1.13",
+ "uuid": "8.3.2"
+ }
+ },
+ "node_modules/@cucumber/cucumber/node_modules/ansi-regex": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+ "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@cucumber/cucumber/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@@ -1881,6 +1949,18 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
+ "node_modules/@cucumber/cucumber/node_modules/chalk/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/@cucumber/cucumber/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -1900,14 +1980,26 @@
"dev": true
},
"node_modules/@cucumber/cucumber/node_modules/commander": {
- "version": "9.2.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz",
- "integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==",
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
+ "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
"dev": true,
"engines": {
"node": "^12.20.0 || >=14"
}
},
+ "node_modules/@cucumber/cucumber/node_modules/has-ansi": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-4.0.1.tgz",
+ "integrity": "sha512-Qr4RtTm30xvEdqUXbSBVWDu+PrTokJOwe/FU+VdfJPk+MXAPoeOzKpRyrDTnZIJwAkQ4oBLTU53nu0HrkF/Z2A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/@cucumber/cucumber/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -1939,9 +2031,9 @@
}
},
"node_modules/@cucumber/cucumber/node_modules/semver": {
- "version": "7.3.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
- "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
@@ -1954,15 +2046,18 @@
}
},
"node_modules/@cucumber/cucumber/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
"node_modules/@cucumber/cucumber/node_modules/tmp": {
@@ -1984,12 +2079,12 @@
"dev": true
},
"node_modules/@cucumber/gherkin": {
- "version": "23.0.1",
- "resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-23.0.1.tgz",
- "integrity": "sha512-WdSf1EfEajZ0ZYHPN6mX8Dl+jPgCLfnMPMq3rgYH6QOkHnBiQdsR0h6ahJj8iW5Zj2lZpMlW7SK7N1LW3c9YLQ==",
+ "version": "27.0.0",
+ "resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-27.0.0.tgz",
+ "integrity": "sha512-j5rCsjqzRiC3iVTier3sa0kzyNbkcAmF7xr7jKnyO7qDeK3Z8Ye1P3KSVpeQRMY+KCDJ3WbTDdyxH0FwfA/fIw==",
"dev": true,
"dependencies": {
- "@cucumber/messages": "^18.0.0"
+ "@cucumber/messages": ">=19.1.4 <=22"
}
},
"node_modules/@cucumber/gherkin-streams": {
@@ -2020,56 +2115,53 @@
}
},
"node_modules/@cucumber/gherkin-utils": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@cucumber/gherkin-utils/-/gherkin-utils-7.0.0.tgz",
- "integrity": "sha512-tDkSRITTPA6Df501doqeRH3+1jAM4ls6+tlFEVvkvuzTH3C8DXwQ5xBPWmUNmDhR/gJeZ+yj7gDRbDWr7Qc6Zw==",
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/@cucumber/gherkin-utils/-/gherkin-utils-8.0.0.tgz",
+ "integrity": "sha512-8uIZInEe3cO1cASmy3BA0PbVFUI+xWBnZAxmICbVOPsZaMB85MtESZLafzErgfRQPsHf6uYbVagP7MIjNPM5Jw==",
"dev": true,
"dependencies": {
- "@cucumber/messages": "^17.1.0",
+ "@cucumber/messages": "^19.0.0",
"@teppeis/multimaps": "2.0.0",
- "commander": "8.1.0"
+ "commander": "9.3.0"
},
"bin": {
"gherkin-utils": "bin/gherkin-utils"
}
},
"node_modules/@cucumber/gherkin-utils/node_modules/@cucumber/messages": {
- "version": "17.1.1",
- "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-17.1.1.tgz",
- "integrity": "sha512-KQMn2Ag+1g1CXp/zKQ7LLqmuHjuQwuXw0N2u5SrDk8r72zPt36SxmDSJK7w6HiFTI+3p5ZuzwLi4S5jop3Tx4g==",
+ "version": "19.1.4",
+ "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-19.1.4.tgz",
+ "integrity": "sha512-Pksl0pnDz2l1+L5Ug85NlG6LWrrklN9qkMxN5Mv+1XZ3T6u580dnE6mVaxjJRdcOq4tR17Pc0RqIDZMyVY1FlA==",
"dev": true,
"dependencies": {
- "@types/uuid": "8.3.1",
- "class-transformer": "0.4.0",
+ "@types/uuid": "8.3.4",
+ "class-transformer": "0.5.1",
"reflect-metadata": "0.1.13",
- "uuid": "8.3.2"
+ "uuid": "9.0.0"
}
},
- "node_modules/@cucumber/gherkin-utils/node_modules/@types/uuid": {
- "version": "8.3.1",
- "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.1.tgz",
- "integrity": "sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg==",
- "dev": true
- },
- "node_modules/@cucumber/gherkin-utils/node_modules/class-transformer": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.4.0.tgz",
- "integrity": "sha512-ETWD/H2TbWbKEi7m9N4Km5+cw1hNcqJSxlSYhsLsNjQzWWiZIYA1zafxpK9PwVfaZ6AqR5rrjPVUBGESm5tQUA==",
- "dev": true
- },
"node_modules/@cucumber/gherkin-utils/node_modules/commander": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-8.1.0.tgz",
- "integrity": "sha512-mf45ldcuHSYShkplHHGKWb4TrmwQadxOn7v4WuhDJy0ZVoY5JFajaRDKD0PNe5qXzBX0rhovjTnP6Kz9LETcuA==",
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz",
+ "integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==",
"dev": true,
"engines": {
- "node": ">= 12"
+ "node": "^12.20.0 || >=14"
+ }
+ },
+ "node_modules/@cucumber/gherkin-utils/node_modules/uuid": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
+ "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
+ "dev": true,
+ "bin": {
+ "uuid": "dist/bin/uuid"
}
},
"node_modules/@cucumber/html-formatter": {
- "version": "19.1.0",
- "resolved": "https://registry.npmjs.org/@cucumber/html-formatter/-/html-formatter-19.1.0.tgz",
- "integrity": "sha512-VCsRa34SNg9plfziFwOaoCSfsphHUb1Ivk8px8eLJc0rBFLDPDgJcHJtcufAu6AxFamGiptt2dt0XoqVq2Gr/Q==",
+ "version": "20.0.0",
+ "resolved": "https://registry.npmjs.org/@cucumber/html-formatter/-/html-formatter-20.0.0.tgz",
+ "integrity": "sha512-I6ZzUZ0CkaaPm6QHThoCRmdcuEIV9kJlNjaWvQ3PRkJm0OscQkQ0SXL/j73U30RDPiCAWwtq6ZSeQrgkTnSK+Q==",
"dev": true,
"peerDependencies": {
"@cucumber/messages": ">=18"
@@ -2085,15 +2177,24 @@
}
},
"node_modules/@cucumber/messages": {
- "version": "18.0.0",
- "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-18.0.0.tgz",
- "integrity": "sha512-1HmQwrscW0PNABwYB/pOgJms2e6DNZLvBNne3n2cllgxoVDzFgKiO94PIvpBZUaqMcj7FLhHaOyCnYZgK8vDFQ==",
+ "version": "21.0.1",
+ "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-21.0.1.tgz",
+ "integrity": "sha512-pGR7iURM4SF9Qp1IIpNiVQ77J9kfxMkPOEbyy+zRmGABnWWCsqMpJdfHeh9Mb3VskemVw85++e15JT0PYdcR3g==",
"dev": true,
"dependencies": {
"@types/uuid": "8.3.4",
"class-transformer": "0.5.1",
"reflect-metadata": "0.1.13",
- "uuid": "8.3.2"
+ "uuid": "9.0.0"
+ }
+ },
+ "node_modules/@cucumber/messages/node_modules/uuid": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
+ "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
+ "dev": true,
+ "bin": {
+ "uuid": "dist/bin/uuid"
}
},
"node_modules/@cucumber/tag-expressions": {
@@ -2269,9 +2370,9 @@
}
},
"node_modules/@jridgewell/resolve-uri": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.6.tgz",
- "integrity": "sha512-R7xHtBSNm+9SyvpJkdQl+qrM3Hm2fea3Ef197M3mUug+v+yR+Rhfbs7PBtcBUVnIWJ4JcAdjvij+c8hXS9p5aw==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
+ "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
"dev": true,
"engines": {
"node": ">=6.0.0"
@@ -2287,19 +2388,19 @@
}
},
"node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.12",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.12.tgz",
- "integrity": "sha512-az/NhpIwP3K33ILr0T2bso+k2E/SLf8Yidd8mHl0n6sCQ4YdyC8qDhZA6kOPDNDBA56ZnIjngVl0U3jREA0BUA==",
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
- "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "version": "0.3.20",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
+ "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
"dev": true,
"dependencies": {
- "@jridgewell/resolve-uri": "^3.0.3",
- "@jridgewell/sourcemap-codec": "^1.4.10"
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@nicolo-ribaudo/chokidar-2": {
@@ -2441,6 +2542,16 @@
"@types/node": "*"
}
},
+ "node_modules/@types/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==",
+ "dev": true,
+ "dependencies": {
+ "@types/minimatch": "^5.1.2",
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/http-cache-semantics": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
@@ -2559,6 +2670,12 @@
"integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==",
"dev": true
},
+ "node_modules/@types/minimatch": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
+ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
+ "dev": true
+ },
"node_modules/@types/mocha": {
"version": "9.1.1",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz",
@@ -2650,6 +2767,12 @@
"@types/node": "*"
}
},
+ "node_modules/@types/sinonjs__fake-timers": {
+ "version": "8.1.4",
+ "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.4.tgz",
+ "integrity": "sha512-GDV68H0mBSN449sa5HEj51E0wfpVQb8xNSMzxf/PrypMFcLTMwJMOM/cgXiv71Mq5drkOQmUGvL1okOZcu6RrQ==",
+ "dev": true
+ },
"node_modules/@types/stack-utils": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
@@ -2868,23 +2991,25 @@
}
},
"node_modules/@wdio/cucumber-framework": {
- "version": "7.19.7",
- "resolved": "https://registry.npmjs.org/@wdio/cucumber-framework/-/cucumber-framework-7.19.7.tgz",
- "integrity": "sha512-mV4MtioYiR2pEiuQbmVVcop3mFN+m/Ch1dviU8lLeGt8MbL1MR6LnlrDayTw6RC76hOYmziPo44yvrNrUJWBbQ==",
+ "version": "7.33.0",
+ "resolved": "https://registry.npmjs.org/@wdio/cucumber-framework/-/cucumber-framework-7.33.0.tgz",
+ "integrity": "sha512-/b6cn1IaB4bcvKL+B6CwEo65/es1e14gzuo8GdLxjEHJoOzWYf/y7Cs7cjzv2QyzaRevyKGfJmeJVt+dnfOO9Q==",
"dev": true,
"dependencies": {
- "@cucumber/cucumber": "8.1.2",
- "@cucumber/gherkin": "23.0.1",
+ "@cucumber/cucumber": "8.6.0",
+ "@cucumber/gherkin": "27.0.0",
"@cucumber/gherkin-streams": "^5.0.0",
- "@cucumber/messages": "18.0.0",
+ "@cucumber/messages": "21.0.1",
+ "@types/glob": "^8.1.0",
"@types/is-glob": "^4.0.1",
"@types/long": "^4.0.1",
"@types/mockery": "^1.4.29",
- "@wdio/logger": "7.19.0",
- "@wdio/types": "7.19.5",
- "@wdio/utils": "7.19.7",
+ "@types/sinonjs__fake-timers": "^8.1.2",
+ "@wdio/logger": "7.26.0",
+ "@wdio/types": "7.33.0",
+ "@wdio/utils": "7.33.0",
"expect-webdriverio": "^3.0.0",
- "glob": "^7.1.2",
+ "glob": "^8.0.3",
"is-glob": "^4.0.0",
"long": "^4.0.0",
"mockery": "^2.1.0"
@@ -2896,6 +3021,172 @@
"@wdio/cli": "^7.0.0"
}
},
+ "node_modules/@wdio/cucumber-framework/node_modules/@types/node": {
+ "version": "18.18.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.6.tgz",
+ "integrity": "sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==",
+ "dev": true
+ },
+ "node_modules/@wdio/cucumber-framework/node_modules/@wdio/logger": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.26.0.tgz",
+ "integrity": "sha512-kQj9s5JudAG9qB+zAAcYGPHVfATl2oqKgqj47yjehOQ1zzG33xmtL1ArFbQKWhDG32y1A8sN6b0pIqBEIwgg8Q==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "loglevel": "^1.6.0",
+ "loglevel-plugin-prefix": "^0.8.4",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@wdio/cucumber-framework/node_modules/@wdio/types": {
+ "version": "7.33.0",
+ "resolved": "https://registry.npmjs.org/@wdio/types/-/types-7.33.0.tgz",
+ "integrity": "sha512-tNcuN5Kl+i5CffaeTYV1omzAo4rVjiI1m9raIA8ph6iVteWdCzYv2/ImpGgFiBPb7Mf6VokU3+q9Slh5Jitaww==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "^18.0.0",
+ "got": "^11.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "typescript": "^4.6.2"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@wdio/cucumber-framework/node_modules/@wdio/utils": {
+ "version": "7.33.0",
+ "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-7.33.0.tgz",
+ "integrity": "sha512-4kQQ86EvEN6fBY5+u7M08cT6LfJtpk1rHd203xyxmbmV9lpNv/OCl4CsC+SD0jGT0aZZqYSIJ/Pil07pAh5K0g==",
+ "dev": true,
+ "dependencies": {
+ "@wdio/logger": "7.26.0",
+ "@wdio/types": "7.33.0",
+ "p-iteration": "^1.1.8"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@wdio/cucumber-framework/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@wdio/cucumber-framework/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@wdio/cucumber-framework/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@wdio/cucumber-framework/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@wdio/cucumber-framework/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/@wdio/cucumber-framework/node_modules/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@wdio/cucumber-framework/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@wdio/cucumber-framework/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@wdio/cucumber-framework/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/@wdio/junit-reporter": {
"version": "7.19.7",
"resolved": "https://registry.npmjs.org/@wdio/junit-reporter/-/junit-reporter-7.19.7.tgz",
@@ -3429,7 +3720,7 @@
"node_modules/any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
- "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
"dev": true
},
"node_modules/anymatch": {
@@ -3569,7 +3860,7 @@
"node_modules/assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
- "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
"dev": true,
"engines": {
"node": ">=0.8"
@@ -3651,9 +3942,9 @@
}
},
"node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
@@ -3810,9 +4101,9 @@
"dev": true
},
"node_modules/browserslist": {
- "version": "4.20.3",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz",
- "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==",
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
+ "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==",
"dev": true,
"funding": [
{
@@ -3822,14 +4113,17 @@
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
- "caniuse-lite": "^1.0.30001332",
- "electron-to-chromium": "^1.4.118",
- "escalade": "^3.1.1",
- "node-releases": "^2.0.3",
- "picocolors": "^1.0.0"
+ "caniuse-lite": "^1.0.30001541",
+ "electron-to-chromium": "^1.4.535",
+ "node-releases": "^2.0.13",
+ "update-browserslist-db": "^1.0.13"
},
"bin": {
"browserslist": "cli.js"
@@ -4031,9 +4325,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001335",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001335.tgz",
- "integrity": "sha512-ddP1Tgm7z2iIxu6QTtbZUv6HJxSaV/PZeSrWFZtbY4JZ69tOeNhBCl3HyRQgeNZKE5AOn1kpV7fhljigy0Ty3w==",
+ "version": "1.0.30001551",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001551.tgz",
+ "integrity": "sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg==",
"dev": true,
"funding": [
{
@@ -4043,6 +4337,10 @@
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
}
]
},
@@ -4141,9 +4439,9 @@
}
},
"node_modules/chromedriver": {
- "version": "116.0.0",
- "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-116.0.0.tgz",
- "integrity": "sha512-/TQaRn+RUAYnVqy5Vx8VtU8DvtWosU8QLM2u7BoNM5h55PRQPXF/onHAehEi8Sj/CehdKqH50NFdiumQAUr0DQ==",
+ "version": "118.0.1",
+ "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-118.0.1.tgz",
+ "integrity": "sha512-GlGfyRE47IuSJnuadIiDy89EMDMQFBVWxUmiclLJKzQhFsiWAtcIr/mNOxjljZdsw9IwIOQEkrB9wympKYFPLw==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
@@ -4159,7 +4457,7 @@
"chromedriver": "bin/chromedriver"
},
"engines": {
- "node": ">=16"
+ "node": ">=18"
}
},
"node_modules/class-transformer": {
@@ -4193,9 +4491,9 @@
}
},
"node_modules/cli-table3": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz",
- "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==",
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz",
+ "integrity": "sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==",
"dev": true,
"dependencies": {
"string-width": "^4.2.0"
@@ -4204,7 +4502,7 @@
"node": "10.* || >= 12.*"
},
"optionalDependencies": {
- "colors": "1.4.0"
+ "@colors/colors": "1.5.0"
}
},
"node_modules/cli-width": {
@@ -4274,16 +4572,6 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
- "node_modules/colors": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
- "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
- "dev": true,
- "optional": true,
- "engines": {
- "node": ">=0.1.90"
- }
- },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -4423,28 +4711,18 @@
"dev": true
},
"node_modules/core-js-compat": {
- "version": "3.22.4",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.22.4.tgz",
- "integrity": "sha512-dIWcsszDezkFZrfm1cnB4f/J85gyhiCpxbgBdohWCDtSVuAaChTSpPV7ldOQf/Xds2U5xCIJZOK82G4ZPAIswA==",
+ "version": "3.33.1",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.1.tgz",
+ "integrity": "sha512-6pYKNOgD/j/bkC5xS5IIg6bncid3rfrI42oBH1SQJbsmYPKF7rhzcFzYCcxYMmNQQ0rCEB8WqpW7QHndOggaeQ==",
"dev": true,
"dependencies": {
- "browserslist": "^4.20.3",
- "semver": "7.0.0"
+ "browserslist": "^4.22.1"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
},
- "node_modules/core-js-compat/node_modules/semver": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
- "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
- }
- },
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -4813,9 +5091,9 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.4.134",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.134.tgz",
- "integrity": "sha512-OdD7M2no4Mi8PopfvoOuNcwYDJ2mNFxaBfurA6okG3fLBaMcFah9S+si84FhX+FIWLKkdaiHfl4A+5ep/gOVrg==",
+ "version": "1.4.562",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.562.tgz",
+ "integrity": "sha512-kMGVZLP65O2/oH7zzaoIA5hcr4/xPYO6Sa83FrIpWcd7YPPtSlxqwxTd8lJIwKxaiXM6FGsYK4ukyJ40XkW7jg==",
"dev": true
},
"node_modules/emoji-regex": {
@@ -4912,9 +5190,9 @@
}
},
"node_modules/es5-ext": {
- "version": "0.10.61",
- "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz",
- "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==",
+ "version": "0.10.62",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
+ "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
@@ -4929,7 +5207,7 @@
"node_modules/es6-iterator": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
- "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
+ "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
"dev": true,
"dependencies": {
"d": "1",
@@ -5043,9 +5321,9 @@
}
},
"node_modules/eslint-config-airbnb-base/node_modules/semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
@@ -5586,18 +5864,18 @@
]
},
"node_modules/ext": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz",
- "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
+ "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
"dev": true,
"dependencies": {
- "type": "^2.5.0"
+ "type": "^2.7.2"
}
},
"node_modules/ext/node_modules/type": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz",
- "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==",
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz",
+ "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==",
"dev": true
},
"node_modules/external-editor": {
@@ -6056,6 +6334,21 @@
"node": ">= 6"
}
},
+ "node_modules/global-dirs": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz",
+ "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==",
+ "dev": true,
+ "dependencies": {
+ "ini": "2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
@@ -6266,9 +6559,9 @@
}
},
"node_modules/http-cache-semantics": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
- "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
"dev": true
},
"node_modules/http-errors": {
@@ -6524,6 +6817,15 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
+ "node_modules/ini": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz",
+ "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/inquirer": {
"version": "8.2.4",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz",
@@ -6782,6 +7084,22 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-installed-globally": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz",
+ "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==",
+ "dev": true,
+ "dependencies": {
+ "global-dirs": "^3.0.0",
+ "is-path-inside": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-interactive": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
@@ -6827,6 +7145,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-plain-obj": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
@@ -7518,7 +7845,7 @@
"node_modules/knuth-shuffle-seeded": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/knuth-shuffle-seeded/-/knuth-shuffle-seeded-1.0.6.tgz",
- "integrity": "sha1-AfG2VzOqdUDuCNiwF0Fk0iCB5OE=",
+ "integrity": "sha512-9pFH0SplrfyKyojCLxZfMcvkhf5hH0d+UwR9nTVJ/DDQJGuzcXjTwB7TP7sDfehSudlGGaOLblmEWqv04ERVWg==",
"dev": true,
"dependencies": {
"seed-random": "~2.2.0"
@@ -8402,9 +8729,9 @@
}
},
"node_modules/node-releases": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz",
- "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==",
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
+ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
"dev": true
},
"node_modules/normalize-package-data": {
@@ -8598,7 +8925,7 @@
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true,
"engines": {
"node": ">=0.10.0"
@@ -8901,7 +9228,7 @@
"node_modules/pad-right": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/pad-right/-/pad-right-0.2.2.tgz",
- "integrity": "sha1-b7ySQEXSRPKiokRQMGDTv8YAl3Q=",
+ "integrity": "sha512-4cy8M95ioIGolCoMmm2cMntGR1lPLEbOMzOKu8bzjuJP6JpzEMQcDHmh7hHLYGgob+nKe1YHFMaG4V59HQa89g==",
"dev": true,
"dependencies": {
"repeat-string": "^1.5.2"
@@ -9211,9 +9538,9 @@
}
},
"node_modules/property-expr": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz",
- "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
+ "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==",
"dev": true
},
"node_modules/proxy-addr": {
@@ -9567,9 +9894,9 @@
}
},
"node_modules/regexp-tree": {
- "version": "0.1.24",
- "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz",
- "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==",
+ "version": "0.1.27",
+ "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz",
+ "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==",
"dev": true,
"bin": {
"regexp-tree": "bin/regexp-tree"
@@ -9634,7 +9961,7 @@
"node_modules/repeat-string": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
- "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
"dev": true,
"engines": {
"node": ">=0.10"
@@ -9790,7 +10117,7 @@
"node_modules/seed-random": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/seed-random/-/seed-random-2.2.0.tgz",
- "integrity": "sha1-KpsZ4lCoFwmSMaW5mk2vgLf77VQ=",
+ "integrity": "sha512-34EQV6AAHQGhoc0tn/96a9Fsi6v2xdqe/dMUwljGRaFOzR3EgRmECvD0O8vi8X+/uQ50LGHfkNu/Eue5TPKZkQ==",
"dev": true
},
"node_modules/selenium-standalone": {
@@ -9846,9 +10173,9 @@
}
},
"node_modules/semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"bin": {
"semver": "bin/semver"
@@ -10159,9 +10486,9 @@
]
},
"node_modules/string-argv": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz",
- "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==",
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
+ "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
"dev": true,
"engines": {
"node": ">=0.6.19"
@@ -10368,7 +10695,7 @@
"node_modules/thenify-all": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
- "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
"dev": true,
"dependencies": {
"thenify": ">= 3.1.0 < 4"
@@ -10428,7 +10755,7 @@
"node_modules/toposort": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
- "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=",
+ "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==",
"dev": true
},
"node_modules/tr46": {
@@ -10645,6 +10972,36 @@
"node": ">= 0.8"
}
},
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.13",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
+ "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
"node_modules/upper-case-first": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz",
@@ -10672,7 +11029,7 @@
"node_modules/util-arity": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/util-arity/-/util-arity-1.1.0.tgz",
- "integrity": "sha1-WdAa8f2z/t4KxOYysKtfbOl8kzA=",
+ "integrity": "sha512-kkyIsXKwemfSy8ZEoaIz06ApApnWsk5hQO0vLjZS6UkBiGiW++Jsyb8vSBoc0WKlffGoGs5yYy/j5pp8zckrFA==",
"dev": true
},
"node_modules/util-deprecate": {
@@ -10750,7 +11107,7 @@
"node_modules/verror/node_modules/core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
"dev": true
},
"node_modules/wcwidth": {
@@ -10969,9 +11326,9 @@
}
},
"node_modules/word-wrap": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
- "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
@@ -11295,12 +11652,13 @@
}
},
"@babel/code-frame": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
- "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==",
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+ "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
"dev": true,
"requires": {
- "@babel/highlight": "^7.16.7"
+ "@babel/highlight": "^7.22.13",
+ "chalk": "^2.4.2"
}
},
"@babel/compat-data": {
@@ -11333,9 +11691,9 @@
},
"dependencies": {
"semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true
}
}
@@ -11374,22 +11732,36 @@
"dev": true
},
"semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true
}
}
},
"@babel/generator": {
- "version": "7.17.10",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.10.tgz",
- "integrity": "sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
+ "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"dev": true,
"requires": {
- "@babel/types": "^7.17.10",
- "@jridgewell/gen-mapping": "^0.1.0",
+ "@babel/types": "^7.23.0",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
+ },
+ "dependencies": {
+ "@jridgewell/gen-mapping": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
+ "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ }
}
},
"@babel/helper-annotate-as-pure": {
@@ -11424,9 +11796,9 @@
},
"dependencies": {
"semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true
}
}
@@ -11473,21 +11845,18 @@
},
"dependencies": {
"semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true
}
}
},
"@babel/helper-environment-visitor": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz",
- "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.16.7"
- }
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
+ "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
+ "dev": true
},
"@babel/helper-explode-assignable-expression": {
"version": "7.16.7",
@@ -11499,22 +11868,22 @@
}
},
"@babel/helper-function-name": {
- "version": "7.17.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz",
- "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
+ "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"dev": true,
"requires": {
- "@babel/template": "^7.16.7",
- "@babel/types": "^7.17.0"
+ "@babel/template": "^7.22.15",
+ "@babel/types": "^7.23.0"
}
},
"@babel/helper-hoist-variables": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz",
- "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+ "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
"dev": true,
"requires": {
- "@babel/types": "^7.16.7"
+ "@babel/types": "^7.22.5"
}
},
"@babel/helper-member-expression-to-functions": {
@@ -11609,18 +11978,24 @@
}
},
"@babel/helper-split-export-declaration": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz",
- "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==",
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+ "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"dev": true,
"requires": {
- "@babel/types": "^7.16.7"
+ "@babel/types": "^7.22.5"
}
},
+ "@babel/helper-string-parser": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
+ "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
+ "dev": true
+ },
"@babel/helper-validator-identifier": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
- "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+ "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
"dev": true
},
"@babel/helper-validator-option": {
@@ -11653,20 +12028,20 @@
}
},
"@babel/highlight": {
- "version": "7.17.9",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz",
- "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
+ "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"dev": true,
"requires": {
- "@babel/helper-validator-identifier": "^7.16.7",
- "chalk": "^2.0.0",
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "chalk": "^2.4.2",
"js-tokens": "^4.0.0"
}
},
"@babel/parser": {
- "version": "7.17.10",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz",
- "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
+ "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"dev": true
},
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
@@ -12389,9 +12764,9 @@
},
"dependencies": {
"semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true
}
}
@@ -12432,108 +12807,153 @@
}
},
"@babel/template": {
- "version": "7.16.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
- "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==",
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+ "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
"dev": true,
"requires": {
- "@babel/code-frame": "^7.16.7",
- "@babel/parser": "^7.16.7",
- "@babel/types": "^7.16.7"
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
}
},
"@babel/traverse": {
- "version": "7.17.10",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.10.tgz",
- "integrity": "sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.16.7",
- "@babel/generator": "^7.17.10",
- "@babel/helper-environment-visitor": "^7.16.7",
- "@babel/helper-function-name": "^7.17.9",
- "@babel/helper-hoist-variables": "^7.16.7",
- "@babel/helper-split-export-declaration": "^7.16.7",
- "@babel/parser": "^7.17.10",
- "@babel/types": "^7.17.10",
+ "version": "7.23.2",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
+ "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/generator": "^7.23.0",
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-function-name": "^7.23.0",
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/parser": "^7.23.0",
+ "@babel/types": "^7.23.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
- "version": "7.17.10",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.10.tgz",
- "integrity": "sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
+ "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"dev": true,
"requires": {
- "@babel/helper-validator-identifier": "^7.16.7",
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0"
}
},
- "@cspotcode/source-map-consumer": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
- "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==",
- "dev": true
+ "@colors/colors": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
+ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
+ "dev": true,
+ "optional": true
},
"@cspotcode/source-map-support": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz",
- "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"requires": {
- "@cspotcode/source-map-consumer": "0.8.0"
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
+ "dependencies": {
+ "@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ }
}
},
"@cucumber/ci-environment": {
- "version": "9.0.4",
- "resolved": "https://registry.npmjs.org/@cucumber/ci-environment/-/ci-environment-9.0.4.tgz",
- "integrity": "sha512-da6H/wtVerhGUP4OCWTOmbNd4+gC1FhAcLzYgn6O68HgQbMwkmV3M8AwtbQWZkfF+Ph7z0M/UQYYdNIDu5V5MA==",
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/@cucumber/ci-environment/-/ci-environment-9.1.0.tgz",
+ "integrity": "sha512-jdnF6APXP3GawMue8kdMxhu6TBhyRUO4KDRxTowf06NtclLjIw2Ybpo9IcIOMvE8kHukvJyM00uxWX+CfS7JgQ==",
"dev": true
},
"@cucumber/cucumber": {
- "version": "8.1.2",
- "resolved": "https://registry.npmjs.org/@cucumber/cucumber/-/cucumber-8.1.2.tgz",
- "integrity": "sha512-HaAkGa40P8YNCkT6D4hVNFdvTHL3eIJbZmvPI9XKszQA+A7tkBxKjHva8esI4dfdLeZuq5ksNkyjEiHobPxfIA==",
+ "version": "8.6.0",
+ "resolved": "https://registry.npmjs.org/@cucumber/cucumber/-/cucumber-8.6.0.tgz",
+ "integrity": "sha512-htkP/MlaYmgDId1Z2+7OQnH9aBd4Ui/Lk6PEmvMvP52ixPSUOv0MrP4/HUSECVXY0TI8GG7Ho03uLf6lieiFvw==",
"dev": true,
"requires": {
- "@cspotcode/source-map-support": "^0.7.0",
- "@cucumber/ci-environment": "9.0.4",
- "@cucumber/cucumber-expressions": "15.0.2",
- "@cucumber/gherkin": "23.0.1",
+ "@cspotcode/source-map-support": "^0.8.0",
+ "@cucumber/ci-environment": "9.1.0",
+ "@cucumber/cucumber-expressions": "16.0.0",
+ "@cucumber/gherkin": "24.0.0",
"@cucumber/gherkin-streams": "5.0.1",
- "@cucumber/gherkin-utils": "7.0.0",
- "@cucumber/html-formatter": "19.1.0",
+ "@cucumber/gherkin-utils": "8.0.0",
+ "@cucumber/html-formatter": "20.0.0",
"@cucumber/message-streams": "4.0.1",
- "@cucumber/messages": "18.0.0",
+ "@cucumber/messages": "19.1.2",
"@cucumber/tag-expressions": "4.1.0",
"assertion-error-formatter": "^3.0.0",
"capital-case": "^1.0.4",
"chalk": "^4.1.2",
- "cli-table3": "0.6.1",
+ "cli-table3": "0.6.2",
"commander": "^9.0.0",
+ "debug": "^4.3.4",
"duration": "^0.2.2",
"durations": "^3.4.2",
"figures": "^3.2.0",
"glob": "^7.1.6",
+ "has-ansi": "^4.0.1",
"indent-string": "^4.0.0",
+ "is-installed-globally": "^0.4.0",
"is-stream": "^2.0.0",
"knuth-shuffle-seeded": "^1.0.6",
"lodash.merge": "^4.6.2",
"lodash.mergewith": "^4.6.2",
"mz": "^2.7.0",
"progress": "^2.0.3",
- "resolve": "^1.19.0",
"resolve-pkg": "^2.0.0",
- "semver": "7.3.5",
+ "semver": "7.3.7",
"stack-chain": "^2.0.0",
"string-argv": "^0.3.1",
+ "strip-ansi": "6.0.1",
+ "supports-color": "^8.1.1",
"tmp": "^0.2.1",
"util-arity": "^1.1.0",
"verror": "^1.10.0",
"yup": "^0.32.11"
},
"dependencies": {
+ "@cucumber/gherkin": {
+ "version": "24.0.0",
+ "resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-24.0.0.tgz",
+ "integrity": "sha512-b7OsnvX1B8myDAKMc+RAiUX9bzgtNdjGsiMj10O13xu2HBWIOQ19EqBJ4xLO5CFG/lGk1J/+L0lANQVowxLVBg==",
+ "dev": true,
+ "requires": {
+ "@cucumber/messages": "^19.0.0"
+ }
+ },
+ "@cucumber/messages": {
+ "version": "19.1.2",
+ "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-19.1.2.tgz",
+ "integrity": "sha512-vhWkNmQco+7tk/DWqpN0/R9KTNvsKsXVfZ7IsJs+dEeWmTuRztklHq8lJalwMSQBl71+2/KqGHzOO4BMTC9wIQ==",
+ "dev": true,
+ "requires": {
+ "@types/uuid": "8.3.4",
+ "class-transformer": "0.5.1",
+ "reflect-metadata": "0.1.13",
+ "uuid": "8.3.2"
+ }
+ },
+ "ansi-regex": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+ "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
+ "dev": true
+ },
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@@ -12551,6 +12971,17 @@
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
}
},
"color-convert": {
@@ -12569,11 +13000,20 @@
"dev": true
},
"commander": {
- "version": "9.2.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-9.2.0.tgz",
- "integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==",
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
+ "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
"dev": true
},
+ "has-ansi": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-4.0.1.tgz",
+ "integrity": "sha512-Qr4RtTm30xvEdqUXbSBVWDu+PrTokJOwe/FU+VdfJPk+MXAPoeOzKpRyrDTnZIJwAkQ4oBLTU53nu0HrkF/Z2A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ },
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -12596,18 +13036,18 @@
}
},
"semver": {
- "version": "7.3.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
- "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
},
"supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
@@ -12631,21 +13071,21 @@
}
},
"@cucumber/cucumber-expressions": {
- "version": "15.0.2",
- "resolved": "https://registry.npmjs.org/@cucumber/cucumber-expressions/-/cucumber-expressions-15.0.2.tgz",
- "integrity": "sha512-ppN9JL1C5lw3InvM7WnoKZV9La5PW5Vr8c/8J0ZGzdlC8Y+PB7kskGzx7/tzl9kGjq7USQ7MZfwFz5el2sB/GA==",
+ "version": "16.0.0",
+ "resolved": "https://registry.npmjs.org/@cucumber/cucumber-expressions/-/cucumber-expressions-16.0.0.tgz",
+ "integrity": "sha512-HTh+Pg7oQ5aLuCkSbD2Q6jBaE40M3R/XaLEz+UqD5d9dZRu6P38W4LTooV5bV6dZgBunlMLK8+6ug2ziYvRddw==",
"dev": true,
"requires": {
"regexp-match-indices": "1.0.2"
}
},
"@cucumber/gherkin": {
- "version": "23.0.1",
- "resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-23.0.1.tgz",
- "integrity": "sha512-WdSf1EfEajZ0ZYHPN6mX8Dl+jPgCLfnMPMq3rgYH6QOkHnBiQdsR0h6ahJj8iW5Zj2lZpMlW7SK7N1LW3c9YLQ==",
+ "version": "27.0.0",
+ "resolved": "https://registry.npmjs.org/@cucumber/gherkin/-/gherkin-27.0.0.tgz",
+ "integrity": "sha512-j5rCsjqzRiC3iVTier3sa0kzyNbkcAmF7xr7jKnyO7qDeK3Z8Ye1P3KSVpeQRMY+KCDJ3WbTDdyxH0FwfA/fIw==",
"dev": true,
"requires": {
- "@cucumber/messages": "^18.0.0"
+ "@cucumber/messages": ">=19.1.4 <=22"
}
},
"@cucumber/gherkin-streams": {
@@ -12667,52 +13107,46 @@
}
},
"@cucumber/gherkin-utils": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@cucumber/gherkin-utils/-/gherkin-utils-7.0.0.tgz",
- "integrity": "sha512-tDkSRITTPA6Df501doqeRH3+1jAM4ls6+tlFEVvkvuzTH3C8DXwQ5xBPWmUNmDhR/gJeZ+yj7gDRbDWr7Qc6Zw==",
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/@cucumber/gherkin-utils/-/gherkin-utils-8.0.0.tgz",
+ "integrity": "sha512-8uIZInEe3cO1cASmy3BA0PbVFUI+xWBnZAxmICbVOPsZaMB85MtESZLafzErgfRQPsHf6uYbVagP7MIjNPM5Jw==",
"dev": true,
"requires": {
- "@cucumber/messages": "^17.1.0",
+ "@cucumber/messages": "^19.0.0",
"@teppeis/multimaps": "2.0.0",
- "commander": "8.1.0"
+ "commander": "9.3.0"
},
"dependencies": {
"@cucumber/messages": {
- "version": "17.1.1",
- "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-17.1.1.tgz",
- "integrity": "sha512-KQMn2Ag+1g1CXp/zKQ7LLqmuHjuQwuXw0N2u5SrDk8r72zPt36SxmDSJK7w6HiFTI+3p5ZuzwLi4S5jop3Tx4g==",
+ "version": "19.1.4",
+ "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-19.1.4.tgz",
+ "integrity": "sha512-Pksl0pnDz2l1+L5Ug85NlG6LWrrklN9qkMxN5Mv+1XZ3T6u580dnE6mVaxjJRdcOq4tR17Pc0RqIDZMyVY1FlA==",
"dev": true,
"requires": {
- "@types/uuid": "8.3.1",
- "class-transformer": "0.4.0",
+ "@types/uuid": "8.3.4",
+ "class-transformer": "0.5.1",
"reflect-metadata": "0.1.13",
- "uuid": "8.3.2"
+ "uuid": "9.0.0"
}
},
- "@types/uuid": {
- "version": "8.3.1",
- "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.1.tgz",
- "integrity": "sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg==",
- "dev": true
- },
- "class-transformer": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.4.0.tgz",
- "integrity": "sha512-ETWD/H2TbWbKEi7m9N4Km5+cw1hNcqJSxlSYhsLsNjQzWWiZIYA1zafxpK9PwVfaZ6AqR5rrjPVUBGESm5tQUA==",
+ "commander": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz",
+ "integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==",
"dev": true
},
- "commander": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-8.1.0.tgz",
- "integrity": "sha512-mf45ldcuHSYShkplHHGKWb4TrmwQadxOn7v4WuhDJy0ZVoY5JFajaRDKD0PNe5qXzBX0rhovjTnP6Kz9LETcuA==",
+ "uuid": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
+ "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
"dev": true
}
}
},
"@cucumber/html-formatter": {
- "version": "19.1.0",
- "resolved": "https://registry.npmjs.org/@cucumber/html-formatter/-/html-formatter-19.1.0.tgz",
- "integrity": "sha512-VCsRa34SNg9plfziFwOaoCSfsphHUb1Ivk8px8eLJc0rBFLDPDgJcHJtcufAu6AxFamGiptt2dt0XoqVq2Gr/Q==",
+ "version": "20.0.0",
+ "resolved": "https://registry.npmjs.org/@cucumber/html-formatter/-/html-formatter-20.0.0.tgz",
+ "integrity": "sha512-I6ZzUZ0CkaaPm6QHThoCRmdcuEIV9kJlNjaWvQ3PRkJm0OscQkQ0SXL/j73U30RDPiCAWwtq6ZSeQrgkTnSK+Q==",
"dev": true,
"requires": {}
},
@@ -12724,15 +13158,23 @@
"requires": {}
},
"@cucumber/messages": {
- "version": "18.0.0",
- "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-18.0.0.tgz",
- "integrity": "sha512-1HmQwrscW0PNABwYB/pOgJms2e6DNZLvBNne3n2cllgxoVDzFgKiO94PIvpBZUaqMcj7FLhHaOyCnYZgK8vDFQ==",
+ "version": "21.0.1",
+ "resolved": "https://registry.npmjs.org/@cucumber/messages/-/messages-21.0.1.tgz",
+ "integrity": "sha512-pGR7iURM4SF9Qp1IIpNiVQ77J9kfxMkPOEbyy+zRmGABnWWCsqMpJdfHeh9Mb3VskemVw85++e15JT0PYdcR3g==",
"dev": true,
"requires": {
"@types/uuid": "8.3.4",
"class-transformer": "0.5.1",
"reflect-metadata": "0.1.13",
- "uuid": "8.3.2"
+ "uuid": "9.0.0"
+ },
+ "dependencies": {
+ "uuid": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
+ "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
+ "dev": true
+ }
}
},
"@cucumber/tag-expressions": {
@@ -12867,9 +13309,9 @@
}
},
"@jridgewell/resolve-uri": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.6.tgz",
- "integrity": "sha512-R7xHtBSNm+9SyvpJkdQl+qrM3Hm2fea3Ef197M3mUug+v+yR+Rhfbs7PBtcBUVnIWJ4JcAdjvij+c8hXS9p5aw==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
+ "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
"dev": true
},
"@jridgewell/set-array": {
@@ -12879,19 +13321,19 @@
"dev": true
},
"@jridgewell/sourcemap-codec": {
- "version": "1.4.12",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.12.tgz",
- "integrity": "sha512-az/NhpIwP3K33ILr0T2bso+k2E/SLf8Yidd8mHl0n6sCQ4YdyC8qDhZA6kOPDNDBA56ZnIjngVl0U3jREA0BUA==",
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true
},
"@jridgewell/trace-mapping": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
- "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "version": "0.3.20",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
+ "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
"dev": true,
"requires": {
- "@jridgewell/resolve-uri": "^3.0.3",
- "@jridgewell/sourcemap-codec": "^1.4.10"
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"@nicolo-ribaudo/chokidar-2": {
@@ -13021,6 +13463,16 @@
"@types/node": "*"
}
},
+ "@types/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==",
+ "dev": true,
+ "requires": {
+ "@types/minimatch": "^5.1.2",
+ "@types/node": "*"
+ }
+ },
"@types/http-cache-semantics": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
@@ -13139,6 +13591,12 @@
"integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==",
"dev": true
},
+ "@types/minimatch": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
+ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
+ "dev": true
+ },
"@types/mocha": {
"version": "9.1.1",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz",
@@ -13230,6 +13688,12 @@
"@types/node": "*"
}
},
+ "@types/sinonjs__fake-timers": {
+ "version": "8.1.4",
+ "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.4.tgz",
+ "integrity": "sha512-GDV68H0mBSN449sa5HEj51E0wfpVQb8xNSMzxf/PrypMFcLTMwJMOM/cgXiv71Mq5drkOQmUGvL1okOZcu6RrQ==",
+ "dev": true
+ },
"@types/stack-utils": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
@@ -13420,26 +13884,149 @@
}
},
"@wdio/cucumber-framework": {
- "version": "7.19.7",
- "resolved": "https://registry.npmjs.org/@wdio/cucumber-framework/-/cucumber-framework-7.19.7.tgz",
- "integrity": "sha512-mV4MtioYiR2pEiuQbmVVcop3mFN+m/Ch1dviU8lLeGt8MbL1MR6LnlrDayTw6RC76hOYmziPo44yvrNrUJWBbQ==",
+ "version": "7.33.0",
+ "resolved": "https://registry.npmjs.org/@wdio/cucumber-framework/-/cucumber-framework-7.33.0.tgz",
+ "integrity": "sha512-/b6cn1IaB4bcvKL+B6CwEo65/es1e14gzuo8GdLxjEHJoOzWYf/y7Cs7cjzv2QyzaRevyKGfJmeJVt+dnfOO9Q==",
"dev": true,
"requires": {
- "@cucumber/cucumber": "8.1.2",
- "@cucumber/gherkin": "23.0.1",
+ "@cucumber/cucumber": "8.6.0",
+ "@cucumber/gherkin": "27.0.0",
"@cucumber/gherkin-streams": "^5.0.0",
- "@cucumber/messages": "18.0.0",
+ "@cucumber/messages": "21.0.1",
+ "@types/glob": "^8.1.0",
"@types/is-glob": "^4.0.1",
"@types/long": "^4.0.1",
"@types/mockery": "^1.4.29",
- "@wdio/logger": "7.19.0",
- "@wdio/types": "7.19.5",
- "@wdio/utils": "7.19.7",
+ "@types/sinonjs__fake-timers": "^8.1.2",
+ "@wdio/logger": "7.26.0",
+ "@wdio/types": "7.33.0",
+ "@wdio/utils": "7.33.0",
"expect-webdriverio": "^3.0.0",
- "glob": "^7.1.2",
+ "glob": "^8.0.3",
"is-glob": "^4.0.0",
"long": "^4.0.0",
"mockery": "^2.1.0"
+ },
+ "dependencies": {
+ "@types/node": {
+ "version": "18.18.6",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.6.tgz",
+ "integrity": "sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==",
+ "dev": true
+ },
+ "@wdio/logger": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-7.26.0.tgz",
+ "integrity": "sha512-kQj9s5JudAG9qB+zAAcYGPHVfATl2oqKgqj47yjehOQ1zzG33xmtL1ArFbQKWhDG32y1A8sN6b0pIqBEIwgg8Q==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.0.0",
+ "loglevel": "^1.6.0",
+ "loglevel-plugin-prefix": "^0.8.4",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "@wdio/types": {
+ "version": "7.33.0",
+ "resolved": "https://registry.npmjs.org/@wdio/types/-/types-7.33.0.tgz",
+ "integrity": "sha512-tNcuN5Kl+i5CffaeTYV1omzAo4rVjiI1m9raIA8ph6iVteWdCzYv2/ImpGgFiBPb7Mf6VokU3+q9Slh5Jitaww==",
+ "dev": true,
+ "requires": {
+ "@types/node": "^18.0.0",
+ "got": "^11.8.1"
+ }
+ },
+ "@wdio/utils": {
+ "version": "7.33.0",
+ "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-7.33.0.tgz",
+ "integrity": "sha512-4kQQ86EvEN6fBY5+u7M08cT6LfJtpk1rHd203xyxmbmV9lpNv/OCl4CsC+SD0jGT0aZZqYSIJ/Pil07pAh5K0g==",
+ "dev": true,
+ "requires": {
+ "@wdio/logger": "7.26.0",
+ "@wdio/types": "7.33.0",
+ "p-iteration": "^1.1.8"
+ }
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
}
},
"@wdio/junit-reporter": {
@@ -13839,7 +14426,7 @@
"any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
- "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
"dev": true
},
"anymatch": {
@@ -13957,7 +14544,7 @@
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
- "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
"dev": true
},
"assertion-error-formatter": {
@@ -14027,9 +14614,9 @@
},
"dependencies": {
"semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true
}
}
@@ -14154,16 +14741,15 @@
"dev": true
},
"browserslist": {
- "version": "4.20.3",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz",
- "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==",
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
+ "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==",
"dev": true,
"requires": {
- "caniuse-lite": "^1.0.30001332",
- "electron-to-chromium": "^1.4.118",
- "escalade": "^3.1.1",
- "node-releases": "^2.0.3",
- "picocolors": "^1.0.0"
+ "caniuse-lite": "^1.0.30001541",
+ "electron-to-chromium": "^1.4.535",
+ "node-releases": "^2.0.13",
+ "update-browserslist-db": "^1.0.13"
}
},
"buffer": {
@@ -14305,9 +14891,9 @@
}
},
"caniuse-lite": {
- "version": "1.0.30001335",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001335.tgz",
- "integrity": "sha512-ddP1Tgm7z2iIxu6QTtbZUv6HJxSaV/PZeSrWFZtbY4JZ69tOeNhBCl3HyRQgeNZKE5AOn1kpV7fhljigy0Ty3w==",
+ "version": "1.0.30001551",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001551.tgz",
+ "integrity": "sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg==",
"dev": true
},
"capital-case": {
@@ -14381,9 +14967,9 @@
}
},
"chromedriver": {
- "version": "116.0.0",
- "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-116.0.0.tgz",
- "integrity": "sha512-/TQaRn+RUAYnVqy5Vx8VtU8DvtWosU8QLM2u7BoNM5h55PRQPXF/onHAehEi8Sj/CehdKqH50NFdiumQAUr0DQ==",
+ "version": "118.0.1",
+ "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-118.0.1.tgz",
+ "integrity": "sha512-GlGfyRE47IuSJnuadIiDy89EMDMQFBVWxUmiclLJKzQhFsiWAtcIr/mNOxjljZdsw9IwIOQEkrB9wympKYFPLw==",
"dev": true,
"requires": {
"@testim/chrome-version": "^1.1.3",
@@ -14417,12 +15003,12 @@
"dev": true
},
"cli-table3": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz",
- "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==",
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz",
+ "integrity": "sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==",
"dev": true,
"requires": {
- "colors": "1.4.0",
+ "@colors/colors": "1.5.0",
"string-width": "^4.2.0"
}
},
@@ -14484,13 +15070,6 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
- "colors": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
- "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
- "dev": true,
- "optional": true
- },
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -14597,21 +15176,12 @@
"dev": true
},
"core-js-compat": {
- "version": "3.22.4",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.22.4.tgz",
- "integrity": "sha512-dIWcsszDezkFZrfm1cnB4f/J85gyhiCpxbgBdohWCDtSVuAaChTSpPV7ldOQf/Xds2U5xCIJZOK82G4ZPAIswA==",
+ "version": "3.33.1",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.1.tgz",
+ "integrity": "sha512-6pYKNOgD/j/bkC5xS5IIg6bncid3rfrI42oBH1SQJbsmYPKF7rhzcFzYCcxYMmNQQ0rCEB8WqpW7QHndOggaeQ==",
"dev": true,
"requires": {
- "browserslist": "^4.20.3",
- "semver": "7.0.0"
- },
- "dependencies": {
- "semver": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
- "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
- "dev": true
- }
+ "browserslist": "^4.22.1"
}
},
"core-util-is": {
@@ -14893,9 +15463,9 @@
}
},
"electron-to-chromium": {
- "version": "1.4.134",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.134.tgz",
- "integrity": "sha512-OdD7M2no4Mi8PopfvoOuNcwYDJ2mNFxaBfurA6okG3fLBaMcFah9S+si84FhX+FIWLKkdaiHfl4A+5ep/gOVrg==",
+ "version": "1.4.562",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.562.tgz",
+ "integrity": "sha512-kMGVZLP65O2/oH7zzaoIA5hcr4/xPYO6Sa83FrIpWcd7YPPtSlxqwxTd8lJIwKxaiXM6FGsYK4ukyJ40XkW7jg==",
"dev": true
},
"emoji-regex": {
@@ -14977,9 +15547,9 @@
}
},
"es5-ext": {
- "version": "0.10.61",
- "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz",
- "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==",
+ "version": "0.10.62",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
+ "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
"dev": true,
"requires": {
"es6-iterator": "^2.0.3",
@@ -14990,7 +15560,7 @@
"es6-iterator": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
- "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
+ "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
"dev": true,
"requires": {
"d": "1",
@@ -15186,9 +15756,9 @@
},
"dependencies": {
"semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true
}
}
@@ -15504,18 +16074,18 @@
}
},
"ext": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz",
- "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
+ "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
"dev": true,
"requires": {
- "type": "^2.5.0"
+ "type": "^2.7.2"
},
"dependencies": {
"type": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz",
- "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==",
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz",
+ "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==",
"dev": true
}
}
@@ -15866,6 +16436,15 @@
"is-glob": "^4.0.1"
}
},
+ "global-dirs": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz",
+ "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==",
+ "dev": true,
+ "requires": {
+ "ini": "2.0.0"
+ }
+ },
"globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
@@ -16023,9 +16602,9 @@
}
},
"http-cache-semantics": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
- "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
"dev": true
},
"http-errors": {
@@ -16211,6 +16790,12 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
+ "ini": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz",
+ "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==",
+ "dev": true
+ },
"inquirer": {
"version": "8.2.4",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz",
@@ -16393,6 +16978,16 @@
"is-extglob": "^2.1.1"
}
},
+ "is-installed-globally": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz",
+ "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==",
+ "dev": true,
+ "requires": {
+ "global-dirs": "^3.0.0",
+ "is-path-inside": "^3.0.2"
+ }
+ },
"is-interactive": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
@@ -16420,6 +17015,12 @@
"has-tostringtag": "^1.0.0"
}
},
+ "is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true
+ },
"is-plain-obj": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
@@ -16933,7 +17534,7 @@
"knuth-shuffle-seeded": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/knuth-shuffle-seeded/-/knuth-shuffle-seeded-1.0.6.tgz",
- "integrity": "sha1-AfG2VzOqdUDuCNiwF0Fk0iCB5OE=",
+ "integrity": "sha512-9pFH0SplrfyKyojCLxZfMcvkhf5hH0d+UwR9nTVJ/DDQJGuzcXjTwB7TP7sDfehSudlGGaOLblmEWqv04ERVWg==",
"dev": true,
"requires": {
"seed-random": "~2.2.0"
@@ -17635,9 +18236,9 @@
}
},
"node-releases": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz",
- "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==",
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
+ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
"dev": true
},
"normalize-package-data": {
@@ -17783,7 +18384,7 @@
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true
},
"object-inspect": {
@@ -17998,7 +18599,7 @@
"pad-right": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/pad-right/-/pad-right-0.2.2.tgz",
- "integrity": "sha1-b7ySQEXSRPKiokRQMGDTv8YAl3Q=",
+ "integrity": "sha512-4cy8M95ioIGolCoMmm2cMntGR1lPLEbOMzOKu8bzjuJP6JpzEMQcDHmh7hHLYGgob+nKe1YHFMaG4V59HQa89g==",
"dev": true,
"requires": {
"repeat-string": "^1.5.2"
@@ -18230,9 +18831,9 @@
"dev": true
},
"property-expr": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz",
- "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==",
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
+ "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==",
"dev": true
},
"proxy-addr": {
@@ -18524,9 +19125,9 @@
}
},
"regexp-tree": {
- "version": "0.1.24",
- "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz",
- "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==",
+ "version": "0.1.27",
+ "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz",
+ "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==",
"dev": true
},
"regexpp": {
@@ -18575,7 +19176,7 @@
"repeat-string": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
- "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
"dev": true
},
"require-directory": {
@@ -18701,7 +19302,7 @@
"seed-random": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/seed-random/-/seed-random-2.2.0.tgz",
- "integrity": "sha1-KpsZ4lCoFwmSMaW5mk2vgLf77VQ=",
+ "integrity": "sha512-34EQV6AAHQGhoc0tn/96a9Fsi6v2xdqe/dMUwljGRaFOzR3EgRmECvD0O8vi8X+/uQ50LGHfkNu/Eue5TPKZkQ==",
"dev": true
},
"selenium-standalone": {
@@ -18746,9 +19347,9 @@
}
},
"semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true
},
"send": {
@@ -19001,9 +19602,9 @@
}
},
"string-argv": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz",
- "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==",
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
+ "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
"dev": true
},
"string-width": {
@@ -19159,7 +19760,7 @@
"thenify-all": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
- "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
"dev": true,
"requires": {
"thenify": ">= 3.1.0 < 4"
@@ -19204,7 +19805,7 @@
"toposort": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
- "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=",
+ "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==",
"dev": true
},
"tr46": {
@@ -19361,6 +19962,16 @@
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
"dev": true
},
+ "update-browserslist-db": {
+ "version": "1.0.13",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
+ "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
+ "dev": true,
+ "requires": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ }
+ },
"upper-case-first": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz",
@@ -19388,7 +19999,7 @@
"util-arity": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/util-arity/-/util-arity-1.1.0.tgz",
- "integrity": "sha1-WdAa8f2z/t4KxOYysKtfbOl8kzA=",
+ "integrity": "sha512-kkyIsXKwemfSy8ZEoaIz06ApApnWsk5hQO0vLjZS6UkBiGiW++Jsyb8vSBoc0WKlffGoGs5yYy/j5pp8zckrFA==",
"dev": true
},
"util-deprecate": {
@@ -19451,7 +20062,7 @@
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
"dev": true
}
}
@@ -19631,9 +20242,9 @@
}
},
"word-wrap": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
- "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true
},
"workerpool": {
diff --git a/tests/package.json b/tests/package.json
index 2ca9dc0bea..816417f307 100644
--- a/tests/package.json
+++ b/tests/package.json
@@ -42,7 +42,7 @@
"npm-run-all": "^4.1.5",
"wdio-chromedriver-service": "^7.3.1",
"webdriverio": "^7.16.15",
- "chromedriver": "^116.0.0"
+ "chromedriver": "^118.0.0"
},
"dependencies": {
"typescript": "^4.9.5"
diff --git a/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesDailyModelCycle.feature b/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesDailyModelCycle.feature
index a114b0f02a..261bf55923 100644
--- a/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesDailyModelCycle.feature
+++ b/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesDailyModelCycle.feature
@@ -24,8 +24,8 @@ Feature: Match Unmatch Diff Curves DailyModelCycle
When I click the "Add Curve" button
Then "Curve0" is added
- When I change the "data-source" parameter to "RAP_OPS_130"
- Then the "data-source" parameter value matches "RAP_OPS_130"
+ When I change the "variable" parameter to "Visibility"
+ Then the "variable" parameter value matches "Visibility"
When I click the "Add Curve" button
Then "Curve1" is added
And I should see a list of curves containing "Curve0,Curve1"
diff --git a/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesDieoff.feature b/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesDieoff.feature
index 937db5932d..85bee29782 100644
--- a/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesDieoff.feature
+++ b/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesDieoff.feature
@@ -26,8 +26,8 @@ Feature: Match Unmatch Diff Curves Dieoff
When I click the "Add Curve" button
Then "Curve0" is added
- When I change the "data-source" parameter to "RAP_OPS_130"
- Then the "data-source" parameter value matches "RAP_OPS_130"
+ When I change the "variable" parameter to "Visibility"
+ Then the "variable" parameter value matches "Visibility"
When I click the "Add Curve" button
Then "Curve1" is added
And I should see a list of curves containing "Curve0,Curve1"
diff --git a/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesHistogram.feature b/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesHistogram.feature
index c32601d27f..20a0b444e9 100644
--- a/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesHistogram.feature
+++ b/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesHistogram.feature
@@ -24,8 +24,8 @@ Feature: Match Unmatch Diff Curves Histogram
When I click the "Add Curve" button
Then "Curve0" is added
- When I change the "data-source" parameter to "RAP_OPS_130"
- Then the "data-source" parameter value matches "RAP_OPS_130"
+ When I change the "variable" parameter to "Visibility"
+ Then the "variable" parameter value matches "Visibility"
When I click the "Add Curve" button
Then "Curve1" is added
And I should see a list of curves containing "Curve0,Curve1"
diff --git a/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesThreshold.feature b/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesThreshold.feature
index 343b5d7c73..2208f2114b 100644
--- a/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesThreshold.feature
+++ b/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesThreshold.feature
@@ -24,8 +24,8 @@ Feature: Match Unmatch Diff Curves Threshold
When I click the "Add Curve" button
Then "Curve0" is added
- When I change the "data-source" parameter to "RAP_OPS_130"
- Then the "data-source" parameter value matches "RAP_OPS_130"
+ When I change the "variable" parameter to "Visibility"
+ Then the "variable" parameter value matches "Visibility"
When I click the "Add Curve" button
Then "Curve1" is added
And I should see a list of curves containing "Curve0,Curve1"
diff --git a/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesTimeseries.feature b/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesTimeseries.feature
index d261dd1b7f..76d0efd63d 100644
--- a/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesTimeseries.feature
+++ b/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesTimeseries.feature
@@ -24,8 +24,8 @@ Feature: Match Unmatch Diff Curves Timeseries
When I click the "Add Curve" button
Then "Curve0" is added
- When I change the "data-source" parameter to "RAP_OPS_130"
- Then the "data-source" parameter value matches "RAP_OPS_130"
+ When I change the "variable" parameter to "Visibility"
+ Then the "variable" parameter value matches "Visibility"
When I click the "Add Curve" button
Then "Curve1" is added
And I should see a list of curves containing "Curve0,Curve1"
diff --git a/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesValidTime.feature b/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesValidTime.feature
index c92eb229a4..70b225a77e 100644
--- a/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesValidTime.feature
+++ b/tests/src/features/cb-metar/basic/matchUnmatchDiffCurvesValidTime.feature
@@ -24,8 +24,8 @@ Feature: Match Unmatch Diff Curves Valid Time
When I click the "Add Curve" button
Then "Curve0" is added
- When I change the "data-source" parameter to "RAP_OPS_130"
- Then the "data-source" parameter value matches "RAP_OPS_130"
+ When I change the "variable" parameter to "Visibility"
+ Then the "variable" parameter value matches "Visibility"
When I click the "Add Curve" button
Then "Curve1" is added
And I should see a list of curves containing "Curve0,Curve1"