Skip to content

Commit 40740d5

Browse files
Tschoundavidoeschmetaodi
authored
Dev 20241209 merge to v1.3.0 (#109)
* updated CMS path for prod * Update step1_processor_vhi.py HOTFIX: if no data is available exit ON prod fixed with e170eeb * Initial Version of JUPYTER notebooks * fix typo * fixed typos and correted binder to dev * added qgis cog tutorial * First version of VHI * commit all changes * Update main_utils.py Setting default values if an image collection is empty * Update dev_config.py adjusted product name * Update step1_processor_vhi_hist.py - renaming of the bands for Landsat 8 to match the band names of Landsat 5 and 7 - thus removing the L8 specific functions - some adjustements due to errors regarding <str> and <String> between python and GEE * previsous version with different functions for Landsa 5 and 7 vs. Landsat 8 * Deactivate the Export to Drive Switch for debugging * Create vhi-plausability.ipynb * Update step1_processor_vhi_hist.py - taking the variables water_binary and DEM into the functions that need them - improve code for all dates from GEE copies to purely python - fixed the sorting of Landsat collections * Added get_follection_info_landsat function The metadata for landsat collections is differently stored than for sentinel collection, thus a second function retrieving the dates of the first and last image of a collection and the total count of images in the collection for Landsat collections. * Update vhi-plausability.ipynb Added Spearman's Rank Correlation * Remove empty code cell from stac-introduction notebook * Add utility functions for generating CDI and VHI maps * Add detailed documentation for CDI and VHI maps generation script * Fix import statement for geopandas in util_cdi_vhi_maps.py * Add VHI Map Grid Generator script for generating monthly VHI maps * Update step1_processor_vhi_hist.py - fixed the parameter 'left' is required issue: within the function of the topographic correction the linear relation between illumination and reflectance is used. If a band is empty, this correction doesn't work. Thus, there's now a check for the validity of the bands this correction is applied to. If there are empty bands, these are excluded and carried on as they were without the correction. - fixed the incorrect timestamps for start_date and end_date VHI properties, due to a mismatch while translating from JavaScript to python since timestamp() works in number of seconds, and the GEE expects the imestamps in milliseconds. - Further, used to method chaining for applying the pre-processing functions for the Landsat data. * Add VHIExtractor class and CSV processing functions for VHI and mask data extraction * Add documentation and utility functions for tree network data extraction * Update step1_processor_vhi_hist.py Fix the issue of the date for the last day of the month. relativedelta(months=1) instead of .replace([...].month+1) which would end with a 13 * Update dev_config.py for VHI HIST product paths (set to int "step1_collection": 'projects/satromo-int/assets/VHI_HIST_SWISS'); adjust main_utils.py removed breakpoint; update satromo_publish.py to include additional file checks for 30m.tif for warnregions generation; add "collection" metadata for VHI mosaic processing. * Update date references and enhance processing scripts for VHI data handling for thumbnail * Adjusting prod path * Add get_collection_strings function Display only the Landsat collection names from which images where used for the specific asset. * Update date handling in main_extract_warnregions.py for fix of #107 * Changes in getting the collection info * Remove get_collection_strings function Got error 429 too many requests (concurrent aggregations). The collection filtering did not work properly. Decided to post all three Landsat collection in the property 'Collection' because from the 'NDVI_index_list' it is also clear which sensors exactely were used. * Wrong TCI formula corrected * Wrong TCI formula corrected work on the apply_SCSccorr function still ongoing. * Improve error handling/logging for subprocess calls (#108) LGTM * fix cdi colors * Add support for Sentinel-2C acquisition plans and enhance download reporting * Add STAC asset and item deletion script * Remove unused imports in util_stac_delete.py * Updates to the topographic correction - check if bands are empty before applying topographic correction - check if there are unmasked pixels, if everything is masked don't apply topo correction - check if coefficients are valid * New filter_by_valid_pixels function - filter out scenes from the image collection for which the cloud mask does not at least leave 9km2 unmasked * matching 'global_date' to 'datetime' * prepare deploy --------- Co-authored-by: David Oesch <david.oesch@gmail.com> Co-authored-by: Stefan Oderbolz <oderbolz@gmail.com>
1 parent 3794035 commit 40740d5

22 files changed

+4768
-72
lines changed

codegallery/jupyter/Python/stac/stac-introduction.ipynb

+2
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,15 @@
5959
]
6060
},
6161
{
62+
6263
"cell_type": "code",
6364
"execution_count": null,
6465
"metadata": {},
6566
"outputs": [],
6667
"source": []
6768
},
6869
{
70+
6971
"cell_type": "markdown",
7072
"metadata": {},
7173
"source": [

codegallery/jupyter/Python/stac/vhi-plausability.ipynb

+1,427
Large diffs are not rendered by default.

configuration/dev_config.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,14 @@
124124
"geocat_id": "bc4d0e6b-e92e-4f28-a7d2-f41bf61e98bc",
125125
"temporal_coverage": 1, # Months
126126
"spatial_scale_export": 30, # Meters
127-
"product_name": "ch.swisstopo.swisseo_vhi_hist_v100",
127+
"product_name": "ch.swisstopo.swisseo_vhi_v100",
128128
"no_data": 255,
129129
"missing_data": 110,
130130
"asset_size": 2,
131131
'NDVI_reference_data': 'projects/satromo-prod/assets/col/1991-2020_NDVI_SWISS_M',
132132
'LST_reference_data': 'projects/satromo-prod/assets/col/1991-2020_LST_SWISS_M',
133133
'LST_current_data': 'projects/satromo-prod/assets/col/LST_SWISS',
134-
"step1_collection": 'projects/satromo-int/assets/VHI_HIST_SWISS',
134+
"step1_collection": 'projects/satromo-prod/assets/col/VHI_HIST_SWISS',
135135
"step0_collection": 'projects/satromo-prod/assets/col/LST_SWISS'
136136
}
137137

configuration/oed_prod_config.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
"spatial_scale_export_mask": 10,
9090
"product_name": "ch.swisstopo.swisseo_s2-sr_v100",
9191
"no_data": 9999,
92-
#"step0_collection": "projects/satromo-prod/assets/col/S2_SR_HARMONIZED_SWISS"
92+
"step0_collection": "projects/satromo-prod/assets/col/S2_SR_HARMONIZED_SWISS"
9393
}
9494

9595
# VHI – Trockenstress ch.swisstopo.swisseo_vhi_v100
@@ -107,7 +107,7 @@
107107
'LST_reference_data': 'projects/satromo-prod/assets/col/1991-2020_LST_SWISS',
108108
'LST_current_data': 'projects/satromo-prod/assets/col/LST_SWISS',
109109
"step1_collection": 'projects/satromo-prod/assets/col/VHI_SWISS',
110-
"step0_collection": "projects/satromo-prod/assets/col/S2_SR_HARMONIZED_SWISS"
110+
#"step0_collection": "projects/satromo-prod/assets/col/S2_SR_HARMONIZED_SWISS"
111111
}
112112

113113
# MSG – MeteoSchweiz: only used for repreocessing

configuration/prod_config.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
GDRIVE_SECRETS = os.path.join("secrets", "geetest-credentials-int.secret")
1313
RCLONE_SECRETS = os.path.join("secrets", "rclone.conf")
1414
FSDI_SECRETS = os.path.join("secrets", "stac_fsdi-prod.json")
15-
CMS_SECRETS = os.path.join("secrets", "INT_CMS.json")
15+
CMS_SECRETS = os.path.join("secrets", "PROD_CMS.json")
1616

1717
# File and directory paths
1818
GEE_RUNNING_TASKS = os.path.join("processing", "running_tasks.csv")

main_functions/main_extract_warnregions.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# shapefile with warnregions
2121
shape_file = r"C:\temp\topo-satromo\assets\warnregionen_vhi_2056.shp"
2222
23-
# raster file from URL / file
23+
# raster file from URL / file
2424
raster_url = r"C:\temp\topo-satromo\ch.swisstopo.swisseo_vhi_v100_mosaic_2023-07-13T235959_vegetation-10m.tif"
2525
2626
# missing data values
@@ -134,7 +134,7 @@ def export(raster_url, shape_file, filename, dateISO8601, missing_values):
134134

135135
# Add the date to each region in UTC
136136
# gdf[date_column] = datetime.strptime(dateISO8601, "%Y-%m-%dT%H:%M:%SZ")
137-
gdf[date_column] = pd.to_datetime(dateISO8601).tz_convert('UTC')
137+
gdf[date_column]= pd.to_datetime(dateISO8601).tz_convert('UTC').floor('S')
138138
# gdf[date_column] = gdf[date_column].astype()
139139

140140
# Export the converted GeoDataFrame to a geoparquet file

main_functions/main_thumbnails.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,12 @@ def create_thumbnail(inputfile_name, product):
230230

231231
except subprocess.CalledProcessError as e:
232232
print(f"Error: {e}")
233+
print("Output")
234+
print(e.output)
233235
return False
234236

235237
# VHI Use case
236-
237-
elif product.startswith("ch.swisstopo.swisseo_vhi") and inputfile_name.endswith("forest-10m.tif"):
238+
elif product.startswith("ch.swisstopo.swisseo_vhi") and (inputfile_name.endswith("forest-10m.tif") or inputfile_name.endswith("forest-30m.tif")):
238239
# https://github.com/radiantearth/stac-spec/blob/master/best-practices.md#visual
239240
# It should be called just "thumbnail.jpg"
240241
# thumbnail_name = inputfile_name.replace(

main_functions/main_utils.py

+44-16
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import os
77
import json
88
import pandas as pd
9+
import dateutil
910

1011

1112
def is_date_in_empty_asset_list(collection, check_date_str):
@@ -86,15 +87,15 @@ def get_github_info():
8687

8788
def get_product_from_techname(techname):
8889
"""
89-
This function searches for a dictionary in the 'config' module that contains
90+
This function searches for a dictionary in the 'config' module that contains
9091
'product_name' with a specified value and returns it.
9192
9293
Parameters:
93-
techname (str): The value of 'product_name' to search for.
94+
techname (str): The value of 'product_name' to search for.
9495
For example, 'ch.swisstopo.swisseo_s2-sr_v100'.
9596
9697
Returns:
97-
dict: The dictionary that contains 'product_name' with the value of 'techname'.
98+
dict: The dictionary that contains 'product_name' with the value of 'techname'.
9899
If no such dictionary is found, it returns None.
99100
"""
100101

@@ -172,28 +173,30 @@ def get_collection_info(collection):
172173
173174
Returns:
174175
A tuple containing the first date, last date, and total number of images in the collection.
176+
Returns (None, None, 0) for empty collections.
175177
"""
176178
# Sort the collection by date in ascending order
179+
177180
sorted_collection = collection.sort('system:time_start')
178181

179182
# Get the first and last image from the sorted collection
180183
first_image = sorted_collection.first()
181184
last_image = sorted_collection.sort('system:time_start', False).first()
182185

183-
# Get the dates of the first and last image
184-
first_date = ee.Date(first_image.get('system:time_start')
185-
).format('YYYY-MM-dd').getInfo()
186-
last_date = ee.Date(last_image.get('system:time_start')
187-
).format('YYYY-MM-dd').getInfo()
188-
189-
# Get the count of images in the filtered collection
190-
image_count = collection.size()
191-
192-
# Get the scenes count
193-
total_scenes = image_count.getInfo()
186+
try:
187+
# Get the count of images in the collection
188+
image_count = collection.size().getInfo()
189+
# Get the dates of the first and last image
190+
first_date = ee.Date(first_image.get('system:time_start')).format('YYYY-MM-dd').getInfo()
191+
last_date = ee.Date(last_image.get('system:time_start')).format('YYYY-MM-dd').getInfo()
192+
except ee.EEException:
193+
image_count = 0
194+
# Handle cases where date information might be missing
195+
first_date = None
196+
last_date = None
194197

195198
# Return the first date, last date, and total number of scenes
196-
return first_date, last_date, total_scenes
199+
return first_date, last_date, image_count
197200

198201

199202
def get_quadrants(roi):
@@ -440,7 +443,7 @@ def prepare_export(roi, productitem, productasset, productname, scale, image, se
440443
441444
Args:
442445
roi (ee.Geometry): Region of interest for the export.
443-
productitem (str): Timestamp of assets YYYYMMDThhmmss, "YYYYMMDDT235959" for a day
446+
productitem (str): Timestamp of assets YYYYMMDThhmmss, "YYYYMMDDT235959" for a day
444447
productasset (str): Base filename for the exported files.
445448
productname (str): Product name of the exported files.
446449
scale (str): Scalenumber in [m] of the exported file
@@ -507,3 +510,28 @@ def prepare_export(roi, productitem, productasset, productname, scale, image, se
507510
json.dump(image_info_gee, json_file)
508511

509512
return None
513+
514+
515+
def get_collection_info_landsat(collection):
516+
"""
517+
Retrieves information about an image collection for the line of Landsat satellites
518+
519+
Args:
520+
collection: The landsat image collection to retrieve information from.
521+
522+
Returns:
523+
A tuple containing the first date, last date, and total number of images in the collection.
524+
Returns (None, None, 0) for empty collections.
525+
"""
526+
# Sort the collection by date in ascending order
527+
index_list = collection.aggregate_array('system:index')
528+
529+
dates_list = [dateutil.parser.parse(i.split('_')[-1]) for i in index_list.getInfo()]
530+
531+
# Get the first and last image and size of image collection
532+
image_count = len(dates_list) if len(dates_list)>0 else 0
533+
first_date = min(dates_list) if image_count>0 else None
534+
last_date = max(dates_list) if image_count>0 else None
535+
536+
# Return the first date, last date, and total number of scenes
537+
return first_date, last_date, image_count

0 commit comments

Comments
 (0)