Spaces:
Sleeping
Sleeping
added salinity
Browse files- pages/01-main.py +6 -4
- pages/05_background.py +43 -37
- public/functions.py +23 -67
- public/load_process.py +74 -11
pages/01-main.py
CHANGED
@@ -7,10 +7,10 @@ import sys
|
|
7 |
|
8 |
|
9 |
|
10 |
-
|
11 |
# Get the project root directory
|
12 |
project_root = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
13 |
-
|
14 |
module_path = os.path.join(project_root, 'public')
|
15 |
print(module_path)
|
16 |
# Add the module path to the Python path
|
@@ -18,7 +18,7 @@ sys.path.append(module_path)
|
|
18 |
|
19 |
# Define the path to the shapefile
|
20 |
shapefile_path = os.path.join(project_root,'WaterQuality_SMB', 'public', 'study_boundary.gpkg')
|
21 |
-
|
22 |
|
23 |
|
24 |
|
@@ -49,6 +49,8 @@ class Map(geemap.Map):
|
|
49 |
self.functions.load_and_process_spm(self, STUDY_BOUNDARY_PATH)
|
50 |
elif self.selected_image_type == 'SST':
|
51 |
self.functions.load_and_process_sst(self, STUDY_BOUNDARY_PATH)
|
|
|
|
|
52 |
|
53 |
def set_selected_image_type(self, new_image_type):
|
54 |
self.selected_image_type = new_image_type
|
@@ -100,7 +102,7 @@ Monitoring water quality is crucial for the preservation of marine ecosystems. C
|
|
100 |
|
101 |
with solara.Column(style={'min-width': "500px"}):
|
102 |
with solara.Card(title = 'Select Map Type', subtitle = 'Choose between True Color, Chlorophyll-a, Suspended Particle Matter, Sea Surface Temperature'):
|
103 |
-
solara.ToggleButtonsSingle(value=selected_image_type, values=["True Color", "Chl-a", "SPM", "SST"], on_value=on_change_callback)
|
104 |
solara.Markdown('''Currently bugged between switching: Return to TRUE COLOR then switch to CHL-A, SPM, or SST''')
|
105 |
Map(selected_image_type).element(
|
106 |
selected_image_type= selected_image_type,
|
|
|
7 |
|
8 |
|
9 |
|
10 |
+
|
11 |
# Get the project root directory
|
12 |
project_root = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
13 |
+
|
14 |
module_path = os.path.join(project_root, 'public')
|
15 |
print(module_path)
|
16 |
# Add the module path to the Python path
|
|
|
18 |
|
19 |
# Define the path to the shapefile
|
20 |
shapefile_path = os.path.join(project_root,'WaterQuality_SMB', 'public', 'study_boundary.gpkg')
|
21 |
+
|
22 |
|
23 |
|
24 |
|
|
|
49 |
self.functions.load_and_process_spm(self, STUDY_BOUNDARY_PATH)
|
50 |
elif self.selected_image_type == 'SST':
|
51 |
self.functions.load_and_process_sst(self, STUDY_BOUNDARY_PATH)
|
52 |
+
elif self.selected_image_type == 'Salinity':
|
53 |
+
self.functions.load_and_process_salinity(self, STUDY_BOUNDARY_PATH)
|
54 |
|
55 |
def set_selected_image_type(self, new_image_type):
|
56 |
self.selected_image_type = new_image_type
|
|
|
102 |
|
103 |
with solara.Column(style={'min-width': "500px"}):
|
104 |
with solara.Card(title = 'Select Map Type', subtitle = 'Choose between True Color, Chlorophyll-a, Suspended Particle Matter, Sea Surface Temperature'):
|
105 |
+
solara.ToggleButtonsSingle(value=selected_image_type, values=["True Color", "Chl-a", "SPM", "SST", 'Salinity'], on_value=on_change_callback)
|
106 |
solara.Markdown('''Currently bugged between switching: Return to TRUE COLOR then switch to CHL-A, SPM, or SST''')
|
107 |
Map(selected_image_type).element(
|
108 |
selected_image_type= selected_image_type,
|
pages/05_background.py
CHANGED
@@ -4,71 +4,77 @@ import solara
|
|
4 |
@solara.component
|
5 |
def Page():
|
6 |
with solara.Column(align="center"):
|
7 |
-
markdown =
|
8 |
-
|
9 |
-
|
10 |
-
**A collection of Earth Engine web apps developed using [Solara](https://github.com/widgetti/solara) and geemap**
|
11 |
|
12 |
-
|
13 |
-
# WaterQualityMonitoring_SMB
|
14 |
-
Monitoring water quality in the Santa Monica Bay using Landsat 8 OLI satellite data
|
15 |
|
16 |
-
|
17 |
-
|
|
|
18 |
|
19 |
-
|
|
|
20 |
|
21 |
-
|
22 |
|
23 |
-
|
24 |
|
25 |
-
|
26 |
|
27 |
-
|
28 |
|
29 |
-
|
30 |
|
31 |
-
|
32 |
|
33 |
-
|
34 |
|
35 |
-
|
36 |
|
37 |
-
|
38 |
|
39 |
-
|
40 |
|
41 |
-
|
42 |
|
43 |
-
|
44 |
|
45 |
-
|
46 |
|
47 |
-
|
48 |
|
49 |
-
|
50 |
|
51 |
-
|
52 |
|
|
|
53 |
|
54 |
-
The Santa Monica Bay, California, and the Gironde Estuary and Bourgneuf Bay in France have some similarities but also significant differences. Here are some key points to consider:
|
55 |
|
56 |
-
|
57 |
|
58 |
-
|
59 |
|
60 |
-
|
61 |
|
62 |
-
|
63 |
|
64 |
-
|
65 |
|
66 |
-
|
67 |
|
68 |
-
|
69 |
-
Trinh, R. C., Fichot, C. G., Gierach, M. M., Holt, B., Malakar, N. K., Hulley, G., & Smith, J. (2017). Application of Landsat 8 for Monitoring Impacts of Wastewater Discharge on Coastal Water Quality. Frontiers in Marine Science, 4. https://doi.org/10.3389/fmars.2017.00329
|
70 |
|
71 |
-
|
72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
|
74 |
solara.Markdown(markdown)
|
|
|
4 |
@solara.component
|
5 |
def Page():
|
6 |
with solara.Column(align="center"):
|
7 |
+
markdown ="""
|
8 |
+
## Earth Engine Web Apps
|
|
|
|
|
9 |
|
10 |
+
**A collection of Earth Engine web apps developed using [Solara](https://github.com/widgetti/solara) and geemap**
|
|
|
|
|
11 |
|
12 |
+
|
13 |
+
# WaterQualityMonitoring_SMB
|
14 |
+
Monitoring water quality in the Santa Monica Bay using Landsat 8 OLI satellite data
|
15 |
|
16 |
+
# Reproducing Chlorophyll-a Analysis in Santa Monica Bay Using Landsat 8
|
17 |
+
This notebook aims to reproduce and extend the analysis conducted in the ocean remote sensing project titled "Remote Sensing of Chlorophyll-a using Landsat 8". The original project, available [here](https://romero61.github.io/posts/SMB/), focused on the analysis of Chlorophyll-a concentrations in the Santa Monica Bay.
|
18 |
|
19 |
+
We utilize Landsat 8 satellite imagery to estimate Chlorophyll-a concentrations & Suspended Particle Matter and analyze changes over time, particularly focusing on the impact of the Hyperion Treatment Plant failure.
|
20 |
|
21 |
+
The Earth Engine Web app include the following steps:
|
22 |
|
23 |
+
1. Importing necessary Python libraries for data manipulation, mathematical operations, data visualization, handling date and time data, interacting with Google Earth Engine, and handling geospatial data.
|
24 |
|
25 |
+
2. Initializing the Earth Engine API and creating an interactive map using the geemap library.
|
26 |
|
27 |
+
3. Defining the collection of satellite images to be used (Landsat 8 OLI images) and the study area.
|
28 |
|
29 |
+
4. Processing the satellite images, including applying scale factors and estimating Chlorophyll-a & Suspended Particle Matter concentrations.
|
30 |
|
31 |
+
5. Visualizing the processed images on an interactive map.
|
32 |
|
33 |
+
The next steps of this project will include retrieving the most recent image from the collection, calculating basic statistics for Chlorophyll-a concentrations & Suspended Particle Matter, allowing user-defined regions for analysis, and creating an interactive data exploration.
|
34 |
|
35 |
+
# Santa Monica Bay
|
36 |
|
37 |
+
Santa Monica Bay Watershed Management Area (WMA): The Santa Monica Bay WMA encompasses an area of 414 square miles and is quite diverse. Its borders reach from the crest of the Santa Monica Mountains on the north and from the Ventura-Los Angeles County line to downtown Los Angeles. The WMA includes several watersheds, the two largest being Malibu Creek to the north (west) and Ballona Creek to the south. The Malibu Creek area contains mostly undeveloped mountain areas, large acreage residential properties, and many natural stream reaches. At the same time, Ballona Creek is predominantly channelized and highly developed with both residential and commercial properties. The Santa Monica Bay was included in the National Estuary Program in 1989 and has been extensively studied by the Santa Monica Bay Restoration Project. The Santa Monica Bay Watershed Commission was established in 2002 to oversee the implementation of the Plan.
|
38 |
|
39 |
+
Water Quality Problems and Issues: The Santa Monica Bay WMA embraces a high diversity of geological and hydrological characteristics, habitat features, and human activities. Existing and potential beneficial use impairment problems in the watershed fall into two major categories: human health risk and natural habitat degradation. The former are issues primarily associated with recreational uses of the Santa Monica Bay. The latter are issues associated with terrestrial, aquatic, and marine environments. Pollutant loadings that originate from human activities are common causes of both human health risks and habitat degradation.
|
40 |
|
41 |
+
# Suspended Particulate Matter
|
42 |
|
43 |
+
The Santa Monica Bay, California, and the Gironde Estuary and Bourgneuf Bay in France have some similarities but also significant differences. Here are some key points to consider:
|
44 |
|
45 |
+
Size and Geography: The Santa Monica Bay is a bight of the Pacific Ocean, while the Gironde Estuary and Bourgneuf Bay are estuaries, which are partially enclosed coastal bodies of water where freshwater from rivers and streams meets and mixes with saltwater from the ocean. The Gironde Estuary is formed by the confluence of the Garonne and Dordogne Rivers, and the Loire River feeds into Bourgneuf Bay. The Santa Monica Bay, on the other hand, is fed by several smaller watersheds, including Malibu Creek and Ballona Creek.
|
46 |
|
47 |
+
Turbidity and SPM Concentration: The Gironde Estuary and Bourgneuf Bay are characterized by high Suspended Particulate Matter (SPM) concentrations, ranging from 1 to 3000 g·m−3 in the Gironde and 50 to over 1000 g·m−3 in Bourgneuf Bay. The Santa Monica Bay, according to the information found, has a lower SPM concentration, with a median value of 1.3 mg/L (or approximately 0.0013 g·m−3), which is significantly lower than the French sites.
|
48 |
|
49 |
+
Tidal Range: Both the Gironde Estuary and Bourgneuf Bay have a macro-tidal regime, with tidal ranges from 2 to 5 m and 2 to 6 m, respectively. The tidal range in the Santa Monica Bay is not explicitly stated in the sources found, but the Pacific coast of Southern California typically experiences a smaller tidal range, usually less than 2 meters.
|
50 |
|
51 |
+
Freshwater Inputs: The Gironde Estuary and Bourgneuf Bay have significant freshwater inputs from large rivers, with flow rates ranging from less than 100 m3·s−1 to more than 4000 m3·s−1. The Santa Monica Bay receives freshwater inputs from several smaller watersheds, but the flow rates are likely much lower than those of the French sites.
|
52 |
|
|
|
53 |
|
54 |
+
The Santa Monica Bay, California, and the Gironde Estuary and Bourgneuf Bay in France have some similarities but also significant differences. Here are some key points to consider:
|
55 |
|
56 |
+
Size and Geography: The Santa Monica Bay is a bight of the Pacific Ocean, while the Gironde Estuary and Bourgneuf Bay are estuaries, which are partially enclosed coastal bodies of water where freshwater from rivers and streams meets and mixes with saltwater from the ocean. The Gironde Estuary is formed by the confluence of the Garonne and Dordogne rivers, and the Loire River feeds into Bourgneuf Bay. The Santa Monica Bay, on the other hand, is fed by several smaller watersheds, including Malibu Creek and Ballona Creek.
|
57 |
|
58 |
+
Turbidity and SPM Concentration: The Gironde Estuary and Bourgneuf Bay are characterized by high Suspended Particulate Matter (SPM) concentrations, ranging from 1 to 3000 g·m−3 in the Gironde and 50 to over 1000 g·m−3 in Bourgneuf Bay. The Santa Monica Bay, according to the information found, has a lower SPM concentration, with a median value of 1.3 mg/L (or approximately 0.0013 g·m−3), which is significantly lower than the French sites.
|
59 |
|
60 |
+
Tidal Range: Both the Gironde Estuary and Bourgneuf Bay have a macro-tidal regime, with tidal ranges from 2 to 5 m and 2 to 6 m, respectively. The tidal range in the Santa Monica Bay is not explicitly stated in the sources found, but the Pacific coast of Southern California typically experiences a smaller tidal range, usually less than 2 meters.
|
61 |
|
62 |
+
In conclusion, while there are some similarities in terms of being coastal water bodies with freshwater inputs, the Gironde Estuary and Bourgneuf Bay in France appear to be significantly more turbid and have higher SPM concentrations than the Santa Monica Bay.
|
63 |
|
64 |
+
Freshwater Inputs: The Gironde Estuary and Bourgneuf Bay have significant freshwater inputs from large rivers, with flow rates ranging from less than 100 m3·s−1 to more than 4000 m3·s−1. The Santa Monica Bay receives freshwater inputs from several smaller watersheds, but the flow rates are likely much lower than those of the French sites.
|
65 |
|
66 |
+
In conclusion, while there are some similarities in terms of being coastal water bodies with freshwater inputs, the Gironde Estuary and Bourgneuf Bay in France appear to be significantly more turbid and have higher SPM concentrations than the Santa Monica Bay. Therefore, the models developed for the French sites may not be directly applicable to the Santa Monica Bay without some adjustments or recalibrations.
|
|
|
67 |
|
68 |
+
# References
|
69 |
+
Trinh, R. C., Fichot, C. G., Gierach, M. M., Holt, B., Malakar, N. K., Hulley, G., & Smith, J. (2017). Application of Landsat 8 for Monitoring Impacts of Wastewater Discharge on Coastal Water Quality. Frontiers in Marine Science, 4. https://doi.org/10.3389/fmars.2017.00329
|
70 |
+
|
71 |
+
Novoa S, Doxaran D, Ody A, Vanhellemont Q, Lafon V, Lubac B, Gernez P. Atmospheric Corrections and Multi-Conditional Algorithm for Multi-Sensor Remote Sensing of Suspended Particulate Matter in Low-to-High Turbidity Levels Coastal Waters. Remote Sensing. 2017; 9(1):61. https://doi.org/10.3390/rs9010061
|
72 |
+
|
73 |
+
Quinten Vanhellemont. Automated Water Surface Temperature Retrieval from Landsat 8/TIRS. Feb. 2020, pp. 111518–18, https://doi.org/10.1016/j.rse.2019.111518. Accessed 17 July 2023.
|
74 |
+
|
75 |
+
Ansari, Mohsen, and M. Akhoondzadeh. Mapping Water Salinity Using Landsat-8 OLI Satellite Images (Case Study: Karun Basin Located in Iran). no. 5, Mar. 2020, pp. 1490–502, https://doi.org/10.1016/j.asr.2019.12.007. Accessed 17 July 2023.
|
76 |
+
|
77 |
+
Landsat-8 imagery courtesy of the U.S. Geological Survey
|
78 |
+
"""
|
79 |
|
80 |
solara.Markdown(markdown)
|
public/functions.py
CHANGED
@@ -158,17 +158,8 @@ class ImageFunctions:
|
|
158 |
image = image.addBands(SST_B10_Celsius.rename('SST_B10_Celsius'))
|
159 |
|
160 |
return image
|
161 |
-
|
162 |
-
|
163 |
-
'''def calculate_sst(self, image):
|
164 |
-
# Constants from Table 1
|
165 |
-
K1_B10 = 774.8853
|
166 |
-
K2_B10 = 1321.0789
|
167 |
-
epsilon_B10 = 0.9926
|
168 |
-
K1_B11 = 480.8883
|
169 |
-
K2_B11 = 1201.1442
|
170 |
-
epsilon_B11 = 0.9877
|
171 |
-
|
172 |
# extract the cloud and water masks
|
173 |
qa_band = ee.Image(image).select('QA_PIXEL')
|
174 |
cloudMask = self.extract_qa_bits(qa_band, 8, 9, "cloud").neq(3) # different than 3 to remove clouds
|
@@ -176,67 +167,32 @@ class ImageFunctions:
|
|
176 |
|
177 |
# apply the masks to the image
|
178 |
image = image.updateMask(cloudMask).updateMask(waterMask)
|
179 |
-
image =
|
180 |
|
181 |
-
|
182 |
-
|
183 |
-
|
|
|
184 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
185 |
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
'B10': B10,
|
191 |
-
'K2_B10': K2_B10,
|
192 |
-
'epsilon_B10': epsilon_B10
|
193 |
-
}
|
194 |
-
)
|
195 |
-
Ls_B11 = image.expression(
|
196 |
-
"B11 / (1 + (B11 / K2_B11) * log(epsilon_B11))",
|
197 |
-
{ 'B11': B11,
|
198 |
-
'K2_B11': K2_B11,
|
199 |
-
'epsilon_B11': epsilon_B11}
|
200 |
-
)
|
201 |
-
|
202 |
-
# Calculate the atmospheric transmittance (tau)
|
203 |
-
tau = image.expression(
|
204 |
-
"(B10 - B11) / (Ls_B10 - Ls_B11)",
|
205 |
-
{'B10': B10, 'B11': B11, 'Ls_B10': Ls_B10, 'Ls_B11': Ls_B11}
|
206 |
-
)
|
207 |
-
|
208 |
-
# Calculate the upwelled radiance (Lu) for Band 10
|
209 |
-
Lu_B10 = image.expression(
|
210 |
-
"B10 - tau * Ls_B10",
|
211 |
-
{'B10': B10, 'tau': tau, 'Ls_B10': Ls_B10}
|
212 |
-
)
|
213 |
-
|
214 |
-
# Calculate the downwelled radiance (Ld) for Band 10
|
215 |
-
Ld_B10 = image.expression(
|
216 |
-
"(B10 - Lu_B10) / (tau * (1 - epsilon_B10))",
|
217 |
-
{'B10': B10, 'Lu_B10': Lu_B10, 'tau': tau,'epsilon_B10': epsilon_B10}
|
218 |
-
)
|
219 |
-
|
220 |
-
|
221 |
-
# Define the expression for calculating SST
|
222 |
-
expression = (
|
223 |
-
)
|
224 |
|
225 |
-
# Calculate SST using the expression
|
226 |
-
SST_B10_Celsius = image.expression("K2_B10 / log(K1_B10 / ((B10 - Lu_B10 - tau * Ld_B10) / (tau * epsilon_B10)) + 1) - 273.15",
|
227 |
-
{'K2_B10': K2_B10,
|
228 |
-
'K1_B10': K1_B10,
|
229 |
-
'B10': B10,
|
230 |
-
'Lu_B10': Lu_B10,
|
231 |
-
'tau': tau,
|
232 |
-
'Ld_B10': Ld_B10,
|
233 |
-
'epsilon_B10': epsilon_B10
|
234 |
-
}
|
235 |
-
)
|
236 |
|
237 |
-
# Add the SST_B10_Celsius band to the image
|
238 |
-
image = image.addBands(SST_B10_Celsius.select([0], ['SST_B10_Celsius']))
|
239 |
-
return image'''
|
240 |
|
241 |
|
242 |
|
|
|
158 |
image = image.addBands(SST_B10_Celsius.rename('SST_B10_Celsius'))
|
159 |
|
160 |
return image
|
161 |
+
|
162 |
+
def ansari_akhoondzadeh_salinity(self, image):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
# extract the cloud and water masks
|
164 |
qa_band = ee.Image(image).select('QA_PIXEL')
|
165 |
cloudMask = self.extract_qa_bits(qa_band, 8, 9, "cloud").neq(3) # different than 3 to remove clouds
|
|
|
167 |
|
168 |
# apply the masks to the image
|
169 |
image = image.updateMask(cloudMask).updateMask(waterMask)
|
170 |
+
image = self.apply_scale_factors(image)
|
171 |
|
172 |
+
a_0 = 570.80
|
173 |
+
a_1 = 26535.17
|
174 |
+
a_2 = -62141.71
|
175 |
+
a_3 = 34952.89
|
176 |
|
177 |
+
coastal_aerosol = image.select('SR_B1')
|
178 |
+
blue_bands = image.select('SR_B2')
|
179 |
+
green_bands = image.select('SR_B3')
|
180 |
+
salinity = image.expression("a_0 + (a_1 *coastal_aerosol) + (a_2 * blue_bands) + (a_3 * green_bands)", {
|
181 |
+
'a_0': a_0,
|
182 |
+
'a_1': a_1,
|
183 |
+
'a_2': a_2,
|
184 |
+
'a_3': a_3,
|
185 |
+
'coastal_aerosol': coastal_aerosol,
|
186 |
+
'blue_bands': blue_bands,
|
187 |
+
'green_bands': green_bands
|
188 |
+
})
|
189 |
|
190 |
+
image = image.addBands(salinity.select([0], ['salinity']))
|
191 |
+
|
192 |
+
|
193 |
+
return image
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
|
|
|
|
|
|
|
196 |
|
197 |
|
198 |
|
public/load_process.py
CHANGED
@@ -39,7 +39,7 @@ class ImageProcess:
|
|
39 |
|
40 |
# Loop through the dates and get the imagery
|
41 |
for date in dates:
|
42 |
-
|
43 |
start_date = ee.Date(date)
|
44 |
end_date = start_date.advance(1, 'day')
|
45 |
|
@@ -50,7 +50,7 @@ class ImageProcess:
|
|
50 |
.first() # get the first image that matches the filters
|
51 |
|
52 |
if image: # check if image exists
|
53 |
-
|
54 |
optical_bands = image.select('SR_B.*').multiply(0.0000275).add(-0.2)
|
55 |
clipped_image = optical_bands.clip(aoi) # Clip the image to the study boundary
|
56 |
map_instance.addLayer(clipped_image, vis_params, date, shown = True) # add the image to the map
|
@@ -62,7 +62,7 @@ class ImageProcess:
|
|
62 |
|
63 |
def load_and_process_chla(self, map_instance, shapefile_path):
|
64 |
# Load the study area
|
65 |
-
|
66 |
study_boundary = gpd.read_file(shapefile_path)
|
67 |
ee_boundary = geemap.geopandas_to_ee(study_boundary)
|
68 |
aoi = ee_boundary.geometry()
|
@@ -112,7 +112,7 @@ class ImageProcess:
|
|
112 |
|
113 |
# Loop through the dates and get the imagery
|
114 |
for date in dates:
|
115 |
-
|
116 |
start_date = ee.Date(date)
|
117 |
end_date = start_date.advance(1, 'day')
|
118 |
|
@@ -123,7 +123,7 @@ class ImageProcess:
|
|
123 |
.first() # get the first image that matches the filters
|
124 |
|
125 |
if image: # check if image exists
|
126 |
-
|
127 |
clipped_image = image.clip(aoi) # Clip the image to the study boundary
|
128 |
processed_image = map_instance.image_functions.trinh_et_al_chl_a(clipped_image) # process the image
|
129 |
map_instance.addLayer(processed_image, chloro_params, date, shown = True) # add the image to the map
|
@@ -132,7 +132,7 @@ class ImageProcess:
|
|
132 |
print(f"No image found for date {date}")
|
133 |
|
134 |
# Set the map to focus on the study area
|
135 |
-
|
136 |
map_instance.add_colorbar_branca(vis_params= chloro_params, colors = TURBO_PALETTE,vmin = 0, vmax = 3, label = 'mg/m³')
|
137 |
|
138 |
|
@@ -189,7 +189,7 @@ class ImageProcess:
|
|
189 |
.first() # get the first image that matches the filters
|
190 |
|
191 |
if image: # check if image exists
|
192 |
-
|
193 |
clipped_image = image.clip(aoi) # Clip the image to the study boundary
|
194 |
processed_image = map_instance.image_functions.novoa_et_al_spm(clipped_image) # process the image
|
195 |
map_instance.addLayer(processed_image, spm_params, date, shown = True) # add the image to the map
|
@@ -203,7 +203,7 @@ class ImageProcess:
|
|
203 |
|
204 |
def load_and_process_sst(self, map_instance, shapefile_path):
|
205 |
# Load the study area
|
206 |
-
|
207 |
study_boundary = gpd.read_file(shapefile_path)
|
208 |
ee_boundary = geemap.geopandas_to_ee(study_boundary)
|
209 |
aoi = ee_boundary.geometry()
|
@@ -253,7 +253,7 @@ class ImageProcess:
|
|
253 |
|
254 |
# Loop through the dates and get the imagery
|
255 |
for date in dates:
|
256 |
-
|
257 |
start_date = ee.Date(date)
|
258 |
end_date = start_date.advance(1, 'day')
|
259 |
|
@@ -264,7 +264,6 @@ class ImageProcess:
|
|
264 |
.first() # get the first image that matches the filters
|
265 |
|
266 |
if image: # check if image exists
|
267 |
-
print(f'Image found for sst {date}')
|
268 |
clipped_image = image.clip(aoi) # Clip the image to the study boundary
|
269 |
processed_image = map_instance.image_functions.calculate_sst(clipped_image) # process the image
|
270 |
map_instance.addLayer(processed_image, sst_params, date, shown = True) # add the image to the map
|
@@ -273,5 +272,69 @@ class ImageProcess:
|
|
273 |
print(f"No image found for date {date}")
|
274 |
|
275 |
# Set the map to focus on the study area
|
276 |
-
|
277 |
map_instance.add_colorbar_branca(vis_params= sst_params, colors = TURBO_PALETTE,vmin = 13.5, vmax = 20, label = 'C')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
|
40 |
# Loop through the dates and get the imagery
|
41 |
for date in dates:
|
42 |
+
|
43 |
start_date = ee.Date(date)
|
44 |
end_date = start_date.advance(1, 'day')
|
45 |
|
|
|
50 |
.first() # get the first image that matches the filters
|
51 |
|
52 |
if image: # check if image exists
|
53 |
+
|
54 |
optical_bands = image.select('SR_B.*').multiply(0.0000275).add(-0.2)
|
55 |
clipped_image = optical_bands.clip(aoi) # Clip the image to the study boundary
|
56 |
map_instance.addLayer(clipped_image, vis_params, date, shown = True) # add the image to the map
|
|
|
62 |
|
63 |
def load_and_process_chla(self, map_instance, shapefile_path):
|
64 |
# Load the study area
|
65 |
+
|
66 |
study_boundary = gpd.read_file(shapefile_path)
|
67 |
ee_boundary = geemap.geopandas_to_ee(study_boundary)
|
68 |
aoi = ee_boundary.geometry()
|
|
|
112 |
|
113 |
# Loop through the dates and get the imagery
|
114 |
for date in dates:
|
115 |
+
|
116 |
start_date = ee.Date(date)
|
117 |
end_date = start_date.advance(1, 'day')
|
118 |
|
|
|
123 |
.first() # get the first image that matches the filters
|
124 |
|
125 |
if image: # check if image exists
|
126 |
+
|
127 |
clipped_image = image.clip(aoi) # Clip the image to the study boundary
|
128 |
processed_image = map_instance.image_functions.trinh_et_al_chl_a(clipped_image) # process the image
|
129 |
map_instance.addLayer(processed_image, chloro_params, date, shown = True) # add the image to the map
|
|
|
132 |
print(f"No image found for date {date}")
|
133 |
|
134 |
# Set the map to focus on the study area
|
135 |
+
|
136 |
map_instance.add_colorbar_branca(vis_params= chloro_params, colors = TURBO_PALETTE,vmin = 0, vmax = 3, label = 'mg/m³')
|
137 |
|
138 |
|
|
|
189 |
.first() # get the first image that matches the filters
|
190 |
|
191 |
if image: # check if image exists
|
192 |
+
|
193 |
clipped_image = image.clip(aoi) # Clip the image to the study boundary
|
194 |
processed_image = map_instance.image_functions.novoa_et_al_spm(clipped_image) # process the image
|
195 |
map_instance.addLayer(processed_image, spm_params, date, shown = True) # add the image to the map
|
|
|
203 |
|
204 |
def load_and_process_sst(self, map_instance, shapefile_path):
|
205 |
# Load the study area
|
206 |
+
|
207 |
study_boundary = gpd.read_file(shapefile_path)
|
208 |
ee_boundary = geemap.geopandas_to_ee(study_boundary)
|
209 |
aoi = ee_boundary.geometry()
|
|
|
253 |
|
254 |
# Loop through the dates and get the imagery
|
255 |
for date in dates:
|
256 |
+
|
257 |
start_date = ee.Date(date)
|
258 |
end_date = start_date.advance(1, 'day')
|
259 |
|
|
|
264 |
.first() # get the first image that matches the filters
|
265 |
|
266 |
if image: # check if image exists
|
|
|
267 |
clipped_image = image.clip(aoi) # Clip the image to the study boundary
|
268 |
processed_image = map_instance.image_functions.calculate_sst(clipped_image) # process the image
|
269 |
map_instance.addLayer(processed_image, sst_params, date, shown = True) # add the image to the map
|
|
|
272 |
print(f"No image found for date {date}")
|
273 |
|
274 |
# Set the map to focus on the study area
|
275 |
+
|
276 |
map_instance.add_colorbar_branca(vis_params= sst_params, colors = TURBO_PALETTE,vmin = 13.5, vmax = 20, label = 'C')
|
277 |
+
|
278 |
+
|
279 |
+
def load_and_process_salinity(self, map_instance, shapefile_path):
|
280 |
+
# Load the study area
|
281 |
+
|
282 |
+
study_boundary = gpd.read_file(shapefile_path)
|
283 |
+
ee_boundary = geemap.geopandas_to_ee(study_boundary)
|
284 |
+
aoi = ee_boundary.geometry()
|
285 |
+
VIRIDIS_PALETTE = [
|
286 |
+
'440154', '440256', '450457', '450559', '46075a', '46085c', '460a5d', '460b5e', '470d60',
|
287 |
+
'470e61', '471063', '471164', '471365', '481467', '481668', '481769', '48186a', '481a6c',
|
288 |
+
'481b6d', '481c6e', '481d6f', '481f70', '482071', '482173', '482374', '482475', '482576',
|
289 |
+
'482677', '482878', '482979', '472a7a', '472c7a', '472d7b', '472e7c', '472f7d', '46307e',
|
290 |
+
'46327e', '46337f', '463480', '453581', '453781', '453882', '443983', '443a83', '443b84',
|
291 |
+
'433d84', '433e85', '423f85', '424086', '424186', '414287', '414487', '404588', '404688',
|
292 |
+
'3f4788', '3f4889', '3e4989', '3e4a89', '3e4c8a', '3d4d8a', '3d4e8a', '3c4f8a', '3c508b',
|
293 |
+
'3b518b', '3b528b', '3a538b', '3a548c', '39558c', '39568c', '38588c', '38598c', '375a8c',
|
294 |
+
'375b8d', '365c8d', '365d8d', '355e8d', '355f8d', '34608d', '34618d', '33628d', '33638d',
|
295 |
+
'32648e', '32658e', '31668e', '31678e', '30688e', '30698e', '2f6a8e', '2f6b8e', '2e6c8e',
|
296 |
+
'2e6d8e', '2d6e8e', '2d6f8e', '2c708e', '2c718e', '2b728e', '2b738e', '2a748e', '2a758e',
|
297 |
+
'29768e', '29778e', '28788e', '28798e', '277a8e', '277b8e', '267c8e', '267d8e', '257e8e',
|
298 |
+
'257f8e', '24808e', '24818e', '23828e', '23828e', '22838e', '22848e', '21858e', '21868e',
|
299 |
+
'20878e', '20888e', '1f898e', '1f8a8d', '1e8b8d', '1e8c8d', '1d8d8d', '1d8e8d', '1c8f8d',
|
300 |
+
'1c8f8d', '1b908c', '1b918c', '1a928c', '1a938b', '19948b', '19958b', '18968a', '18978a',
|
301 |
+
'17988a', '179989', '169a89', '169b88', '159c88', '159d87', '149e87', '149f86', '13a086',
|
302 |
+
'13a185', '12a285', '12a384', '11a483', '11a583', '10a682', '10a781', '0fa881', '0fa980',
|
303 |
+
'0eaa7f', '0eab7e', '0dac7e', '0dad7d', '0cae7c', '0caf7b', '0bb07a', '0bb179', '0ab278',
|
304 |
+
'0ab377', '09b476', '09b575', '08b674', '08b773', '07b872', '07b971', '06ba70', '06bb6f',
|
305 |
+
'05bc6e', '05bd6d', '04be6c', '04bf6b', '03c06a', '03c169', '02c268', '02c367', '01c466',
|
306 |
+
'01c565', '00c664']
|
307 |
+
|
308 |
+
salinity_params= {
|
309 |
+
'bands': ['salinity'],
|
310 |
+
'min': 0,
|
311 |
+
'max': 1000,
|
312 |
+
'palette': VIRIDIS_PALETTE
|
313 |
+
}
|
314 |
+
dates = ['2021-11-11', '2021-10-26','2021-10-10', '2021-08-07','2021-07-22', '2021-07-06' ]
|
315 |
+
|
316 |
+
processed_collection = ee.ImageCollection([])
|
317 |
+
|
318 |
+
# Loop through the dates and get the imagery
|
319 |
+
for date in dates:
|
320 |
+
|
321 |
+
start_date = ee.Date(date)
|
322 |
+
end_date = start_date.advance(1, 'day')
|
323 |
+
|
324 |
+
# Filter the image collection by date and area
|
325 |
+
image = ee.ImageCollection("LANDSAT/LC08/C02/T1_L2") \
|
326 |
+
.filterDate(start_date, end_date) \
|
327 |
+
.filterBounds(ee_boundary) \
|
328 |
+
.first() # get the first image that matches the filters
|
329 |
+
|
330 |
+
if image: # check if image exists
|
331 |
+
|
332 |
+
clipped_image = image.clip(aoi) # Clip the image to the study boundary
|
333 |
+
processed_image = map_instance.image_functions.ansari_akhoondzadeh_salinity(clipped_image) # process the image
|
334 |
+
map_instance.addLayer(processed_image, salinity_params, date, shown = True) # add the image to the map
|
335 |
+
processed_collection = processed_collection.merge(processed_image) # add the image to the processed collection
|
336 |
+
else:
|
337 |
+
print(f"No image found for date {date}")
|
338 |
+
|
339 |
+
# Set the map to focus on the study area
|
340 |
+
map_instance.add_colorbar_branca(vis_params= salinity_params, colors = VIRIDIS_PALETTE,vmin = 0, vmax = 1000, label = 'EC')
|