Skip to content
Snippets Groups Projects
Commit c084330e authored by Tor-Einar Skog's avatar Tor-Einar Skog
Browse files

First version with chart for barley net bloch model

Also, refactore chart library out of html template in forecasts app
parent 014bdaa9
No related branches found
No related tags found
No related merge requests found
File added
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-05-29 16:02+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: templates/cerealblotchmodels/barleynetblotchform.html:25
#: templates/cerealblotchmodels/barleynetblotchform.html:28
msgid "Barley net blotch"
msgstr "Byggbrunflekk"
#: templates/cerealblotchmodels/barleynetblotchform.html:33
msgid "Background data for the barley net blotch model"
msgstr "Bakgrunnsdata for byggbrunflekkmodellen"
#: templates/cerealblotchmodels/barleynetblotchform.html:39
msgid "Weather station"
msgstr "Målestasjon"
#: templates/cerealblotchmodels/barleynetblotchform.html:42
msgid "Sowing date"
msgstr "Sådato"
#: templates/cerealblotchmodels/barleynetblotchform.html:44
msgid "Crop"
msgstr "Kultur"
#: templates/cerealblotchmodels/barleynetblotchform.html:48
msgid "Same crop as last season"
msgstr "Samme kultur som i fjor"
#: templates/cerealblotchmodels/barleynetblotchform.html:50
msgid "Plowed"
msgstr "Pløyd"
#: templates/cerealblotchmodels/barleynetblotchform.html:53
msgid "Observation date"
msgstr "Observasjonsdato"
#: templates/cerealblotchmodels/barleynetblotchform.html:55
#, fuzzy, python-format
msgid "%% Infected leaves"
msgstr "% infiserte blad"
#: templates/cerealblotchmodels/barleynetblotchform.html:57
msgid "Spraying date"
msgstr "Sprøytedato"
#: templates/cerealblotchmodels/barleynetblotchform.html:59
msgid "Preparation"
msgstr "Plantevernmiddel"
#: templates/cerealblotchmodels/barleynetblotchform.html:62
msgid "Preparation dose"
msgstr "Dose"
#: templates/cerealblotchmodels/barleynetblotchform.html:69
msgid "Run model"
msgstr "Kjør modell"
#: templates/cerealblotchmodels/barleynetblotchform.html:76
msgid "Model is running, please wait"
msgstr "Modellen kjører, vennligst vent"
#: templates/cerealblotchmodels/barleynetblotchform.html:132
msgid "Time"
msgstr "Tid"
#: templates/cerealblotchmodels/barleynetblotchform.html:140
msgid "Warning status"
msgstr "Varselstatus"
#: templates/cerealblotchmodels/barleynetblotchform.html:164
msgid "No data returned"
msgstr "Ingen data returnert"
#: templates/cerealblotchmodels/barleynetblotchform.html:175
msgid "Disease value"
msgstr "Sykdomsverdi"
#: templates/cerealblotchmodels/barleynetblotchform.html:178
msgid "Threshold"
msgstr "Terskelverdi"
#: templates/cerealblotchmodels/barleynetblotchform.html:179
msgid "Disease"
msgstr "Sykdom"
#: templates/cerealblotchmodels/barleynetblotchform.html:182
msgid "Barley net blotch development"
msgstr "Utvikling av byggbrunflekk"
#: templates/cerealblotchmodels/barleynetblotchform.html:194
msgid "Select weather station"
msgstr "Velg målestasjon"
#: templates/cerealblotchmodels/barleynetblotchform.html:220
msgid "Select crop"
msgstr "Velg kultur"
#: templates/cerealblotchmodels/barleynetblotchform.html:247
msgid "Select preparation"
msgstr "Velg plantevernmiddel"
#: templates/cerealblotchmodels/index.html:25
#: templates/cerealblotchmodels/index.html:27
msgid "Cereal blotch models"
msgstr "Bladflekksjukdommer i korn"
......@@ -81,17 +81,21 @@
<div class="alert alert-danger" role="alert" id="errorMessage"></div>
</div>
</div>
<div id="results" style="display:none;">
<div class="table-responsive">
<table id="resultsTable" class="table table-striped">
</table>
</div>
<div id="container" style="width: 100%; height:400px;"></div>
<div class="table-responsive">
<table id="resultsTable" class="table table-striped"></table>
</div>
</div>
{% endblock %}
{% block customJS %}
<script type="text/javascript" src="{% url "views.settings_js" %}"></script>
<script type="text/javascript" src="/static/organisms/organismsUtil.js"></script>
<script type="text/javascript" src="{% static "js/3rdparty/moment.min.js" %}"></script>
<script type="text/javascript" src="{% static "js/3rdparty/highcharts.js" %}"></script>
<script type="text/javascript" src="{% static "js/util.js" %}"></script>
<script type="text/javascript" src="{% static "organisms/organismsUtil.js" %}"></script>
<script type="text/javascript" src="{% static "forecasts/js/forecasts.js" %}"></script>
<script type="text/javascript">
$(document).ready(function() {
......@@ -125,7 +129,7 @@
var renderResults = function(data,textStatus, jqXHR)
{
// First attempt: A table!
var headingLine = "<tr><td style=\"font-weight: bold;\">Time</td>";
var headingLine = "<tr><td style=\"font-weight: bold;\">{% trans "Time" %}</td>";
if(data.length > 0)
{
var allKeys = data[0].keys;
......@@ -133,7 +137,7 @@
{
headingLine +="<td style=\"font-weight: bold;\">" + allKeys[i] + "</td>";
}
headingLine +="<td style=\"font-weight: bold;\">Warning Status</td>";
headingLine +="<td style=\"font-weight: bold;\">{% trans "Warning status" %}</td>";
headingLine += "</tr>";
var table = ["<table border=\"1\">",headingLine];
......@@ -153,14 +157,29 @@
}
table.push("</table>");
document.getElementById("resultsTable").innerHTML=table.join("");
}
else
{
document.getElementById("resultsTable").innerHTML="<h2>No data returned</h2>";
document.getElementById("resultsTable").innerHTML="<h2>{% trans "No data returned" %}</h2>";
}
document.getElementById("runningModelMessage").style.display="none";
document.getElementById("errorMessageContainer").style.display="none";
document.getElementById("results").style.display="block";
// Then: The chart
var warningStatusPlotBandData = getWarningStatusPlotBandData(data);
//console.log(warningStatusPlotBandData);
var data = getHighChartsSeries(
data,
[
{"color": "#6600FF", "opposite": false, "abbr": " ", "title": "{% trans "Disease value" %}"}
],
[
{key: "BARLEYNETB.Y", type: "spline", color: "red", name: "{% trans "Threshold" %}", yAxis: 0},
{key: "BARLEYNETB.X_ADJUSTED", type: "spline", color: "black", name: "{% trans "Disease" %}", yAxis: 0}
]
);
renderForecastChart("container", "{% trans "Barley net blotch development" %}", warningStatusPlotBandData, data);
};
......
......@@ -96,7 +96,7 @@ class ForecastResult:
# We probably have a rouge plot band that needs to be finished and appended
if plot_band != None and plot_band.get("to", None) == None:
plot_band["to"] = util.get_unix_timestamp(forecast_results[-1].result_valid_time) - band_offset
plot_band["to"] = util.get_unix_timestamp(forecast_results[-1].result_valid_time) + band_offset
plot_bands.append(plot_band)
return plot_bands
......
......@@ -85,4 +85,206 @@ function getModelLocalName(modelsLocalNames, modelId)
}
}
return modelId;
};
\ No newline at end of file
};
/**
* Renders a forecast chart
* @param DOMContainerId String with id of HTML container to render to
* @param chartTitle String, title of chart
* @param warningStatusPlotBandData Array of plot band data. See http://www.highcharts.com/docs/chart-concepts/plot-bands-and-plot-lines
* Sample:
* <pre>
* [
* {'color': '#F0564D', 'to': 1428942600000.0, 'from': 1428877800000.0},
* {'color': '#6FC49A', 'to': 1429068600000.0, 'from': 1428942600000.0},
* {'color': '#FEDA4D', 'to': 1429075800000.0, 'from': 1429068600000.0},
* {'color': '#F0564D', 'to': 1429234200000.0, 'from': 1429075800000.0}
* ]
* </pre>
* @param data Highcharts formatted data in series. See http://www.highcharts.com/docs/chart-concepts/series
*/
function renderForecastChart(DOMContainerId, chartTitle, warningStatusPlotBandData, data)
{
var options = {
title: {
text: chartTitle,
},
chart: {
renderTo: DOMContainerId,
type: 'spline',
zoomType: "x"
},
plotOptions: {
series: {
allowPointSelect: false,
animation: false,
marker: {
enabled: false
}
}
},
xAxis: {
type: 'datetime',
maxZoom: 4 * 24 * 3600000, // four days
dateTimeLabelFormats: { // don't display the dummy year
month: '%e. %b',
year: '%b'
},
plotBands: warningStatusPlotBandData, // This is where we put warning status background bands
plotLines: [{
color: "white",
width: 3,
value: getSystemTime(),
dashStyle: 'shortdot',
zIndex: 100
}]
},
yAxis: [],
series: []
};
for(index in data.yAxis)
{
options.yAxis[index] = createYAxisConf(data.yAxis[index], index == 0);
}
var warningNS = "WARNING";
var warningPropNames = ["NOFORECAST","MISSINGDATA","NORISK","MEDIUMRISK","HIGHRISK"];
for(propName in data.series){
if(propName.indexOf(warningNS) != 0)
{
options.series[options.series.length] = data.series[propName];
}
}
//console.log("Before creating chart " + (new Date().getTime() % 10000000));
var chart = new Highcharts.Chart(options);
}
/**
* Based on a dict with axisInfo, creates a configuration for an axis
*/
function createYAxisConf(axisInfo, isFirst)
{
return {
gridLineWidth: isFirst ? 1 : 0,
opposite: axisInfo.opposite,
title: {
text: axisInfo.hideAxis ? "" : axisInfo.title,
style: {
color: axisInfo.color
}
},
labels: {
formatter: function(){
return axisInfo.hideAxis ? "" : this.value + axisInfo.abbr;
},
style: {
color: axisInfo.color
}
},
max: axisInfo.max,
min: axisInfo.min,
allowDecimals: axisInfo.allowDecimals != null ? axisInfo.allowDecimals : true,
ceiling: axisInfo.ceiling,
floor: axisInfo.floor
};
}
/**
*
*/
function changeLatestDays(theForm){
window.location.href="/forecasts/" + theForm.forecastConfigurationId.value + "/" + theForm.latestDays.value;
}
/**
* Returns an array with plot band data to be used in HighCharts
* @param results
*/
function getWarningStatusPlotBandData(forecastResults)
{
//console.log(forecastResults);
var warningStatuses = {
0: {name:"No forecast available", color:"#C9C9C9"},
1: {name:"Missing data", color:"#4DA0FE"},
2: {name:"No risk", color:"#6FC49A"},
3: {name:"Medium risk",color:"#FEDA4D"},
4: {name:"High risk",color:"#F0564D"}
};
var plotBands = [];
var previousForecastResult = null;
var plotBand = null;
var bandOffset = 0;
if (forecastResults.length >=2)
{
// Replace with Moment.js
var start = forecastResults[0]["resultValidTime"];
var end = forecastResults[1]["resultValidTime"];
bandOffset = (end - start) / 2;
//console.log("bandOffset=" + bandOffset);
}
for(var i in forecastResults)
{
var forecastResult = forecastResults[i];
if(previousForecastResult == null || previousForecastResult["warningStatus"] != forecastResult["warningStatus"])
{
// Add the previous plot band
if(plotBand != null)
{
// Moment.js needed!
plotBand["to"] = forecastResult["resultValidTime"] - bandOffset;
plotBands.push(plotBand);
}
plotBand = {
"color": warningStatuses[forecastResult["warningStatus"]].color,
// Moment.js!!
"from" : forecastResult["resultValidTime"] - bandOffset
};
}
previousForecastResult = forecastResult;
}
// We probably have a rouge plot band that needs to be finished and appended
if(plotBand != null && plotBand["to"] == null)
{
// Moment.js!!!
plotBand.to = forecastResults[forecastResults.length -1]["resultValidTime"] + bandOffset;
plotBands.push(plotBand);
}
return plotBands;
}
function getHighChartsSeries(forecastResults, yAxisList, parameterList)
{
var chartSeries = {
series: {},
yAxis: yAxisList
};
for(var i in parameterList)
{
var parameter = parameterList[i];
chartSeries.series[parameter.key] = {
data: [],
type: parameter.type,
name: parameter.name,
color: parameter.color,
yAxis: parameter.yAxis
};
}
for(var i in forecastResults)
{
var forecastResult = forecastResults[i];
for(var j in parameterList)
{
var parameter = parameterList[j];
var value = parseFloat(forecastResult["allValues"][parameter.key]);
chartSeries.series[parameter.key].data.push([forecastResult.resultValidTime,value]);
}
}
return chartSeries;
}
\ No newline at end of file
......@@ -91,112 +91,23 @@
<script type="text/javascript" src="{% url "views.settings_js" %}"></script>
<script type="text/javascript" src="{% static "js/3rdparty/moment.min.js" %}"></script>
<script type="text/javascript" src="{% static "js/util.js" %}"></script>
<script type="text/javascript" src="{% static "forecasts/js/forecasts.js" %}"></script>
<script type="text/javascript" src="{% static "js/3rdparty/highcharts.js" %}"></script>
<script type="text/javascript">
$(document).ready(function() {
{% if forecast_results|length > 0 %}
var options = {
title: {
text: "{{forecast_configuration.model_local_name}}"
},
chart: {
renderTo: 'container',
type: 'spline',
zoomType: "x"
},
plotOptions: {
series: {
allowPointSelect: false,
animation: false,
marker: {
enabled: false
}
}
},
xAxis: {
type: 'datetime',
maxZoom: 4 * 24 * 3600000, // four days
dateTimeLabelFormats: { // don't display the dummy year
month: '%e. %b',
year: '%b'
},
plotBands: {{forecast_warning_statuses_highcharts|safe}}, // This is where we put warning status background bands
plotLines: [{
color: "white",
width: 3,
value: getSystemTime(),
dashStyle: 'shortdot',
zIndex: 100
}]
},
yAxis: [],
series: []
};
var data = {{forecast_result_highcharts|safe}};
for(index in data.yAxis)
{
options.yAxis[index] = createYAxisConf(data.yAxis[index], index == 0);
}
var warningNS = "WARNING";
var warningPropNames = ["NOFORECAST","MISSINGDATA","NORISK","MEDIUMRISK","HIGHRISK"];
for(propName in data.series){
if(propName.indexOf(warningNS) != 0)
{
options.series[options.series.length] = data.series[propName];
}
}
/*
// Adding the warning stuff last
for(i in warningPropNames)
{
warningSeries = data.series[warningNS + "." + warningPropNames[i]];
if(warningSeries != null)
{
options.series[options.series.length] = warningSeries;
}
}*/
//console.log("Before creating chart " + (new Date().getTime() % 10000000));
var chart = new Highcharts.Chart(options);
var warningStatusPlotBandData = {{forecast_warning_statuses_highcharts|safe}};
var data = {{forecast_result_highcharts|safe}};
renderForecastChart(
"container",
"{{forecast_configuration.model_local_name}}",
warningStatusPlotBandData,
data
);
{% endif %}
});
/**
* Based on a dict with axisInfo, creates a configuration for an axis
*/
function createYAxisConf(axisInfo, isFirst)
{
return {
gridLineWidth: isFirst ? 1 : 0,
opposite: axisInfo.opposite,
title: {
text: axisInfo.hideAxis ? "" : axisInfo.title,
style: {
color: axisInfo.color
}
},
labels: {
formatter: function(){
return axisInfo.hideAxis ? "" : this.value + axisInfo.abbr;
},
style: {
color: axisInfo.color
}
},
max: axisInfo.max,
min: axisInfo.min,
allowDecimals: axisInfo.allowDecimals != null ? axisInfo.allowDecimals : true,
ceiling: axisInfo.ceiling,
floor: axisInfo.floor
};
}
/**
*
*/
function changeLatestDays(theForm){
window.location.href="/forecasts/" + theForm.forecastConfigurationId.value + "/" + theForm.latestDays.value;
}
</script>
{% endblock %}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment