Skip to content

Commit

Permalink
Y2Y can now plot RI stats
Browse files Browse the repository at this point in the history
  • Loading branch information
mollybsmith-noaa committed Jun 12, 2024
1 parent 9754000 commit 777315d
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 43 deletions.
129 changes: 86 additions & 43 deletions apps/met-cyclone/server/dataFunctions/data_yeartoyear.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,31 +52,89 @@ dataYearToYear = function (plotParams, plotFunction) {
const database = curve.database.replace(/___/g, ".");
const model = matsCollections["data-source"].findOne({ name: "data-source" })
.optionsMap[database][curve["data-source"]][0];
const modelClause = `and h.amodel = '${model}'`;
let modelClause; // the model field in mysql is called different things for RI and non-RI stats

const truthStr = curve.truth;
const truth = Object.keys(
matsCollections.truth.findOne({ name: "truth" }).valuesMap
).find(
(key) =>
matsCollections.truth.findOne({ name: "truth" }).valuesMap[key] === truthStr
);
let truthClause; // the truth field in mysql is called different things for RI and non-RI stats

const selectorPlotType = curve["plot-type"];
const { statistic } = curve;
let { statistic } = curve;
const statisticOptionsMap = matsCollections.statistic.findOne(
{ name: "statistic" },
{ optionsMap: 1 }
).optionsMap[database][curve["data-source"]][selectorPlotType];
const statLineType = statisticOptionsMap[statistic][0];
let statisticClause = "";
let statHeaderType = "";
let lineDataType = "";
if (statLineType === "precalculated") {

const { basin } = curve;
let variableClause = "";
let thresholdClause = "";
let stormClause = "";
let levelsClause = "";
if (statLineType === "ctc") {
// set up fields specific to ctc scores
statisticClause =
"sum(ld.fy_oy) as fy_oy, " +
"sum(ld.fy_on) as fy_on, " +
"sum(ld.fn_oy) as fn_oy, " +
"sum(ld.fn_on) as fn_on, " +
"group_concat(distinct ld.fy_oy, ';', ld.fy_on, ';', ld.fn_oy, ';', ld.fn_on, ';', ld.total, ';', unix_timestamp(ld.fcst_valid), ';', h.fcst_lev order by unix_timestamp(ld.fcst_valid), h.fcst_lev) as sub_data";
statHeaderType = "stat_header";
lineDataType = "line_data_ctc";
modelClause = `and h.model = '${model}'`;
truthClause = `and h.obtype = '${truth}'`;
stormClause = `and h.vx_mask = '${basin}'`;
statistic = statistic.replace("Rapid Intensification ", "");
const { variable } = curve;
variableClause = `and h.fcst_var = '${variable}'`;
const { threshold } = curve;
thresholdClause = `and h.fcst_thresh = '${threshold}'`;
} else if (statLineType === "precalculated") {
// set up fields specific to precalculated stats
statisticClause = `avg(${statisticOptionsMap[statistic][2]}) as stat, group_concat(distinct ${statisticOptionsMap[statistic][2]}, ';', 9999, ';', unix_timestamp(ld.fcst_valid) order by unix_timestamp(ld.fcst_valid)) as sub_data`;
statHeaderType = "tcst_header";
[, lineDataType] = statisticOptionsMap[statistic];
modelClause = `and h.amodel = '${model}'`;
truthClause = `and h.bmodel = '${truth}'`;
stormClause = `and h.basin = '${basin}'`;
let levels =
curve.level === undefined || curve.level === matsTypes.InputTypes.unused
? []
: curve.level;
const levelValuesMap = matsCollections.level.findOne(
{ name: "level" },
{ valuesMap: 1 }
).valuesMap;
const levelKeys = Object.keys(levelValuesMap);
let levelKey;
levels = Array.isArray(levels) ? levels : [levels];
if (levels.length > 0) {
levels = levels
.map(function (l) {
for (let lidx = 0; lidx < levelKeys.length; lidx += 1) {
levelKey = levelKeys[lidx];
if (levelValuesMap[levelKey].name === l) {
return `'${levelKey}'`;
}
}
return null;
})
.join(",");
levelsClause = `and ld.level IN(${levels})`;
}
}
const queryTableClause = `from ${database}.tcst_header h, ${database}.${lineDataType} ld`;
const { basin } = curve;
const stormClause = `and h.basin = '${basin}'`;
const truthStr = curve.truth;
const truth = Object.keys(
matsCollections.truth.findOne({ name: "truth" }).valuesMap
).find(
(key) =>
matsCollections.truth.findOne({ name: "truth" }).valuesMap[key] === truthStr
);
const truthClause = `and h.bmodel = '${truth}'`;

const queryTableClause = `from ${database}.${statHeaderType} h, ${database}.${lineDataType} ld`;
const statHeaderClause = `and h.${statHeaderType}_id = ld.${statHeaderType}_id`;

let vts = ""; // start with an empty string that we can pass to the python script if there aren't vts.
let validTimeClause = "";
if (
Expand Down Expand Up @@ -110,32 +168,6 @@ dataYearToYear = function (plotParams, plotFunction) {
.join(",");
forecastLengthsClause = `and ld.fcst_lead IN(${fcsts})`;
}
let levels =
curve.level === undefined || curve.level === matsTypes.InputTypes.unused
? []
: curve.level;
const levelValuesMap = matsCollections.level.findOne(
{ name: "level" },
{ valuesMap: 1 }
).valuesMap;
const levelKeys = Object.keys(levelValuesMap);
let levelKey;
let levelsClause = "";
levels = Array.isArray(levels) ? levels : [levels];
if (levels.length > 0 && lineDataType !== "line_data_probrirw") {
levels = levels
.map(function (l) {
for (let lidx = 0; lidx < levelKeys.length; lidx += 1) {
levelKey = levelKeys[lidx];
if (levelValuesMap[levelKey].name === l) {
return `'${levelKey}'`;
}
}
return null;
})
.join(",");
levelsClause = `and ld.level IN(${levels})`;
}
let descrs =
curve.description === undefined ||
curve.description === matsTypes.InputTypes.unused
Expand All @@ -158,14 +190,17 @@ dataYearToYear = function (plotParams, plotFunction) {
// 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.
const axisKey = statistic;
const axisKey = statistic
.replace("Truth ", "")
.replace("Model ", "")
.replace("Model-truth ", "");
curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options

if (!diffFrom) {
// this is a database driven curve, not a difference curve
// prepare the query from the above parameters
statement =
"select substring(h.storm_id, -4) as year, " +
"select date_format(ld.fcst_valid, '%Y') as year, " +
"count(distinct unix_timestamp(ld.fcst_valid)) as N_times, " +
"min(unix_timestamp(ld.fcst_valid)) as min_secs, " +
"max(unix_timestamp(ld.fcst_valid)) as max_secs, " +
Expand All @@ -174,12 +209,14 @@ dataYearToYear = function (plotParams, plotFunction) {
"where 1=1 " +
"{{modelClause}} " +
"{{stormClause}} " +
"{{variableClause}} " +
"{{thresholdClause}} " +
"{{truthClause}} " +
"{{validTimeClause}} " +
"{{forecastLengthsClause}} " +
"{{levelsClause}} " +
"{{descrsClause}} " +
"and h.tcst_header_id = ld.tcst_header_id " +
"{{statHeaderClause}} " +
"group by year " +
"order by year" +
";";
Expand All @@ -188,11 +225,17 @@ dataYearToYear = function (plotParams, plotFunction) {
statement = statement.replace("{{queryTableClause}}", queryTableClause);
statement = statement.replace("{{modelClause}}", modelClause);
statement = statement.replace("{{stormClause}}", stormClause);
statement = statement.replace("{{variableClause}}", variableClause);
statement = statement.replace("{{thresholdClause}}", thresholdClause);
statement = statement.replace("{{truthClause}}", truthClause);
statement = statement.replace("{{validTimeClause}}", validTimeClause);
statement = statement.replace("{{forecastLengthsClause}}", forecastLengthsClause);
statement = statement.replace("{{levelsClause}}", levelsClause);
statement = statement.replace("{{descrsClause}}", descrsClause);
statement = statement.replace("{{statHeaderClause}}", statHeaderClause);
if (statLineType !== "precalculated") {
statement = statement.replace(/fcst_valid/g, "fcst_valid_beg");
}
dataRequests[label] = statement;

queryArray.push({
Expand Down
1 change: 1 addition & 0 deletions apps/met-cyclone/server/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ const doCurveParams = function () {
matsTypes.PlotTypes.dieoff,
matsTypes.PlotTypes.validtime,
matsTypes.PlotTypes.histogram,
matsTypes.PlotTypes.yearToYear,
],
};

Expand Down

0 comments on commit 777315d

Please sign in to comment.