Skip to content

Commit

Permalink
fully linted scorecard
Browse files Browse the repository at this point in the history
  • Loading branch information
mollybsmith-noaa committed Nov 10, 2023
1 parent 41f2d87 commit 4e52500
Show file tree
Hide file tree
Showing 12 changed files with 1,012 additions and 808 deletions.
4 changes: 1 addition & 3 deletions apps/ensemble/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,11 @@
"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",
"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"
}
}
1 change: 1 addition & 0 deletions apps/ensemble/client/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
299 changes: 169 additions & 130 deletions apps/ensemble/server/dataFunctions/data_contour.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -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" &&
Expand All @@ -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: <br>${queryResult.error}<br> query: <br>${statement}<br>`;
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: <br>${queryResult.error}<br> query: <br>${statement}<br>`;
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
Expand Down
Loading

0 comments on commit 4e52500

Please sign in to comment.