Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
V
VIPSWeb
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
VIPS
VIPSWeb
Commits
9d548bdc
Commit
9d548bdc
authored
1 year ago
by
Tor-Einar Skog
Browse files
Options
Downloads
Patches
Plain Diff
Add weather data sources (historic and forecast)
parent
9c820098
No related branches found
No related tags found
2 merge requests
!13
Saddlegallmidge form idec 372
,
!12
feat: Add test page (spatial) with mapserver layer in openlayers map
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
ipmd/static/ipmd/js/ipmdlib.js
+108
-2
108 additions, 2 deletions
ipmd/static/ipmd/js/ipmdlib.js
ipmd/templates/ipmd/saddlegallmidgeform.html
+186
-35
186 additions, 35 deletions
ipmd/templates/ipmd/saddlegallmidgeform.html
with
294 additions
and
37 deletions
ipmd/static/ipmd/js/ipmdlib.js
+
108
−
2
View file @
9d548bdc
...
@@ -40,10 +40,27 @@ async function getModelInputSchema(dssId,modelId) {
...
@@ -40,10 +40,27 @@ async function getModelInputSchema(dssId,modelId) {
return
await
response
.
json
();
return
await
response
.
json
();
}
}
async
function
getWeatherDatasource
(
weatherDatasourceId
)
/*
async function getWeatherDatasource(weatherDatasourceId)
{
{
const response = await fetch(ipmdWeatherApiURL + "rest/weatherdatasource/" + weatherDatasourceId);
const response = await fetch(ipmdWeatherApiURL + "rest/weatherdatasource/" + weatherDatasourceId);
return await response.json();
return await response.json();
}*/
function
getWeatherDatasourceEndpoint
(
weatherDatasource
)
{
return
weatherDatasource
.
endpoint
.
replace
(
"
{WEATHER_API_URL}
"
,
ipmdWeatherApiURL
);
}
function
getWeatherDatasource
(
weatherDatasources
,
weatherDatasourceId
)
{
for
(
let
i
=
0
;
i
<
weatherDatasources
.
length
;
i
++
)
{
if
(
weatherDatasources
[
i
].
id
==
weatherDatasourceId
)
{
return
weatherDatasources
[
i
];
}
}
return
null
;
}
}
async
function
getWeatherDatasources
()
async
function
getWeatherDatasources
()
...
@@ -61,10 +78,22 @@ function getWeatherStationList(weatherDatasource){
...
@@ -61,10 +78,22 @@ function getWeatherStationList(weatherDatasource){
let
station
=
{
"
id
"
:
feature
.
id
,
"
name
"
:
feature
.
properties
.
name
}
let
station
=
{
"
id
"
:
feature
.
id
,
"
name
"
:
feature
.
properties
.
name
}
stationList
.
push
(
station
);
stationList
.
push
(
station
);
}
}
stationList
.
sort
((
a
,
b
)
=>
{
return
(
a
.
name
<
b
.
name
)
?
-
1
:
(
a
.
name
>
b
.
name
)
?
1
:
0
;
});
return
stationList
;
return
stationList
;
}
}
async
function
getLocationWeatherData
(
endpoint
,
weatherStationId
,
parameters
,
interval
,
dateStart
,
dateEnd
){
function
renderWeatherStationSelectList
(
stationList
,
selectList
){
selectList
.
add
(
new
Option
(
"
-- Please select weather station --
"
,
-
1
));
for
(
let
i
=
0
;
i
<
stationList
.
length
;
i
++
)
{
selectList
.
add
(
new
Option
(
stationList
[
i
].
name
,
stationList
[
i
].
id
));
}
}
async
function
getStationWeatherData
(
endpoint
,
weatherStationId
,
parameters
,
interval
,
dateStart
,
dateEnd
){
const
response
=
await
fetch
(
endpoint
const
response
=
await
fetch
(
endpoint
+
"
?timeStart=
"
+
dateStart
+
"
?timeStart=
"
+
dateStart
+
"
&timeEnd=
"
+
dateEnd
+
"
&timeEnd=
"
+
dateEnd
...
@@ -75,6 +104,18 @@ async function getLocationWeatherData(endpoint, weatherStationId, parameters, in
...
@@ -75,6 +104,18 @@ async function getLocationWeatherData(endpoint, weatherStationId, parameters, in
return
await
response
.
json
();
return
await
response
.
json
();
}
}
async
function
getLocationWeatherData
(
endpoint
,
longitude
,
latitude
,
parameters
,
interval
,
dateStart
,
dateEnd
){
const
response
=
await
fetch
(
endpoint
+
"
?timeStart=
"
+
dateStart
+
"
&timeEnd=
"
+
dateEnd
+
"
&interval=
"
+
interval
+
"
&longitude=
"
+
longitude
+
"
&latitude=
"
+
latitude
+
"
¶meters=
"
+
parameters
.
join
(
"
,
"
)
);
return
await
response
.
json
();
}
async
function
runModel
(
endpoint
,
inputData
)
async
function
runModel
(
endpoint
,
inputData
)
{
{
const
response
=
await
fetch
(
endpoint
,
{
const
response
=
await
fetch
(
endpoint
,
{
...
@@ -112,6 +153,71 @@ function getWeatherParameter(weatherParameterId){
...
@@ -112,6 +153,71 @@ function getWeatherParameter(weatherParameterId){
return
null
;
return
null
;
}
}
function
getWeatherStationCoordinate
(
weatherDatasource
,
weatherStationId
)
{
geoJson
=
JSON
.
parse
(
weatherDatasource
.
spatial
.
geoJSON
);
let
stationList
=
[];
for
(
let
i
=
0
;
i
<
geoJson
.
features
.
length
;
i
++
)
{
let
feature
=
geoJson
.
features
[
i
];
if
(
feature
.
id
==
weatherStationId
)
{
// TODO: Don't assume feature is a point
return
feature
.
geometry
.
coordinates
;
}
}
return
null
;
}
function
getPragmaticWeatherParameterList
(
requestedParameters
,
availableParameters
)
{
let
completeList
=
[];
for
(
let
i
=
0
;
i
<
requestedParameters
.
length
;
i
++
)
{
completeList
=
completeList
.
concat
(
requestedParameters
[
i
],
fallbackParams
[
requestedParameters
[
i
]]);
}
console
.
info
(
completeList
);
console
.
info
(
availableParameters
);
return
completeList
.
filter
(
param
=>
availableParameters
.
includes
(
param
));
}
/**
* Merges the two datasets. Keeping the primaryData if both sets have data for same time and parameter
* If a merge operation is not possible, primaryData is returned unchanged
* @param {Object} primaryData
* @param {Object} secondaryData
*/
function
mergeWeatherData
(
primaryData
,
secondaryData
)
{
// Where to start in primaryData?
let
mergedData
=
{
timeStart
:
null
,
timeEnd
:
null
,
interval
:
primaryData
.
interval
,
weatherParameters
:
primaryData
.
weatherParameters
};
console
.
info
(
"
primaryData.timeStart=
"
+
primaryData
.
timeStart
);
console
.
info
(
"
mergedData.timeStart=
"
+
mergedData
.
timeStart
);
}
const
fallbackParams
=
{
1001
:
[
1002
],
1002
:
[
1001
],
3001
:
[
3002
],
3002
:
[
3001
],
4002
:
[
4003
,
4012
,
4013
],
4003
:
[
4002
,
4013
,
4012
],
4012
:
[
4013
,
4002
,
4003
],
4013
:
[
4012
,
4003
,
4002
]
}
const
weatherParameterList
=
[
const
weatherParameterList
=
[
{
{
"
id
"
:
1001
,
"
id
"
:
1001
,
...
...
This diff is collapsed.
Click to expand it.
ipmd/templates/ipmd/saddlegallmidgeform.html
+
186
−
35
View file @
9d548bdc
...
@@ -27,10 +27,32 @@
...
@@ -27,10 +27,32 @@
<div
class=
"singleBlockContainer"
>
<div
class=
"singleBlockContainer"
>
<h1>
{% trans "Saddle gall midge" %}
</h1>
<h1>
{% trans "Saddle gall midge" %}
</h1>
<div
id=
"inputForm"
></div>
<div
id=
"inputForm"
></div>
<div
id=
"weatherStations"
style=
"display: none;"
>
<div
id=
"weatherDataForm"
style=
"display: none;"
>
<h2>
Weather stations
</h2>
<h2>
Weather data
</h2>
<select
class=
"form-control"
name=
"weatherStationId"
id=
"weatherStationId"
></select>
<fieldset
id=
"historicDatasourceFields"
>
</div>
<legend>
Weather datasource (historic)
</legend>
<select
class=
"form-control"
name=
"weatherDatasourceId"
id=
"weatherDatasourceList"
onchange=
"handleWeatherDatasourceSelected(this);"
></select>
<div
id=
"historicSourceInfo"
style=
"display: none;"
></div>
</fieldset>
<fieldset
id=
"stationFields"
style=
"display: none;"
>
<select
class=
"form-control"
name=
"weatherStationId"
id=
"weatherStationId"
onchange=
"handleWeatherStationSelected(this);"
></select>
</fieldset>
<fieldset
id=
"locationFields"
>
<legend>
Location (decimal degrees)
</legend>
<div
class=
"form-group"
>
<label
for=
"latitude"
>
Latitude
</label>
<input
type=
"number"
class=
"form-control"
id=
"latitude"
name=
"latitude"
placeholder=
"Latitude"
>
</div>
<div
class=
"form-group"
>
<label
for=
"longitude"
>
Longitude
</label>
<input
type=
"number"
class=
"form-control"
id=
"longitude"
name=
"longitude"
placeholder=
"Longitude"
>
</div>
</fieldset>
<fieldset
id=
"forecastDatasourceFields"
>
<legend>
Weather forecasts datasource
</legend>
<select
class=
"form-control"
name=
"forecastWeatherDatasourceId"
id=
"forecastWeatherDatasourceList"
onchange=
"handleForecastSourceSelected(this);"
></select>
<div
id=
"forecastSourceInfo"
style=
"display: none;"
></div>
</fieldset>
<button
class=
"btn btn-primary"
type=
"button"
onclick=
"submitData();"
>
Submit
</button>
<button
class=
"btn btn-primary"
type=
"button"
onclick=
"submitData();"
>
Submit
</button>
<div
style=
"aspect-ratio: 2;"
>
<div
style=
"aspect-ratio: 2;"
>
<canvas
id=
"resultChart"
"
></canvas>
<canvas
id=
"resultChart"
"
></canvas>
...
@@ -49,13 +71,14 @@
...
@@ -49,13 +71,14 @@
<script
type=
"text/javascript"
>
<script
type=
"text/javascript"
>
// Page globals
// Page globals
var
modelMetaData
=
undefined
;
var
modelMetaData
=
undefined
;
var
weatherDatasource
=
undefined
;
var
currentWeatherDatasource
=
undefined
;
var
currentForecastWeatherDatasource
=
undefined
;
var
weatherDatasources
=
undefined
;
var
weatherDatasources
=
undefined
;
var
editor
=
undefined
;
var
editor
=
undefined
;
const
selectList
=
document
.
getElementById
(
"
weatherStationId
"
);
var
selectList
=
document
.
getElementById
(
"
weatherStationId
"
);
var
weatherData
=
undefined
;
var
weatherData
=
undefined
;
async
function
initPage
()
{
async
function
initPage
()
{
modelMetaData
=
await
getModelMetadata
(
"
adas.dss
"
,
"
HAPDMA
"
);
modelMetaData
=
await
getModelMetadata
(
"
adas.dss
"
,
"
HAPDMA
"
);
document
.
getElementById
(
"
modelDescription
"
).
innerHTML
=
await
modelMetaData
[
"
description
"
];
document
.
getElementById
(
"
modelDescription
"
).
innerHTML
=
await
modelMetaData
[
"
description
"
];
...
@@ -71,32 +94,90 @@
...
@@ -71,32 +94,90 @@
let
fullSchema
=
JSON
.
parse
(
modelMetaData
[
"
execution
"
][
"
input_schema
"
]);
let
fullSchema
=
JSON
.
parse
(
modelMetaData
[
"
execution
"
][
"
input_schema
"
]);
if
(
fullSchema
[
"
properties
"
][
"
weatherData
"
]
!==
undefined
)
if
(
fullSchema
[
"
properties
"
][
"
weatherData
"
]
!==
undefined
)
{
{
//console.info("Adding weather stations");
// Pull weather stations from web service, render list
// Pull weather data sources from web service, render lists (historic and forecast sources, some are both)
weatherDatasource
=
await
getWeatherDatasource
(
"
no.nibio.lmt
"
);
weatherDatasources
=
await
getWeatherDatasources
();
weatherDatasources
=
await
getWeatherDatasources
();
console
.
info
(
weatherDatasources
);
console
.
info
(
weatherDatasources
);
stationList
=
await
getWeatherStationList
(
weatherDatasource
);
weatherDatasources
.
sort
((
a
,
b
)
=>
{
stationList
.
sort
((
a
,
b
)
=>
{
return
(
a
.
name
<
b
.
name
)
?
-
1
:
(
a
.
name
>
b
.
name
)
?
1
:
0
;
return
(
a
.
name
<
b
.
name
)
?
-
1
:
(
a
.
name
>
b
.
name
)
?
1
:
0
;
});
});
let
weatherDatasourceList
=
document
.
getElementById
(
"
weatherDatasourceList
"
);
for
(
let
i
=
0
;
i
<
stationList
.
length
;
i
++
)
weatherDatasourceList
.
add
(
new
Option
(
"
Please select a weather datasource
"
,
"
-1
"
));
for
(
let
i
=
0
;
i
<
weatherDatasources
.
length
;
i
++
)
{
{
selectList
.
add
(
new
Option
(
stationList
[
i
].
name
,
stationList
[
i
].
id
))
if
(
weatherDatasources
[
i
].
temporal
.
historic
!=
null
&&
weatherDatasources
[
i
].
temporal
.
historic
.
start
!=
null
)
{
weatherDatasourceList
.
add
(
new
Option
(
weatherDatasources
[
i
].
name
,
weatherDatasources
[
i
].
id
));
}
}
let
forecastWeatherDatasourceList
=
document
.
getElementById
(
"
forecastWeatherDatasourceList
"
);
forecastWeatherDatasourceList
.
add
(
new
Option
(
"
Please select a weather forecast datasource
"
,
"
-1
"
));
for
(
let
i
=
0
;
i
<
weatherDatasources
.
length
;
i
++
)
{
if
(
weatherDatasources
[
i
].
temporal
.
forecast
!=
null
&&
weatherDatasources
[
i
].
temporal
.
forecast
>
0
)
{
forecastWeatherDatasourceList
.
add
(
new
Option
(
weatherDatasources
[
i
].
name
,
weatherDatasources
[
i
].
id
));
}
}
}
document
.
getElementById
(
"
weatherStations
"
).
style
.
display
=
"
block
"
;
console
.
info
(
weatherDatasource
);
document
.
getElementById
(
"
weatherDataForm
"
).
style
.
display
=
"
block
"
;
}
}
// TODO: Remove this auto-mock!!
// TODO: Remove this auto-mock!!
editor
.
getValue
().
optionalData
.
startDate
=
"
2023-08-01
"
;
editor
.
getValue
().
optionalData
.
startDate
=
"
2023-08-01
"
;
editor
.
getValue
().
optionalData
.
endDate
=
"
2023-08-10
"
;
editor
.
getValue
().
optionalData
.
endDate
=
"
2023-08-10
"
;
submitData
();
document
.
getElementById
(
"
longitude
"
).
value
=
"
11.781989
"
;
document
.
getElementById
(
"
latitude
"
).
value
=
"
59.680468
"
;
//submitData();
}
}
initPage
();
initPage
();
function
handleWeatherDatasourceSelected
(
weatherDatasourceList
){
currentWeatherDatasource
=
getWeatherDatasource
(
weatherDatasources
,
weatherDatasourceList
.
options
[
weatherDatasourceList
.
selectedIndex
].
value
);
let
sourceInfo
=
document
.
getElementById
(
"
historicSourceInfo
"
);
sourceInfo
.
innerHTML
=
currentWeatherDatasource
.
description
;
sourceInfo
.
style
.
display
=
"
block
"
;
if
(
currentWeatherDatasource
.
access_type
==
"
stations
"
)
{
// Display the weather stations
renderWeatherStationSelectList
(
getWeatherStationList
(
currentWeatherDatasource
),
selectList
);
document
.
getElementById
(
"
stationFields
"
).
style
.
display
=
"
block
"
;
}
else
{
// Location based API
// Display lat/lon input fields
document
.
getElementById
(
"
stationFields
"
).
style
.
display
=
"
none
"
;
// TODO: Add map?
}
console
.
info
(
currentWeatherDatasource
);
}
function
handleForecastSourceSelected
(
forecastSourceSelectList
)
{
currentForecastWeatherDatasource
=
getWeatherDatasource
(
weatherDatasources
,
forecastWeatherDatasourceList
.
options
[
forecastWeatherDatasourceList
.
selectedIndex
].
value
);
let
sourceInfo
=
document
.
getElementById
(
"
historicSourceInfo
"
);
sourceInfo
.
innerHTML
=
currentWeatherDatasource
.
description
;
sourceInfo
.
style
.
display
=
"
block
"
;
}
function
handleWeatherStationSelected
(
weatherStationSelectList
)
{
let
weatherStationId
=
selectList
.
options
[
selectList
.
selectedIndex
].
value
;
let
stationCoordinate
=
getWeatherStationCoordinate
(
currentWeatherDatasource
,
weatherStationId
);
console
.
info
(
stationCoordinate
);
document
.
getElementById
(
"
longitude
"
).
value
=
stationCoordinate
[
0
];
document
.
getElementById
(
"
latitude
"
).
value
=
stationCoordinate
[
1
];
}
async
function
submitData
(){
async
function
submitData
(){
console
.
info
(
"
submitData!
"
);
console
.
info
(
"
submitData!
"
);
...
@@ -115,24 +196,92 @@
...
@@ -115,24 +196,92 @@
if
(
fullSchema
[
"
properties
"
][
"
weatherData
"
]
!==
undefined
)
if
(
fullSchema
[
"
properties
"
][
"
weatherData
"
]
!==
undefined
)
{
{
console
.
info
(
"
Need to get weather data!
"
);
console
.
info
(
"
Need to get weather data!
"
);
let
weatherStationId
=
selectList
.
options
[
selectList
.
selectedIndex
].
value
;
let
forecastData
=
undefined
;
// 1. Historic weather data
if
(
currentWeatherDatasource
!=
undefined
)
{
if
(
currentWeatherDatasource
.
access_type
==
"
stations
"
)
{
let
weatherStationId
=
selectList
.
options
[
selectList
.
selectedIndex
].
value
;
weatherData
=
await
getLocationWeatherData
(
weatherData
=
await
getStationWeatherData
(
weatherDatasource
.
endpoint
,
getWeatherDatasourceEndpoint
(
currentWeatherDatasource
),
weatherStationId
,
weatherStationId
,
(
function
(){
getPragmaticWeatherParameterList
(
let
parameterList
=
[]
function
(){
modelMetaData
.
input
.
weather_parameters
.
forEach
(
function
(
weatherParameter
){
let
parameterList
=
[]
parameterList
.
push
(
weatherParameter
.
parameter_code
)
modelMetaData
.
input
.
weather_parameters
.
forEach
(
function
(
weatherParameter
){
})
parameterList
.
push
(
weatherParameter
.
parameter_code
)
return
parameterList
;
})
}()),
return
parameterList
;
3600
,
}(),
inputData
.
optionalData
.
startDate
,
currentWeatherDatasource
.
parameters
.
common
inputData
.
optionalData
.
endDate
,
),
);
3600
,
inputData
.
optionalData
.
startDate
,
inputData
.
optionalData
.
endDate
,
);
}
else
{
weatherData
=
await
getLocationWeatherData
(
getWeatherDatasourceEndpoint
(
currentWeatherDatasource
),
document
.
getElementById
(
"
longitude
"
).
value
,
document
.
getElementById
(
"
latitude
"
).
value
,
getPragmaticWeatherParameterList
(
function
(){
let
parameterList
=
[]
modelMetaData
.
input
.
weather_parameters
.
forEach
(
function
(
weatherParameter
){
parameterList
.
push
(
weatherParameter
.
parameter_code
)
})
return
parameterList
;
}(),
currentWeatherDatasource
.
parameters
.
common
),
3600
,
inputData
.
optionalData
.
startDate
,
inputData
.
optionalData
.
endDate
,
);
}
}
// 2. Forecast weather data
if
(
currentForecastWeatherDatasource
!=
undefined
)
{
forecastData
=
await
getLocationWeatherData
(
getWeatherDatasourceEndpoint
(
currentForecastWeatherDatasource
),
document
.
getElementById
(
"
longitude
"
).
value
,
document
.
getElementById
(
"
latitude
"
).
value
,
getPragmaticWeatherParameterList
(
function
(){
let
parameterList
=
[]
modelMetaData
.
input
.
weather_parameters
.
forEach
(
function
(
weatherParameter
){
parameterList
.
push
(
weatherParameter
.
parameter_code
)
})
return
parameterList
;
}(),
currentForecastWeatherDatasource
.
parameters
.
common
),
3600
,
inputData
.
optionalData
.
startDate
,
inputData
.
optionalData
.
endDate
,
);
// Merge if both historic and forecast data have been collected
if
(
weatherData
==
undefined
)
{
weatherData
=
forecastData
;
}
else
{
// Is NULL until method is implemented
weatherData
=
mergeWeatherData
(
weatherData
,
forecastData
);
}
}
inputData
[
"
weatherData
"
]
=
weatherData
;
inputData
[
"
weatherData
"
]
=
weatherData
;
console
.
info
(
weatherData
);
//
console.info(weatherData);
}
}
// Ready to call server?
// Ready to call server?
//console.info(JSON.stringify(inputData));
//console.info(JSON.stringify(inputData));
...
@@ -204,6 +353,8 @@
...
@@ -204,6 +353,8 @@
}
}
// Mock result!!! Waiting for ADAS to fix CORS issue
// Mock result!!! Waiting for ADAS to fix CORS issue
const
mockResult
=
{
const
mockResult
=
{
"
timeStart
"
:
"
2023-06-30T22:00:00+00:00
"
,
"
timeStart
"
:
"
2023-06-30T22:00:00+00:00
"
,
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment