Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ufz-sdi/spatialio
1 result
Show changes
Commits on Source (9)
Showing
with 111 additions and 55 deletions
...@@ -18,7 +18,7 @@ FROST_POSTGRES_PASSWORD=admin ...@@ -18,7 +18,7 @@ FROST_POSTGRES_PASSWORD=admin
INITIAL_MEMORY=2G INITIAL_MEMORY=2G
MAXIMUM_MEMORY=4G MAXIMUM_MEMORY=4G
GEOSERVER_URL=http://geoserver:8080/geoserver GEOSERVER_URL=http://geoserver:8080/geoserver/
GEOSERVER_USERNAME=admin GEOSERVER_USERNAME=admin
GEOSERVER_PASSWORD=geoserver GEOSERVER_PASSWORD=geoserver
......
...@@ -2,11 +2,11 @@ import os ...@@ -2,11 +2,11 @@ import os
import requests import requests
from requests.adapters import HTTPAdapter from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry # noqa from requests.packages.urllib3.util.retry import Retry # noqa
from xml.etree import ElementTree
import json import json
from geoserver.catalog import Catalog # noqa from geoserver.catalog import Catalog # noqa
from owslib.wms import WebMapService # noqa
GEOSERVER_MOSAIC_DIR = "/opt/geoserver/data_dir/mosaic" GEOSERVER_MOSAIC_DIR = "/opt/geoserver/data_dir/mosaic"
...@@ -195,24 +195,27 @@ class GeoServerApi: ...@@ -195,24 +195,27 @@ class GeoServerApi:
self.log("Time dimension for coverage {} could not be enabled: {}".format(native_name, e)) self.log("Time dimension for coverage {} could not be enabled: {}".format(native_name, e))
self.has_error = True self.has_error = True
def get_wms_timesteps(self, workspace, datastore_name): def get_wms_timesteps(self, workspace, layer_name):
wms_url = '{}/{}/ows?service=wms&version=1.3.0&request=GetCapabilities'.format(os.environ.get("GEOSERVER_URL"), workspace) wms_url = '{}/ows?service=wms&version=1.3.0&request=GetCapabilities&namespace={}'.format(os.environ.get("GEOSERVER_URL"), workspace)
try: try:
wms = WebMapService(wms_url, version='1.3.0') response = self.session.get(wms_url)
xml = ElementTree.fromstring(response.text)
# iterate all available wms 'LAYERS' which exist in the workspace
for wms_variable in list(wms.contents): for item in xml.findall(".//{http://www.opengis.net/wms}Layer"):
if datastore_name == wms_variable: if item.get("queryable") is not None:
time_steps = wms.contents[datastore_name].timepositions
if time_steps is None: name = item.find('{http://www.opengis.net/wms}Name').text
return [] if name == layer_name:
else: for dimension in item.findall("{http://www.opengis.net/wms}Dimension"):
self.log("Layer-timesteps fetched") if dimension.get('name') == 'time':
return time_steps time_steps = dimension.text.strip()
self.log("Layer-timesteps fetched")
return time_steps.split(',')
return []
except Exception as e: except Exception as e:
self.log("Could not fetch timesteps {}: {}".format(datastore_name, str(e))) self.log("Could not fetch timesteps {}: {}".format(layer_name, str(e)))
self.has_error = True self.has_error = True
def delete_datastore(self, workspace, data_store, store_type='coveragestores'): def delete_datastore(self, workspace, data_store, store_type='coveragestores'):
...@@ -227,3 +230,34 @@ class GeoServerApi: ...@@ -227,3 +230,34 @@ class GeoServerApi:
except Exception as e: except Exception as e:
self.log("Error in deleting datastore {}: {}".format(data_store, e)) self.log("Error in deleting datastore {}: {}".format(data_store, e))
self.has_error = True self.has_error = True
def add_allowed_url(self, title, allowed_url):
url = "{}urlchecks".format(self.url)
headers = {"content-type": "application/xml"}
# ^https://minio.ufz.de.*$
body = (
"<regexUrlCheck>"
"<name>" + title + "</name>"
"<description></description>"
"<enabled>true</enabled>"
"<regex>^" + allowed_url + ".*$</regex>"
"</regexUrlCheck>"
)
try:
response = self.session.post(
url,
data=body,
auth=(self.username, self.password),
headers=headers,
timeout=5
)
if response.status_code not in [200, 201]:
print("Error in setting url-check: {}".format(response.content))
else:
print("Adding URL-Check successful: {}".format(allowed_url))
except Exception as e:
print("Error in setting url-check: {}".format(e))
...@@ -66,7 +66,14 @@ class Command(BaseCommand): ...@@ -66,7 +66,14 @@ class Command(BaseCommand):
bucket2.geonetwork_group = geonetwork_api.create_group("test-group2") bucket2.geonetwork_group = geonetwork_api.create_group("test-group2")
bucket2.save() bucket2.save()
print("\nStep 4: Import Netcdf-files")
print("\nStep 4: Configure GeoServer")
geoserver_api = GeoServerApi()
geoserver_api.add_allowed_url("Minio", "http://minio:9000")
print("\nStep 5: Import Netcdf-files")
import_file_to_minio(BUCKET_NAME, "https://minio.ufz.de/rdm/sdi-test-data/drought.nc", "drought.nc", "drought") import_file_to_minio(BUCKET_NAME, "https://minio.ufz.de/rdm/sdi-test-data/drought.nc", "drought.nc", "drought")
import_file_to_minio(BUCKET_NAME, "https://minio.ufz.de/rdm/sdi-test-data/precipitation.nc", "precipitation.nc", "pre") import_file_to_minio(BUCKET_NAME, "https://minio.ufz.de/rdm/sdi-test-data/precipitation.nc", "precipitation.nc", "pre")
...@@ -74,9 +81,7 @@ class Command(BaseCommand): ...@@ -74,9 +81,7 @@ class Command(BaseCommand):
import_file_to_minio(BUCKET_NAME, "https://minio.ufz.de/rdm/sdi-test-data/pre_1950_2021_monsum.nc", "pre_1950_2021_monsum.nc", "pre_1950_2021_monsum") import_file_to_minio(BUCKET_NAME, "https://minio.ufz.de/rdm/sdi-test-data/pre_1950_2021_monsum.nc", "pre_1950_2021_monsum.nc", "pre_1950_2021_monsum")
print("\nStep 5: Configure GeoServer") print("\nStep 6: Configure Layer in GeoServer")
geoserver_api = GeoServerApi()
for legend in WmsLegend.objects.all(): for legend in WmsLegend.objects.all():
sld = create_sld_file(legend, "de") sld = create_sld_file(legend, "de")
...@@ -100,16 +105,16 @@ class Command(BaseCommand): ...@@ -100,16 +105,16 @@ class Command(BaseCommand):
geoserver_api.add_style(style_name_en, layer.layer_name) geoserver_api.add_style(style_name_en, layer.layer_name)
print("\nStep 6: Upload GeoJson-File") print("\nStep 7: Upload GeoJson-File")
upload_file(BUCKET_NAME, "public/bw.json", "main/geojson/districts/08_admin.geojson") upload_file(BUCKET_NAME, "public/bw.json", "main/geojson/districts/08_admin.geojson")
print("\nStep 7: Upload Metadata-Json-File") print("\nStep 8: Upload Metadata-Json-File")
upload_file(BUCKET_NAME, "drought/metadata.jsonld", "main/fixtures/metadata.jsonld") upload_file(BUCKET_NAME, "drought/metadata.jsonld", "main/fixtures/metadata.jsonld")
print("\nStep 8: Import STA-Data") print("\nStep 9: Import STA-Data")
import_file_to_minio(BUCKET_NAME, "https://minio.ufz.de/rdm/sdi-test-data/wis-d_input_last_14_D.csv", "wis-d_input_last_14_D.csv", "sta") import_file_to_minio(BUCKET_NAME, "https://minio.ufz.de/rdm/sdi-test-data/wis-d_input_last_14_D.csv", "wis-d_input_last_14_D.csv", "sta")
print("\nStep 9: Import Shapefile Data") print("\nStep 10: Import Shapefile Data")
import_file_to_minio(BUCKET_NAME, "https://minio.ufz.de/rdm/sdi-test-data/shp/cologne_polygon_shp.zip", "cologne_polygon_shp.zip", "shp") import_file_to_minio(BUCKET_NAME, "https://minio.ufz.de/rdm/sdi-test-data/shp/cologne_polygon_shp.zip", "cologne_polygon_shp.zip", "shp")
......
...@@ -16,7 +16,6 @@ xarray==2024.6.0 ...@@ -16,7 +16,6 @@ xarray==2024.6.0
rasterio==1.3.10 rasterio==1.3.10
django-tabbed-changeform-admin==0.1.7 django-tabbed-changeform-admin==0.1.7
pytz==2024.1 pytz==2024.1
OWSLib==0.31.0
netCDF4==1.7.1 netCDF4==1.7.1
h5netcdf==1.3.0 h5netcdf==1.3.0
pyproj==3.6.1 pyproj==3.6.1
......
services: services:
wis-d: wis-d:
image: registry.hzdr.de/ufz-sdi/spatialio/wis-d:3.14.0 image: registry.hzdr.de/ufz-sdi/spatialio/wis-d:3.14.2
build: build:
context: ./../.. context: ./../..
dockerfile: ./container/frontend-prod/Dockerfile-prod dockerfile: ./container/frontend-prod/Dockerfile-prod
......
ARG IMAGE_VERSION=9.0.85-jdk11-temurin-jammy FROM tomcat:9.0.98-jdk17-temurin-jammy@sha256:1f35364892e7d90cc6ccbfe23b03d84791fbaaf4197171ea3cdac6672983de2f
ARG JAVA_HOME=/usr/local/openjdk-11
FROM tomcat:$IMAGE_VERSION
RUN set -eux; \ RUN set -eux; \
apt-get update; \ apt-get update; \
......
...@@ -7,7 +7,7 @@ x-image2: &backend-image ...@@ -7,7 +7,7 @@ x-image2: &backend-image
services: services:
frontend: frontend:
image: ${REPOSITORY}frontend:3.14.1 image: ${REPOSITORY}frontend:3.14.2
build: build:
context: . context: .
dockerfile: ./container/frontend-prod/Dockerfile-prod dockerfile: ./container/frontend-prod/Dockerfile-prod
......
...@@ -513,21 +513,10 @@ ...@@ -513,21 +513,10 @@
<div v-show="showAreaInfoBox" class="infoContent standardScrollbar" v-html="getInfoBoxText"></div> <div v-show="showAreaInfoBox" class="infoContent standardScrollbar" v-html="getInfoBoxText"></div>
<div v-show="showLayerInfo" class="infoContent standardScrollbar" > <div v-show="showLayerInfo" class="infoContent standardScrollbar" >
<p v-html="layerInfoText"></p> <p v-html="layerInfoText"></p>
<br>
<p v-show="stabilityUncertainty || significanceUncertainty"> <br>
<br> <br>
<br> <p v-show="stabilityUncertainty || significanceUncertainty" v-html="$t('message.robustnessText')"></p>
<br>
Hier wird auch die <b>Robustheit der Änderung</b> dargestellt. Dazu werden die Übereinstimmung der Änderungsrichtung (<b>Trendstabilität</b>) sowie die <b>Signifikanz</b> der Änderung verwendet.
Wenn weniger als 2/3 (66%) der Simulationen dieselbe Änderungsrichtung zeigen, werden die entsprechenden Flächen rechtsoben [//] schraffiert.
Die Signifikanz der Änderung beinhaltet den Test, ob zukünftige Änderungen innerhalb oder außerhalb der natürlichen Variabilität liegen.
Eine Klimaänderung ist signifikant, wenn sie gemäß eines sogenannten U-Tests (hier: Wilcoxon Rangsummentest) mit einer Wahrscheinlichkeit von unter 5% mit zufälligen Schwankungen erklärbar ist.
Wenn weniger als die Hälfte (50%) der Simulationen eine signifikante Änderung zeigen, werden die Flächen nach rechtsunten schraffiert [\\].
Schraffierungen in beide Richtungen liefern ebenfalls eine klare Aussage, da statistisch keine Änderung zwischen Vergangenheits- und Zukunftszeitscheibe zu erwarten ist.
<br>
<br>
<b><i>Trendstabilität und Signifikanz können jeweils (de-)aktiviert werden.</i></b>
</p>
</div> </div>
<div v-show="showShapefileInfo"> <div v-show="showShapefileInfo">
......
...@@ -445,7 +445,15 @@ export default defineComponent({ ...@@ -445,7 +445,15 @@ export default defineComponent({
} }
}) })
downloadDataAsCsv(csvContent, this.lat + '_' + this.lon) let titleText = this.timeSeriesCollection[0].name
if (this.$i18n.locale == 'de') {
titleText += ' für die Koordinaten '
} else {
titleText += ' for coordinates at '
}
titleText += this.lat + ' Lat - ' + this.lon + ' Lon'
downloadDataAsCsv(csvContent, titleText)
} }
}, },
computed: { computed: {
......
...@@ -100,6 +100,7 @@ const chartMarginBottom = -0.15 ...@@ -100,6 +100,7 @@ const chartMarginBottom = -0.15
export default defineComponent({ export default defineComponent({
props: { props: {
layerName: String,
dataCollection: Object as PropType<DataCollection>, dataCollection: Object as PropType<DataCollection>,
showChart: Boolean, showChart: Boolean,
printAnnotation: String printAnnotation: String
...@@ -170,11 +171,11 @@ export default defineComponent({ ...@@ -170,11 +171,11 @@ export default defineComponent({
const layoutUpdate = structuredClone(toRaw(this.chart.layout)) const layoutUpdate = structuredClone(toRaw(this.chart.layout))
let titleText = '' let titleText = this.$props.layerName
if (this.$i18n.locale == 'de') { if (this.$i18n.locale == 'de') {
titleText += 'Aggregationswerte für ' titleText += ': Regionale Auswertung für '
} else { } else {
titleText += 'Aggregation results for ' titleText += ': Regional Analysis for '
} }
titleText += this.$props.dataCollection.chartName titleText += this.$props.dataCollection.chartName
...@@ -195,7 +196,7 @@ export default defineComponent({ ...@@ -195,7 +196,7 @@ export default defineComponent({
Plotly.react( plotlyId2, this.timeSeriesCollection, layoutUpdate) Plotly.react( plotlyId2, this.timeSeriesCollection, layoutUpdate)
Plotly.downloadImage(plotlyId2, { Plotly.downloadImage(plotlyId2, {
filename: titleText, filename: titleText.replace(/ /g, '_'),
format: 'png', format: 'png',
height: 450, height: 450,
width: 1200 width: 1200
...@@ -320,7 +321,14 @@ export default defineComponent({ ...@@ -320,7 +321,14 @@ export default defineComponent({
} }
}) })
downloadDataAsCsv(csvContent, this.$props.dataCollection?.chartName) let fileName = 'Aggregation results for '
if (this.$i18n.locale == 'de') {
fileName = 'Aggregationswerte für '
}
fileName += this.$props.layerName + ' ' + this.$props.dataCollection?.chartName
fileName = fileName.replace(/ /g, '_')
downloadDataAsCsv(csvContent, fileName)
} }
}, },
mounted() { mounted() {
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
> >
<ol-style> <ol-style>
<ol-style-stroke color="green" :width="6"></ol-style-stroke> <ol-style-stroke color="green" :width="6"></ol-style-stroke>
<ol-style-fill color="rgba(255,255,255,0.5)"></ol-style-fill> <ol-style-fill color="rgba(255,255,255,0)"></ol-style-fill>
</ol-style> </ol-style>
</ol-interaction-select> </ol-interaction-select>
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
<ol-geom-polygon :coordinates="polygon"></ol-geom-polygon> <ol-geom-polygon :coordinates="polygon"></ol-geom-polygon>
<ol-style> <ol-style>
<ol-style-stroke :color="'red'" :width="8"></ol-style-stroke> <ol-style-stroke :color="'red'" :width="8"></ol-style-stroke>
<ol-style-fill color="rgba(255,255,255,0.5)"></ol-style-fill> <ol-style-fill color="rgba(255,255,255,0)"></ol-style-fill>
</ol-style> </ol-style>
</ol-feature> </ol-feature>
</ol-source-vector> </ol-source-vector>
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
:data-collection="dataCollection" :data-collection="dataCollection"
:show-chart="!isLoading && isSuccess" :show-chart="!isLoading && isSuccess"
:print-annotation="'projectPrintAnnotation'" :print-annotation="'projectPrintAnnotation'"
:layer-name="clickedLayer?.name"
v-if="!isLoading && isSuccess" v-if="!isLoading && isSuccess"
></AggregationChart> ></AggregationChart>
......
...@@ -58,6 +58,7 @@ import { messages } from "./translation/messages" ...@@ -58,6 +58,7 @@ import { messages } from "./translation/messages"
const i18n = createI18n({ const i18n = createI18n({
locale: 'de', locale: 'de',
fallbackLocale: 'de', fallbackLocale: 'de',
warnHtmlInMessage: 'off',
messages messages
}) })
......
...@@ -55,6 +55,13 @@ export const messages = { ...@@ -55,6 +55,13 @@ export const messages = {
relativeDerivationPrecipitation: 'Relative Abweichung in %', relativeDerivationPrecipitation: 'Relative Abweichung in %',
resetMap: 'Karte zurücksetzen', resetMap: 'Karte zurücksetzen',
resetFilters: 'Zurücksetzen', resetFilters: 'Zurücksetzen',
robustnessText: 'Hier wird auch die <b>Robustheit der Änderung</b> dargestellt. Dazu werden die Übereinstimmung der Änderungsrichtung (<b>Trendstabilität</b>) sowie die <b>Signifikanz</b> der Änderung verwendet.' +
'Wenn weniger als 2/3 (66%) der Simulationen dieselbe Änderungsrichtung zeigen, werden die entsprechenden Flächen rechtsoben [//] schraffiert.\n' +
'Die Signifikanz der Änderung beinhaltet den Test, ob zukünftige Änderungen innerhalb oder außerhalb der natürlichen Variabilität liegen.\n' +
'Eine Klimaänderung ist signifikant, wenn sie gemäß eines sogenannten U-Tests (hier: Wilcoxon Rangsummentest) mit einer Wahrscheinlichkeit von unter 5% mit zufälligen Schwankungen erklärbar ist.\n' +
'Wenn weniger als die Hälfte (50%) der Simulationen eine signifikante Änderung zeigen, werden die Flächen nach rechtsunten schraffiert [\\\\].\n' +
'Schraffierungen in beide Richtungen liefern ebenfalls eine klare Aussage, da statistisch keine Änderung zwischen Vergangenheits- und Zukunftszeitscheibe zu erwarten ist.\n' +
'<br><br><b><i>Trendstabilität und Signifikanz können jeweils (de-)aktiviert werden.</i></b>',
save: 'Herunterladen', save: 'Herunterladen',
selectablesAdvanced: 'Erweiterte Werkzeuge', selectablesAdvanced: 'Erweiterte Werkzeuge',
selectablesAreas: 'Bereich', selectablesAreas: 'Bereich',
...@@ -124,7 +131,7 @@ export const messages = { ...@@ -124,7 +131,7 @@ export const messages = {
missingTrendStability: 'Mssing Trend Stability', missingTrendStability: 'Mssing Trend Stability',
noMethodAvailable: 'No method available', noMethodAvailable: 'No method available',
noLayerSelectable: 'No layer selectable', noLayerSelectable: 'No layer selectable',
noPointRequest: 'Climate simulations at this point not significant. Please use analysis by countries, districts or shapefiles for requesting values.', noPointRequest: 'Climate simulations cannot be interpreted at the grid cell level. Please use the regional analysis to define your region of interest.',
pointData: 'Point Data', pointData: 'Point Data',
precipitationAnomaly: 'Precipitation Anomaly', precipitationAnomaly: 'Precipitation Anomaly',
printChart: 'Download diagram as image', printChart: 'Download diagram as image',
...@@ -138,6 +145,13 @@ export const messages = { ...@@ -138,6 +145,13 @@ export const messages = {
relativeDerivationPrecipitation: 'Relative derivation in %', relativeDerivationPrecipitation: 'Relative derivation in %',
resetMap: 'reset map', resetMap: 'reset map',
resetFilters: 'Reset', resetFilters: 'Reset',
robustnessText: 'Additionally, the <b>robustness of the change</b> is shown here. The consistency of the direction of change (<b>trend stability</b>) and <b>the significance</b> of the change are used for this purpose.' +
'If less than 2/3 (66%) of the simulations show the same direction of change, the corresponding areas are shaded at the top right [//].\n' +
'The significance of the change includes the test whether future changes are within or outside the natural variability.\n' +
'A climate change is significant if it can be explained by random fluctuations with a probability of less than 5% according to a so-called U-test (here: Wilcoxon rank sum test).\n' +
'If less than half (50%) of the simulations show a significant change, the areas are shaded to the bottom right [\\].\n' +
'Hatching in both directions also provides a clear statement, as statistically no change between past and future time slices is to be expected.\n' +
'<br><br><b><i>The layers of trend stability and significance can be (de)activated separately.</i></b>',
save: 'Download', save: 'Download',
selectablesAreas: 'Area', selectablesAreas: 'Area',
selectablesAdvanced: 'Advanced tools', selectablesAdvanced: 'Advanced tools',
......