diff --git a/cefi.css b/cefi.css index c6ced94..d260f6f 100644 --- a/cefi.css +++ b/cefi.css @@ -1,3 +1,8 @@ +.google-form{ + width: 100%; + height: 1000px; + max-height: 1000px; /* Or set a specific max height if needed */ +} .refresh-link { cursor: pointer; diff --git a/forecast.js b/forecast.js index 8e8c298..cd79fa4 100644 --- a/forecast.js +++ b/forecast.js @@ -58,60 +58,9 @@ createMomCobaltDepthBlockOptFcast(varValueFcast,'blockMOMCobaltFcast') // setup colorbar option createMomCobaltCbarOpt('cbarOptsFcast'); -// Initial dashboard plot -$(function() { - var trace = { - x: "", - y: "", - type: 'scatter', - mode: 'lines+markers', - marker: { size: 8 }, - line: { shape: 'linear' }, - name: "" - }; - - var layout1 = { - title: - 'Create Forecast Map first
& pick point on the shaded area', - // autosize: true, - // width: 1000, - // height: 400, - xaxis: { title: 'Date' }, - yaxis: { title: 'Variable' }, - hovermode: 'closest', - showlegend: false, - // responsive: true - }; - - var layout2 = { - title: - 'Create Forecast Map first & draw transect (polyline) on the shaded area', - // autosize: true, - // width: 1000, - // height: 400, - xaxis: { title: 'Date' }, - yaxis: { title: 'Variable' }, - hovermode: 'closest', - showlegend: false, - // responsive: true - }; - - var layout3 = { - title: - 'Pick a index', - // autosize: true, - // width: 1000, - // height: 400, - xaxis: { title: 'Date' }, - yaxis: { title: 'Variable' }, - hovermode: 'closest', - showlegend: false, - // responsive: true - }; - var config = {responsive: true} - Plotly.newPlot('plotly-fcast-spread', [trace], layout1, config); - Plotly.newPlot('plotly-fcast-box', [trace], layout1, config); - // Plotly.newPlot('plotly-index', [trace], layout3) +// initialize plotly +$(document).ready(function() { + window.asyncInitializePlotlyResize('forecast') }); ///////////////// event listener //////////////// @@ -202,6 +151,8 @@ $("#analysisMOMCobaltFcast").on("change", function(){ $("#"+selectedValue.slice(0, -3)).addClass("active"); }) + + // add event listener for the "message" event using jQuery (location click) $(window).on("message", receiveMessageFcast); diff --git a/forecast_mhw.html b/forecast_mhw.html index 0085a2a..b8a8a62 100644 --- a/forecast_mhw.html +++ b/forecast_mhw.html @@ -161,14 +161,15 @@

Initialization :

Probability Forecast

-
-
-
+
+

Forecast Spread

+
+
diff --git a/forecast_mhw.js b/forecast_mhw.js index 8c20a6d..cc740c2 100644 --- a/forecast_mhw.js +++ b/forecast_mhw.js @@ -55,6 +55,10 @@ window.createMomCobaltOpt_singleID('statMOMCobaltFcastMHW',momCobaltStatsFcastMH // setup colorbar option (using historical.js function) window.createMomCobaltCbarOpt('cbarOptsFcastMHW','inferno'); +// initialize the plotly +$(document).ready(function() { + window.asyncInitializePlotlyResize('mhwForecast') +}); ///////////////// event listener //////////////// // screen size adjustment trigger by window resizing @@ -163,6 +167,9 @@ $("#"+dashNavPillID+" > ul.nav-tabs > li.nav-item > .nav-link").on('click',funct let hrefIDText = hrefID.slice(1) // reuse changeDashSelect (historical.js) window.changeDashSelect(dashDropDownID,hrefIDText+'Val') + + // Manually trigger a resize event for triggering plotly resizing + window.dispatchEvent(new Event('resize')); }); // event listener for the "message" event when map location click @@ -240,6 +247,7 @@ function replaceFoliumForecastMHW() { // getting the lon lat from iframe and send to // server to get // 1. value of the marker on the shading +// 2. plotly figure create/refresh var varDataFcastMHW = null function receiveMessageFcastMHW(event) { // Access the data sent from the iframe @@ -266,10 +274,8 @@ function receiveMessageFcastMHW(event) { }); // display forecast spread plotly - // plotTSFcast(locationDataFcastMHW) - + plotFcast(locationDataFcastMHW) } - // console.log("Received data from iframe:", locationDataFcastMHW); // console.log(event.originalEvent.origin); }; @@ -307,316 +313,239 @@ function getvarValFcastMHW(infoLonLat) { console.error('Fetch MHW value error:', error); }); - return ajaxGetPromise }; -// // function for setting up promises in Forecast TS spread(execute order for async) -// // 1. input lon lat location -// // 2. Fetch forecast TSs (setup promise) -// // 3. create plotly object on webpage (execute when promise resolved) -// function plotTSFcastMHW(infoLonLat) { -// showLoadingSpinner("loading-spinner-fcastmhw-spread"); -// getTSFcastsMHW(infoLonLat) // the function return a promise obj from fetch -// .then((jsonData)=>{ -// plotlyForecastSpread(jsonData) -// plotlyForecastBox(jsonData) -// hideLoadingSpinner("loading-spinner-fcastmhw-spread"); -// }) -// .catch((error)=>{ -// console.error(error); -// }) -// }; - -// // function to fetch all forecast spread based on locationData -// // response in the json format (testing) -// function getTSFcasts(infoLonLat) { -// var ajaxGet = "/cgi-bin/cefi_portal/mom_extract_timeseries_fcast.py" -// +"?variable="+varFoliumMapFcastMHW -// +"®ion="+$("#regMOMCobaltFcast").val() -// +"&stat="+statMapFcastMHW -// +"&depth="+depthMapFcast -// +"&lon="+infoLonLat.longitude -// +"&lat="+infoLonLat.latitude -// +"&iniyear="+$("#iniYearMOMCobaltFcast").val() -// +"&inimonth="+$("#iniMonthMOMCobaltFcast").val() +// function for setting up promises in Forecast prob TS spread +// 1. input lon lat location +// 2. fetch forecast TSs (return promise) +// 3. create plotly object on webpage (execute when promise resolved) +function plotFcast(infoLonLat) { + showLoadingSpinner("loading-spinner-fcastmhw-prob"); + showLoadingSpinner("loading-spinner-fcastmhw-spread"); + // get promise obj from fetch + fetchFcastsTS(infoLonLat) + .then((jsonData)=>{ + plotlyFcastsProb(jsonData); + plotlyForecastSpread(jsonData); + }) + .then(()=>{ + hideLoadingSpinner("loading-spinner-fcastmhw-prob"); + hideLoadingSpinner("loading-spinner-fcastmhw-spread"); + }) + .catch((error)=>{ + console.error('Plotting MHW time series error:',error); + }) +}; + +// function to fetch all forecast ts based on locationData +// response in the json format +function fetchFcastsTS(infoLonLat) { + var ajaxGet = "/cgi-bin/cefi_portal/mom_extract_timeseries_fcast_mhw.py" + +"?region="+$("#regMOMCobaltFcastMHW").val() + +"&lon="+infoLonLat.longitude + +"&lat="+infoLonLat.latitude + +"&iniyear="+$("#iniYearMOMCobaltFcastMHW").val() + +"&inimonth="+$("#iniMonthMOMCobaltFcastMHW").val() -// console.log('https://webtest.psd.esrl.noaa.gov/'+ajaxGet) - -// ajaxGetPromise = fetch(ajaxGet) -// .then(response => { -// if (!response.ok) { -// throw new Error('Network response was not ok'); -// } -// return response.json(); -// }) -// .catch(error => { -// // Handle errors here -// console.error('Fetch time series error:', error); -// }); - -// return ajaxGetPromise -// }; - -// // function for creating the plotly forecast spread time series -// function plotlyForecastSpread(jsonData) { -// var yformat = decimal_format(jsonData.mean); - -// var trace1Color = "rgba(113, 29, 176, 0.7)"; -// var trace = { -// x: leadMonthListMHW, -// y: jsonData.mean, -// type: 'scatter', -// mode: 'lines+markers', -// marker: { size: 5 }, -// line: { -// shape: 'linear', -// color: trace1Color, -// width: 3 -// }, -// // name: statMap+' time series', -// name: varnameFcast -// }; - -// var data = [trace]; - -// var trace2Color = "rgba(113, 29, 176, 0.1)"; -// for (var i=1; i<=10; i++) { -// var key = 'ens'+i -// var trace_ens = { -// x: leadMonthListMHW, -// y: jsonData[key], -// type: 'scatter', -// mode: 'lines+markers', -// marker: { size: 2 }, -// line: { -// shape: 'linear', -// color: trace2Color }, -// // name: statMap+' time series', -// name: key -// }; -// data.push(trace_ens) -// } + console.log('https://webtest.psd.esrl.noaa.gov/'+ajaxGet) + + var ajaxGetPromise = fetch(ajaxGet) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .catch(error => { + // Handle errors here + console.error('Fetch MHW time series error:', error); + }); + + return ajaxGetPromise +}; + +// function for creating the plotly forecast prob time series +function plotlyFcastsProb(jsonData) { + // getting the y axis format using forecast.js function + var yformat = window.decimal_format(jsonData.mhw_prob90.ts); + + var trace1Color = "rgba(113, 29, 176, 0.7)"; + var trace = { + x: leadMonthListMHW, + y: jsonData.mhw_prob90.ts, + type: 'scatter', + mode: 'lines+markers', + marker: { size: 5 }, + line: { + shape: 'linear', + color: trace1Color, + width: 3 + }, + // legend + name: jsonData.mhw_prob90.varname + }; + + var data = [trace]; + + var layout = { + hovermode: 'closest', + showlegend: false, + title: + 'MHW Probability
' + + ' @ (lat:'+parseFloat(jsonData.location.lat).toFixed(2)+'N,'+ + 'lon:'+parseFloat(jsonData.location.lon).toFixed(2)+'E)', + autosize: true, + annotations: [{ + x: 0, + y: 0, + xref: 'paper', + yref: 'paper', + text: 'Source: NOAA CEFI data portal', + showarrow: false + }], + // width: 550, + // height: 400, + margin: { + l: 80, + r: 80, + b: 80, + t: 100, + // pad: 4 + }, + xaxis: { + title: 'Lead time' + }, + yaxis: { + title: { + text: 'MHW Probability (%)', + standoff: 10, + font: { color: trace1Color } + }, + tickfont: { color: trace1Color }, + tickformat: yformat, + tickmode: 'auto' + }, + modebar: { + remove: ["autoScale2d", "autoscale", "zoom", "zoom2d", ] + }, + dragmode: "select" + // responsive: true + }; + + Plotly.newPlot('plotly-fcastmhw-prob', data, layout); +}; + +// function for creating the plotly forecast spread time series +function plotlyForecastSpread(jsonData) { + // getting the y axis format using forecast.js function + var yformat = decimal_format(jsonData.ssta_avg.ts); + + // ensemble mean + var trace1Color = "rgba(113, 29, 176, 0.7)"; + var trace = { + x: leadMonthListMHW, + y: jsonData.ssta_avg.ts, + type: 'scatter', + mode: 'lines+markers', + marker: { size: 5 }, + line: { + shape: 'linear', + color: trace1Color, + width: 3 + }, + name: 'ssta ens mean' + }; + var data = [trace]; + + // ensemble members + var trace2Color = "rgba(113, 29, 176, 0.1)"; + for (var i=1; i<=10; i++) { + var key = 'ssta_ens'+i + var trace_ens = { + x: leadMonthListMHW, + y: jsonData[key].ts, + type: 'scatter', + mode: 'lines+markers', + marker: { size: 2 }, + line: { + shape: 'linear', + color: trace2Color }, + name: key + }; + data.push(trace_ens); + } + // threshold + var trace3Color = "rgba(203, 128, 171, 0.9)"; + var trace_thres = { + x: leadMonthListMHW, + y: jsonData.tos_threshold90.ts, + type: 'scatter', + mode: 'lines+markers', + marker: { size: 2 }, + line: { + shape: 'linear', + color: trace3Color, + dash: 'dash' + }, + name: '90% threshold' + }; + data.push(trace_thres); + + // plotly figure layout + var layout = { + hovermode: 'closest', + showlegend: true, + legend: { + x: 1, // Positioning on the right + y: 0, + xanchor: 'left' // Anchor the legend to avoid it getting cut off + }, + title: + 'MHW Magnitude
' + + ' @ (lat:'+parseFloat(jsonData.location.lat).toFixed(2)+'N,'+ + 'lon:'+parseFloat(jsonData.location.lon).toFixed(2)+'E)', + autosize: true, + annotations: [{ + x: 0, + y: 0, + xref: 'paper', + yref: 'paper', + text: 'Source: NOAA CEFI data portal', + showarrow: false + }], + // width: 550, + // height: 400, + margin: { + l: 80, + r: 150, + b: 80, + t: 100, + // pad: 4 + }, + xaxis: { + title: 'Lead time' + }, + yaxis: { + title: { + text: 'Sea Surface Temperature Anomaly (degC)', + standoff: 10, + font: { color: trace1Color } + }, + tickfont: { color: trace1Color }, + tickformat: yformat, + tickmode: 'auto' + }, + modebar: { + remove: ["autoScale2d", "autoscale", "zoom", "zoom2d", ] + }, + dragmode: "select" + // responsive: true + }; -// var layout = { -// hovermode: 'closest', -// showlegend: false, -// title: -// varnameFcast +'
' + -// ' @ (lat:'+parseFloat(jsonData.lat).toFixed(2)+'N,'+ -// 'lon:'+parseFloat(jsonData.lon).toFixed(2)+'E)', -// // autosize: true, -// annotations: [{ -// x: 0, -// y: 0, -// xref: 'paper', -// yref: 'paper', -// text: 'Source: NOAA CEFI data portal', -// showarrow: false -// }], -// // width: 550, -// // height: 400, -// margin: { -// l: 80, -// r: 80, -// b: 80, -// t: 100, -// // pad: 4 -// }, -// xaxis: { -// title: 'Lead time' -// }, -// yaxis: { -// title: { -// text: statMapFcastNameMHW + ' (' + jsonData.units + ')', -// standoff: 10, -// font: { color: trace1Color } -// }, -// tickfont: { color: trace1Color }, -// tickformat: yformat, -// tickmode: 'auto' -// }, -// modebar: { -// remove: ["autoScale2d", "autoscale", "zoom", "zoom2d", ] -// }, -// dragmode: "select" -// // responsive: true -// }; - -// Plotly.newPlot('plotly-fcast-spread', data, layout); -// }; - -// // function for creating the plotly forecast ensemble range time series -// function plotlyForecastRange(jsonData) { -// var yformat = decimal_format(jsonData.spread); - -// var trace1Color = "rgba(113, 29, 176, 0.7)"; -// var trace = { -// x: leadMonthListMHW, -// y: jsonData.spread, -// type: 'scatter', -// mode: 'lines+markers', -// marker: { size: 5 }, -// line: { -// shape: 'linear', -// color: trace1Color, -// width: 3 -// }, -// // name: statMap+' time series', -// name: varnameFcast -// }; - -// var data = [trace]; - -// var layout = { -// hovermode: 'closest', -// showlegend: false, -// title: -// varnameFcast +'
' + -// ' @ (lat:'+parseFloat(jsonData.lat).toFixed(2)+'N,'+ -// 'lon:'+parseFloat(jsonData.lon).toFixed(2)+'E)', -// // autosize: true, -// annotations: [{ -// x: 0, -// y: 0, -// xref: 'paper', -// yref: 'paper', -// text: 'Source: NOAA CEFI data portal', -// showarrow: false -// }], -// // width: 1000, -// // height: 400, -// margin: { -// l: 80, -// r: 80, -// b: 80, -// t: 100, -// // pad: 4 -// }, -// xaxis: { -// title: 'Lead time' -// }, -// yaxis: { -// title: { -// text: statMapFcastNameMHW + ' (' + jsonData.units + ')', -// standoff: 10, -// font: { color: trace1Color } -// }, -// tickfont: { color: trace1Color }, -// tickformat: yformat, -// tickmode: 'auto' -// }, -// modebar: { -// remove: ["autoScale2d", "autoscale", "zoom", "zoom2d", ] -// }, -// dragmode: "select" -// // responsive: true -// }; -// var config = {responsive: true} -// Plotly.newPlot('plotly-fcast-spread', data, layout,config); -// }; - -// // function for creating the plotly time series box plot -// function plotlyForecastBox(jsonData) { -// var yformat = decimal_format(jsonData.mean); -// var trace1Color = "rgba(113, 29, 176, 0.8)"; -// var xData = leadMonthListMHW; -// var yData = []; -// for (var l=0; l<=11; l++) { -// var ens = [] -// for (var i=1; i<=10; i++) { -// var key = 'ens'+i -// ens.push(jsonData[key][l]); -// } -// yData.push(ens); -// }; - -// var data = []; - -// for ( var i = 0; i < xData.length; i ++ ) { -// var result = { -// type: 'box', -// y: yData[i], -// name: xData[i], -// boxpoints: false, -// // jitter: 0.3, -// // pointpos: -1.8, -// type: 'box', -// boxmean: 'sd', -// // boxpoints: 'all', -// // jitter: 0.5, -// whiskerwidth: 1, -// // fillcolor: none, -// marker: { -// size: 1, -// color: trace1Color -// }, -// line: { -// width: 1, -// color: trace1Color -// } -// }; -// data.push(result); -// }; - -// layout = { -// hovermode: 'closest', -// showlegend: false, -// title: 'Ensemble spread at each lead', -// annotations: [{ -// x: 0, -// y: 0, -// xref: 'paper', -// yref: 'paper', -// text: 'Source: NOAA CEFI data portal', -// showarrow: false -// }], -// // width: 530, -// // height: 400, -// margin: { -// l: 80, -// r: 80, -// b: 80, -// t: 100, -// // pad: 4 -// }, -// xaxis: { -// title: 'Lead time' -// }, -// yaxis: { -// title: { -// text: statMapFcastNameMHW + ' (' + jsonData.units + ')', -// standoff: 10, -// font: { color: trace1Color } -// }, -// tickfont: { color: trace1Color }, -// tickformat: yformat, -// tickmode: 'auto' -// }, -// modebar: { -// remove: ["autoScale2d", "autoscale", "zoom", "zoom2d", ] -// }, -// dragmode: "select" -// // responsive: true -// }; -// var config = {responsive: true} - -// Plotly.newPlot('plotly-fcast-box', data, layout,config); - -// }; - -// // function for deciding the y tick numerical format -// function decimal_format(numArray) { -// var format = '.2f'; -// var maxVal = Math.max(...numArray); -// var minVal = Math.min(...numArray); -// var diff = Math.abs(maxVal-minVal); -// if (diff< 0.01) { -// format = '.2e'; -// } -// return format -// }; + Plotly.newPlot('plotly-fcastmhw-mag', data, layout); +}; ///////// information function start ///////// diff --git a/historical.html b/historical.html index 826fe46..5f47c41 100644 --- a/historical.html +++ b/historical.html @@ -191,7 +191,7 @@

Time Series Analyses

- +
diff --git a/historical.js b/historical.js index 2290360..67a1ce9 100644 --- a/historical.js +++ b/historical.js @@ -65,7 +65,10 @@ $('#depthMOMCobaltTS2').val(''); createMomCobaltVarOpt('onlyIndexes','indexMOMCobaltTS'); // initialize plotly -initializePlotly('all'); +$(document).ready(function() { + asyncInitializePlotlyResize('all') +}); +// initializePlotly('all'); // plot index plotIndexes(); @@ -177,6 +180,7 @@ $("#analysisMOMCobalt").on("change", function(){ // change the active navpil content $("#dashContentHistrun div.tab-pane").removeClass("active"); $("#"+selectedValue.slice(0, -3)).addClass("active"); + }) // event listener for navpil being clicked @@ -184,6 +188,7 @@ $("#dashNavHistrun > ul.nav-pills > li.nav-item > .nav-link").on('click',functio let hrefID = $(this).attr('href') let hrefIDText = hrefID.slice(1) changeDashSelect('analysisMOMCobalt',hrefIDText+'Val') + window.dispatchEvent(new Event('resize')); }); // event listener for navtab being clicked @@ -311,6 +316,16 @@ $('#indexMOMCobaltTS').on("change", function () { ///////// functional function start ///////// // intialize the plotly plot // Initial dashboard plot +function asyncInitializePlotlyResize(flag) { + return initializePlotly(flag) + .then(() => { + window.dispatchEvent(new Event('resize')); + }) + .catch(error => { + console.error('Error in async plotly initialization:', error); + }); +} + function initializePlotly(flag) { var trace = { x: "", @@ -381,9 +396,9 @@ function initializePlotly(flag) { // responsive: true }; - var layout3 = { + var layoutFcst = { title: - 'Pick an index', + 'Create Forecast Map first
& pick point on the shaded area', // autosize: true, // width: 1000, // height: 400, @@ -411,9 +426,18 @@ function initializePlotly(flag) { Plotly.newPlot('plotly-time-series', [trace], layoutTS,config); } else if (flag ==='transect') { Plotly.newPlot('plotly-transect', [trace], layout2,config); + } else if (flag ==='forecast') { + Plotly.newPlot('plotly-fcast-spread', [trace], layoutFcst, config); + Plotly.newPlot('plotly-fcast-box', [trace], layoutFcst, config); } else if (flag ==='mhwForecast') { - + Plotly.newPlot('plotly-fcastmhw-prob', [trace], layoutTS,config); + Plotly.newPlot('plotly-fcastmhw-mag', [trace], layoutTS,config); } + + return new Promise(resolve => { + console.log('Initial Plotly created'); + resolve(); + }); }; // //function for option change due to button/view change at the bottom diff --git a/overview.html b/overview.html index 9ab28cb..5160894 100644 --- a/overview.html +++ b/overview.html @@ -3,6 +3,29 @@ + + + +

1 minute CEFI

The goal of the Climate Ecosystem and Fisheries Initiative (CEFI) is to provide @@ -157,4 +180,6 @@

NOAA’s Response

- \ No newline at end of file + + +