diff --git a/deployment/ansible/group_vars/all b/deployment/ansible/group_vars/all
index 08426ebf5..474a00072 100644
--- a/deployment/ansible/group_vars/all
+++ b/deployment/ansible/group_vars/all
@@ -20,7 +20,7 @@ postgresql_support_repository_channel: "main"
postgresql_support_libpq_version: "13.*.pgdg20.04+1"
postgresql_support_psycopg2_version: "2.8.*"
postgis_version: "3"
-postgis_package_version: "3.2*pgdg20.04+1"
+postgis_package_version: "3.3*pgdg20.04+1"
daemontools_version: "1:0.76-7"
diff --git a/deployment/ansible/roles/model-my-watershed.app/tasks/dev-and-test-dependencies.yml b/deployment/ansible/roles/model-my-watershed.app/tasks/dev-and-test-dependencies.yml
index f1df9d8d1..5053fa062 100644
--- a/deployment/ansible/roles/model-my-watershed.app/tasks/dev-and-test-dependencies.yml
+++ b/deployment/ansible/roles/model-my-watershed.app/tasks/dev-and-test-dependencies.yml
@@ -1,6 +1,6 @@
---
- name: Install Firefox for UI tests
- apt: pkg="firefox=9*" state=present
+ apt: pkg="firefox" state=present
- name: Install Xvfb for JavaScript tests
apt: pkg="xvfb=2:1.20.*" state=present
diff --git a/src/mmw/apps/geoprocessing_api/schemas.py b/src/mmw/apps/geoprocessing_api/schemas.py
index 006ef4a49..44fd327c5 100644
--- a/src/mmw/apps/geoprocessing_api/schemas.py
+++ b/src/mmw/apps/geoprocessing_api/schemas.py
@@ -192,11 +192,11 @@
)
nlcd_override_allowed_values = '", "'.join([
- 'nlcd-2019-30m-epsg5070-512-byte',
- 'nlcd-2016-30m-epsg5070-512-byte',
- 'nlcd-2011-30m-epsg5070-512-byte',
- 'nlcd-2006-30m-epsg5070-512-byte',
- 'nlcd-2001-30m-epsg5070-512-byte',
+ 'nlcd-2019-30m-epsg5070-512-uint8raw',
+ 'nlcd-2016-30m-epsg5070-512-uint8raw',
+ 'nlcd-2011-30m-epsg5070-512-uint8raw',
+ 'nlcd-2006-30m-epsg5070-512-uint8raw',
+ 'nlcd-2001-30m-epsg5070-512-uint8raw',
'nlcd-2011-30m-epsg5070-512-int8',
])
LAYER_OVERRIDES = Schema(
@@ -209,12 +209,12 @@
properties={
'__LAND__': Schema(
type=TYPE_STRING,
- example='nlcd-2019-30m-epsg5070-512-byte',
+ example='nlcd-2019-30m-epsg5070-512-uint8raw',
description='The NLCD layer to use. Valid options are: '
- f'"{nlcd_override_allowed_values}". All "-byte" '
+ f'"{nlcd_override_allowed_values}". All "-uint8raw" '
'layers are from the NLCD19 product. The "-int8" '
'layer is from the NLCD11 product. The default value '
- 'is NLCD19 2019 "nlcd-2019-30m-epsg5070-512-byte".',
+ 'is NLCD19 2019 "nlcd-2019-30m-epsg5070-512-uint8raw".'
),
'__STREAMS__': Schema(
type=TYPE_STRING,
diff --git a/src/mmw/apps/geoprocessing_api/views.py b/src/mmw/apps/geoprocessing_api/views.py
index 830840ffd..9a7385d10 100644
--- a/src/mmw/apps/geoprocessing_api/views.py
+++ b/src/mmw/apps/geoprocessing_api/views.py
@@ -426,7 +426,7 @@ def start_analyze_land(request, nlcd_year, format=None):
nlcd, year = nlcd_year.split('_')
if nlcd == '2019' and year in ['2019', '2016', '2011', '2006', '2001']:
- layer_overrides['__LAND__'] = f'nlcd-{year}-30m-epsg5070-512-byte'
+ layer_overrides['__LAND__'] = f'nlcd-{year}-30m-epsg5070-512-uint8raw'
return start_celery_job([
geoprocessing.run.s('nlcd_ara', geop_input, wkaoi,
diff --git a/src/mmw/apps/home/views.py b/src/mmw/apps/home/views.py
index 53cc0e6c8..e2b5dbcdb 100644
--- a/src/mmw/apps/home/views.py
+++ b/src/mmw/apps/home/views.py
@@ -340,6 +340,7 @@ def get_client_settings(request):
'stream_layers': create_layer_config_with_urls('stream'),
'nhd_perimeter': settings.NHD_REGION2_PERIMETER,
'conus_perimeter': settings.CONUS_PERIMETER,
+ 'drwi_simple_perimeter': settings.DRWI_SIMPLE_PERIMETER_JSON,
'draw_tools': settings.DRAW_TOOLS,
'map_controls': settings.MAP_CONTROLS,
'vizer_urls': settings.VIZER_URLS,
diff --git a/src/mmw/apps/modeling/calcs.py b/src/mmw/apps/modeling/calcs.py
index bf383863d..383588516 100644
--- a/src/mmw/apps/modeling/calcs.py
+++ b/src/mmw/apps/modeling/calcs.py
@@ -400,7 +400,7 @@ def get_layer_value(layer, layer_overrides=dict):
If the default config is something like:
{
- '__LAND__': 'nlcd-2019-30m-epsg5070-512-byte',
+ '__LAND__': 'nlcd-2019-30m-epsg5070-512-uint8raw',
'__SOIL__': 'ssurgo-hydro-groups-30m-epsg5070-512-int8',
'__STREAMS__': 'nhd',
}
diff --git a/src/mmw/apps/modeling/migrations/0041_clear_nlcd2019_gwlfe_results.py b/src/mmw/apps/modeling/migrations/0041_clear_nlcd2019_gwlfe_results.py
new file mode 100644
index 000000000..58def7406
--- /dev/null
+++ b/src/mmw/apps/modeling/migrations/0041_clear_nlcd2019_gwlfe_results.py
@@ -0,0 +1,45 @@
+# Generated by Django 3.2.13 on 2022-10-17 13:47
+
+from django.db import migrations
+
+
+def clear_nlcd2019_gwlfe_results(apps, schema_editor):
+ """
+ Clear the results for all scenarios belonging to GWLF-E projects made after
+ the release of 1.33.0, which had incorrectly aligned NLCD19 2019 on
+ 2022-01-17:
+ https://github.com/WikiWatershed/model-my-watershed/releases/tag/1.33.0
+
+ These results will be recalculated with the correclty aligned NLCD19 values
+ when these projects are accessed again.
+ """
+ Project = apps.get_model('modeling', 'Project')
+ Scenario = apps.get_model('modeling', 'Scenario')
+
+ Project.objects.filter(
+ model_package='gwlfe',
+ created_at__gte='2022-01-17',
+ ).update(
+ gis_data=None,
+ mapshed_job_uuid=None,
+ subbasin_mapshed_job_uuid=None,
+ )
+
+ Scenario.objects.filter(
+ project__model_package='gwlfe',
+ project__created_at__gte='2022-01-17',
+ ).update(
+ results='[]',
+ modification_hash='',
+ )
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('modeling', '0040_clear_nlcd2019_tr55_results'),
+ ]
+
+ operations = [
+ migrations.RunPython(clear_nlcd2019_gwlfe_results),
+ ]
diff --git a/src/mmw/apps/modeling/models.py b/src/mmw/apps/modeling/models.py
index 8ad5299a3..847fa3586 100644
--- a/src/mmw/apps/modeling/models.py
+++ b/src/mmw/apps/modeling/models.py
@@ -82,6 +82,10 @@ def __unicode__(self):
def in_drb(self):
return self.area_of_interest.within(settings.DRB_SIMPLE_PERIMETER)
+ @property
+ def in_drwi(self):
+ return self.area_of_interest.within(settings.DRWI_SIMPLE_PERIMETER)
+
class WeatherType:
diff --git a/src/mmw/apps/modeling/serializers.py b/src/mmw/apps/modeling/serializers.py
index 49ffcb543..90e3931b6 100644
--- a/src/mmw/apps/modeling/serializers.py
+++ b/src/mmw/apps/modeling/serializers.py
@@ -112,7 +112,7 @@ class Meta:
'scenarios', 'model_package', 'created_at', 'modified_at',
'is_private', 'is_activity', 'gis_data', 'mapshed_job_uuid',
'subbasin_mapshed_job_uuid', 'wkaoi', 'user', 'hydroshare',
- 'in_drb', 'layer_overrides')
+ 'in_drb', 'in_drwi', 'layer_overrides')
user = UserSerializer(default=serializers.CurrentUserDefault())
gis_data = JsonField(required=False, allow_null=True)
diff --git a/src/mmw/apps/modeling/views.py b/src/mmw/apps/modeling/views.py
index 7d743ca9d..cc8b94a3b 100644
--- a/src/mmw/apps/modeling/views.py
+++ b/src/mmw/apps/modeling/views.py
@@ -141,10 +141,13 @@ def project_weather(request, proj_id, category):
return Response({'errors': ['Invalid category specified.']},
status=status.HTTP_400_BAD_REQUEST)
- # This applies to all current weather categories. If in the future there
- # are categories to which it doesn't apply, this will have to be further
- # qualified.
- if not project.in_drb:
+ if category == 'NASA_NLDAS_2000_2019' and not project.in_drwi:
+ return Response({'errors': ['Only supported within'
+ ' Delware River Watershed Initiative.']},
+ status=status.HTTP_400_BAD_REQUEST)
+
+ if category in ['RCP45_2080_2099', 'RCP85_2080_2099'] \
+ and not project.in_drb:
return Response({'errors': ['Only supported within'
' Delware River Basin.']},
status=status.HTTP_400_BAD_REQUEST)
diff --git a/src/mmw/js/src/analyze/models.js b/src/mmw/js/src/analyze/models.js
index 00599a39d..9c54a0651 100644
--- a/src/mmw/js/src/analyze/models.js
+++ b/src/mmw/js/src/analyze/models.js
@@ -76,6 +76,7 @@ var AnalyzeTaskModel = coreModels.TaskModel.extend({
token: settings.get('api_token'),
// Include this task in Catalog Search results (ie, BigCZ)
enabledForCatalogMode: false,
+ lazy: false, // Will not execute immediately if lazy is true
}, coreModels.TaskModel.prototype.defaults
),
@@ -167,11 +168,13 @@ var AnalyzeTaskGroupModel = Backbone.Model.extend({
/**
* Returns a promise that completes when Analysis has been fetched. If
* fetching is not required, returns an immediatley resolved promise.
+ * Skips lazy analyses, which should be triggered explicitly on the task.
*/
fetchAnalysisIfNeeded: function() {
- var taskAnalysisFetches = this.get('tasks').map(function(t) {
- return t.fetchAnalysisIfNeeded();
- });
+ var taskAnalysisFetches =
+ this.get('tasks')
+ .filter(function(t) { return !t.get('lazy'); })
+ .map(function(t) { return t.fetchAnalysisIfNeeded(); });
return $.when.apply($, taskAnalysisFetches);
},
@@ -220,18 +223,19 @@ function createAnalyzeTaskGroupCollection(aoi, wkaoi) {
displayName: "Streams",
tasks: [
{
- name: "streams_nhdhr",
- displayName: "NHD High Resolution Streams",
+ name: "streams_nhd",
+ displayName: "NHD Medium Resolution Streams",
area_of_interest: aoi,
wkaoi: wkaoi,
- taskName: "analyze/streams/nhdhr"
+ taskName: "analyze/streams/nhd",
},
{
- name: "streams_nhd",
- displayName: "NHD Medium Resolution Streams",
+ name: "streams_nhdhr",
+ displayName: "NHD High Resolution Streams",
area_of_interest: aoi,
wkaoi: wkaoi,
- taskName: "analyze/streams/nhd"
+ taskName: "analyze/streams/nhdhr",
+ lazy: true,
},
]
},
diff --git a/src/mmw/js/src/analyze/views.js b/src/mmw/js/src/analyze/views.js
index 1a7405f39..84dcf0eec 100644
--- a/src/mmw/js/src/analyze/views.js
+++ b/src/mmw/js/src/analyze/views.js
@@ -1568,6 +1568,7 @@ var TaskSelectorView = Marionette.ItemView.extend({
updateTask: function() {
var taskName = this.ui.selector.val();
this.model.setActiveTask(taskName);
+ this.model.get('activeTask').fetchAnalysisIfNeeded();
}
});
diff --git a/src/mmw/js/src/core/utils.js b/src/mmw/js/src/core/utils.js
index 4c483f50d..3ab57907c 100644
--- a/src/mmw/js/src/core/utils.js
+++ b/src/mmw/js/src/core/utils.js
@@ -575,16 +575,27 @@ var utils = {
}
},
- // Check if a geom is completely within DRB_SIMPLE_PERIMETER
- isInDrb: _.memoize(function(geom) {
- var layers = settings.get('stream_layers'),
- drb = _.find(layers, {code: 'drb_streams_v2'}).perimeter,
- coordCount = this.coordinates(geom).length,
- intersection = intersect(geom, drb),
+ _containedIn: function(perimeter, geom) {
+ var coordCount = this.coordinates(geom).length,
+ intersection = intersect(geom, perimeter),
intersectionCount = intersection &&
this.coordinates(intersection.geometry).length;
return intersection && coordCount === intersectionCount;
+ },
+
+ isInDrb: _.memoize(function(geom) {
+ var DRB_SIMPLE_PERIMETER =
+ _.find(settings.get('stream_layers'),
+ {code: 'drb_streams_v2'}).perimeter;
+
+ return this._containedIn(DRB_SIMPLE_PERIMETER, geom);
+ }),
+
+ isInDrwi: _.memoize(function(geom) {
+ var DRWI_SIMPLE_PERIMETER = settings.get('drwi_simple_perimeter');
+
+ return this._containedIn(DRWI_SIMPLE_PERIMETER, geom);
}),
// Calculates a range from 0 to the upper bound
diff --git a/src/mmw/js/src/modeling/constants.js b/src/mmw/js/src/modeling/constants.js
index a34410532..e210ff081 100644
--- a/src/mmw/js/src/modeling/constants.js
+++ b/src/mmw/js/src/modeling/constants.js
@@ -27,16 +27,16 @@ module.exports = {
},
// In sync with apps.modeling.models.WeatherType.simulations
Simulations: [
- // {
- // group: 'Recent Weather',
- // items: [
- // {
- // name: 'NASA_NLDAS_2000_2019',
- // label: 'NASA NLDAS 2000-2019',
- // },
- // ],
- // in_drb: true,
- // },
+ {
+ group: 'Recent Weather',
+ items: [
+ {
+ name: 'NASA_NLDAS_2000_2019',
+ label: 'NASA NLDAS 2000-2019',
+ },
+ ],
+ in_drwi: true,
+ },
{
group: 'Future Weather Simulations',
items: [
diff --git a/src/mmw/js/src/modeling/controllers.js b/src/mmw/js/src/modeling/controllers.js
index ee34137ea..80fef3f60 100644
--- a/src/mmw/js/src/modeling/controllers.js
+++ b/src/mmw/js/src/modeling/controllers.js
@@ -132,6 +132,7 @@ var ModelingController = {
model_package: modelPackage,
scenarios: new models.ScenariosCollection(),
in_drb: utils.isInDrb(App.map.get('areaOfInterest')),
+ in_drwi: utils.isInDrwi(App.map.get('areaOfInterest')),
});
App.currentProject = project;
diff --git a/src/mmw/js/src/modeling/gwlfe/weather/models.js b/src/mmw/js/src/modeling/gwlfe/weather/models.js
index 2f5e81a8f..fe9b9247f 100644
--- a/src/mmw/js/src/modeling/gwlfe/weather/models.js
+++ b/src/mmw/js/src/modeling/gwlfe/weather/models.js
@@ -9,6 +9,7 @@ var WindowModel = Backbone.Model.extend({
defaults: {
project_id: null, // Must be specified
in_drb: false,
+ in_drwi: false,
scenario_id: null, // Must be specified
weather_type: WeatherType.DEFAULT,
available_data: 'DEFAULT',
diff --git a/src/mmw/js/src/modeling/gwlfe/weather/templates/modal.html b/src/mmw/js/src/modeling/gwlfe/weather/templates/modal.html
index d2a6d9ad9..8fdf51784 100644
--- a/src/mmw/js/src/modeling/gwlfe/weather/templates/modal.html
+++ b/src/mmw/js/src/modeling/gwlfe/weather/templates/modal.html
@@ -32,9 +32,9 @@
{% for s in Simulations %}
-