coastseg 0.0.65.dev4__tar.gz → 0.0.66.dev1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. {coastseg-0.0.65.dev4/src/coastseg.egg-info → coastseg-0.0.66.dev1}/PKG-INFO +1 -1
  2. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/pyproject.toml +5 -3
  3. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/bbox.py +2 -1
  4. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/coastseg_map.py +210 -186
  5. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/common.py +105 -56
  6. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/downloads.py +0 -1
  7. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/extracted_shoreline.py +46 -15
  8. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/map_UI.py +68 -79
  9. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/models_UI.py +2 -2
  10. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/settings_UI.py +0 -6
  11. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/shoreline.py +0 -1
  12. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects.py +1 -1
  13. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/watchable_slider.py +2 -0
  14. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/zoo_model.py +102 -86
  15. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1/src/coastseg.egg-info}/PKG-INFO +1 -1
  16. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg.egg-info/requires.txt +3 -1
  17. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/LICENSE +0 -0
  18. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/MANIFEST.in +0 -0
  19. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/README.md +0 -0
  20. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/config.md +0 -0
  21. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/extract_shorelines.md +0 -0
  22. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/gifs/change_layer_demo.gif +0 -0
  23. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/gifs/colab_demo.gif +0 -0
  24. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/gifs/colab_downloads_location.gif +0 -0
  25. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/gifs/create_rois_demo.gif +0 -0
  26. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/gifs/extract_shorelines_and_transects.gif +0 -0
  27. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/gifs/gee_auth_tutorial.gif +0 -0
  28. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/gifs/generate_rois_and_display_area.gif +0 -0
  29. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/gifs/load_config_demo.gif +0 -0
  30. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/gifs/load_geojson_demo.gif +0 -0
  31. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/gifs/load_geojson_files_demo.gif +0 -0
  32. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/gifs/load_shoreline_transect_demo.gif +0 -0
  33. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/gifs/settings_demo.gif +0 -0
  34. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/map_guide.md +0 -0
  35. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/models.md +0 -0
  36. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/roi.md +0 -0
  37. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/settings.md +0 -0
  38. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/docs/transect_time_series.md +0 -0
  39. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/setup.cfg +0 -0
  40. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/setup.py +0 -0
  41. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/__init__.py +0 -0
  42. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/bounding_boxes/shorelines_bounding_boxes.csv +0 -0
  43. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/bounding_boxes/transects_bounding_boxes.csv +0 -0
  44. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/bounding_boxes/usa_shorelines_bounding_boxes.csv +0 -0
  45. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/bounding_boxes/usa_shorelines_bounding_boxes.geojson +0 -0
  46. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/bounding_boxes/world_reference_shorelines_bboxes.geojson +0 -0
  47. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/bounding_boxes/world_shorelines_bounding_boxes.csv +0 -0
  48. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/coastseg_logs.py +0 -0
  49. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/exception_handler.py +0 -0
  50. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/exceptions.py +0 -0
  51. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/factory.py +0 -0
  52. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/observable.py +0 -0
  53. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/roi.py +0 -0
  54. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/sessions.py +0 -0
  55. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/BarterIslandAlaskaTransects.geojson +0 -0
  56. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/CA_USA_transects.geojson +0 -0
  57. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/Chile_transects.geojson +0 -0
  58. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/E_aus_transects.geojson +0 -0
  59. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/Gulf_USA_transects.geojson +0 -0
  60. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/Japan_transects.geojson +0 -0
  61. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/Mexico_transects.geojson +0 -0
  62. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/NE_TWL_transects.geojson +0 -0
  63. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/NE_usa_DSAS.geojson +0 -0
  64. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/NZ_transects.geojson +0 -0
  65. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/N_AK_DSAS.geojson +0 -0
  66. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/PNW_transects.geojson +0 -0
  67. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/Peru_transects.geojson +0 -0
  68. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/PuertoRico_TWL_transects.geojson +0 -0
  69. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/SE_USA_transects.geojson +0 -0
  70. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/SFlorida_TWL_transects.geojson +0 -0
  71. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/all_HI_transects.geojson +0 -0
  72. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/mergedBI_transects.geojson +0 -0
  73. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/usa_southeast_transects_DE.geojson +0 -0
  74. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/transects/usa_southeast_transects_MD.geojson +0 -0
  75. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg/upload_feature_widget.py +0 -0
  76. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg.egg-info/SOURCES.txt +0 -0
  77. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg.egg-info/dependency_links.txt +0 -0
  78. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/src/coastseg.egg-info/top_level.txt +0 -0
  79. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/__init__.py +0 -0
  80. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/conftest.py +0 -0
  81. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/test_bbox.py +0 -0
  82. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/test_coastseg_map.py +0 -0
  83. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/test_common.py +0 -0
  84. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/test_data/config.json +0 -0
  85. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/test_data/config_gdf_id_2.geojson +0 -0
  86. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/test_data/config_id_2.json +0 -0
  87. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/test_data/transect_compatible_bbox.geojson +0 -0
  88. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/test_data/transect_compatible_rois.geojson +0 -0
  89. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/test_data/transect_compatible_shoreline.geojson +0 -0
  90. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/test_data/transect_compatible_transects.geojson +0 -0
  91. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/test_data/valid_bbox.geojson +0 -0
  92. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/test_data/valid_rois.geojson +0 -0
  93. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/test_extracted_shoreline.py +0 -0
  94. {coastseg-0.0.65.dev4 → coastseg-0.0.66.dev1}/tests/test_roi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: coastseg
3
- Version: 0.0.65.dev4
3
+ Version: 0.0.66.dev1
4
4
  Summary: An interactive jupyter notebook for downloading satellite imagery
5
5
  Author-email: Sharon Fitzpatrick <sharon.fitzpatrick23@gmail.com>
6
6
  License: MIT License
@@ -5,14 +5,14 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  name = "coastseg"
7
7
  dynamic = ["readme"]
8
- version = "0.0.65dev4"
8
+ version = "0.0.66dev1"
9
9
  authors = [
10
10
  { name=" Sharon Fitzpatrick", email="sharon.fitzpatrick23@gmail.com" },
11
11
  ]
12
12
  # find` directive with `include` or `exclude`
13
13
  description = "An interactive jupyter notebook for downloading satellite imagery"
14
14
  dependencies = [
15
- "coastsat-package>=0.1.11",
15
+ "coastsat-package>=0.1.12",
16
16
  "area",
17
17
  "doodleverse-utils>=0.0.29",
18
18
  "ipyfilechooser>=0.6.0",
@@ -22,7 +22,9 @@ dependencies = [
22
22
  "aiohttp",
23
23
  "nest-asyncio",
24
24
  "tensorflow",
25
- "dask"]
25
+ "dask",
26
+ "xarray",
27
+ "pyTMD"]
26
28
  license = { file="LICENSE" }
27
29
  requires-python = ">=3.8"
28
30
  classifiers = [
@@ -79,7 +79,8 @@ class Bounding_Box:
79
79
  crs (str, optional): coordinate reference system string. Defaults to 'EPSG:4326'.
80
80
 
81
81
  Returns:
82
- gpd.GeoDataFrame: geodataframe with geometry column = rectangle and given crs"""
82
+ gpd.GeoDataFrame: geodataframe with geometry column = rectangle and given crs
83
+ """
83
84
  geom = [shape(rectangle)]
84
85
  geojson_bbox = gpd.GeoDataFrame({"geometry": geom})
85
86
  geojson_bbox.crs = crs
@@ -1,3 +1,4 @@
1
+ from datetime import datetime
1
2
  import os
2
3
  import json
3
4
  import logging
@@ -19,7 +20,6 @@ from coastseg.observable import Observable
19
20
 
20
21
  from coastsat import (
21
22
  SDS_download,
22
- SDS_transects,
23
23
  )
24
24
  import pandas as pd
25
25
  import geopandas as gpd
@@ -195,11 +195,31 @@ class CoastSeg_Map:
195
195
  file_path = os.path.join(dir_path, file_name)
196
196
  if not os.path.isfile(file_path):
197
197
  continue
198
- elif (
199
- file_name == "transects_settings.json"
200
- or file_name == "shoreline_settings.json"
201
- ):
202
- self.load_settings(file_path)
198
+ if file_name == "shoreline_settings.json":
199
+ keys = [
200
+ "cloud_thresh",
201
+ "cloud_mask_issue",
202
+ "min_beach_area",
203
+ "min_length_sl",
204
+ "output_epsg",
205
+ "sand_color",
206
+ "pan_off",
207
+ "max_dist_ref",
208
+ "dist_clouds",
209
+ "percent_no_data",
210
+ ]
211
+ self.load_settings(file_path, keys)
212
+ elif file_name == "transects_settings.json":
213
+ keys = [
214
+ "max_std",
215
+ "min_points",
216
+ "along_dist",
217
+ "max_range",
218
+ "min_chainage",
219
+ "multiple_inter",
220
+ "prc_multiple",
221
+ ]
222
+ self.load_settings(file_path, keys)
203
223
  if not config_loaded:
204
224
  logger.info(f"Not all config files not found at {dir_path}")
205
225
 
@@ -281,38 +301,13 @@ class CoastSeg_Map:
281
301
  # update observable list of ROI ids with extracted shorelines
282
302
  self.roi_ids_with_extracted_shorelines.set(ids_with_extracted_shorelines)
283
303
 
284
- def load_settings(self, filepath: str = "", new_settings: dict = {}):
285
- """
286
- Load settings from a JSON file. Only loads settings for transects and shorelines.
287
- If no JSON file is provided then load then load from new_settings.
288
-
289
- Args:
290
- filepath: The path to the JSON file containing the new settings.
291
- new_settings: A dictionary of new settings to apply.
292
-
293
- Returns:
294
- None.
295
- """
296
- new_settings = common.read_json_file(filepath, raise_error=False)
297
- if new_settings is None:
298
- new_settings = {}
299
- # load in transect settings if found
300
- transect_keys = [
301
- "max_std",
302
- "min_points",
303
- "along_dist",
304
- "max_range",
305
- "min_chainage",
306
- "multiple_inter",
307
- "prc_multiple",
308
- ]
309
- transect_settings = common.filter_dict_by_keys(new_settings, keys=transect_keys)
310
- if transect_settings != {}:
311
- logger.info(f"Loading transect_settings: {transect_settings}")
312
- self.set_settings(**transect_settings)
313
- logger.info(f"Loaded transect_settings from {filepath}")
314
-
315
- shoreline_keys = [
304
+ def load_settings(
305
+ self,
306
+ filepath: str = "",
307
+ keys: set = (
308
+ "sat_list",
309
+ "dates",
310
+ "sand_color",
316
311
  "cloud_thresh",
317
312
  "cloud_mask_issue",
318
313
  "min_beach_area",
@@ -323,18 +318,74 @@ class CoastSeg_Map:
323
318
  "max_dist_ref",
324
319
  "dist_clouds",
325
320
  "percent_no_data",
326
- ]
327
- shoreline_settings = {
328
- k: v for k, v in new_settings.items() if k in shoreline_keys
329
- }
330
- shoreline_settings["save_figure"] = True
331
- shoreline_settings["check_detection"] = False
332
- shoreline_settings["adjust_detection"] = False
321
+ "max_std",
322
+ "min_points",
323
+ "along_dist",
324
+ "max_range",
325
+ "min_chainage",
326
+ "multiple_inter",
327
+ "prc_multiple",
328
+ ),
329
+ load_nested_settings:bool=True,
330
+ ):
331
+ """
332
+ Loads settings from a JSON file and applies them to the object.
333
+
334
+ Args:
335
+ filepath (str, optional): The filepath to the JSON file containing the settings. Defaults to an empty string.
336
+ load_nested_setting (bool, optional): Load settings from a nest subdictionary 'settings' or not.
337
+ keys (list or set, optional): A list of keys specifying which settings to load from the JSON file. If empty, no settings are loaded. Defaults to a set with the following
338
+ "sat_list",
339
+ "dates",
340
+ "cloud_thresh",
341
+ "cloud_mask_issue",
342
+ "min_beach_area",
343
+ "min_length_sl",
344
+ "output_epsg",
345
+ "sand_color",
346
+ "pan_off",
347
+ "max_dist_ref",
348
+ "dist_clouds",
349
+ "percent_no_data",
350
+ "max_std",
351
+ "min_points",
352
+ "along_dist",
353
+ "max_range",
354
+ "min_chainage",
355
+ "multiple_inter",
356
+ "prc_multiple".
357
+
358
+ Returns:
359
+ None
360
+
361
+ """
362
+ # Convert keys to a list if a set is passed
363
+ if isinstance(keys, set):
364
+ keys = list(keys)
333
365
 
334
- if shoreline_settings != {}:
335
- logger.info(f"Loading shoreline_settings: {shoreline_settings}")
336
- self.set_settings(**shoreline_settings)
337
- logger.info(f"Loaded shoreline_settings from {filepath}")
366
+ new_settings = common.read_json_file(filepath, raise_error=False)
367
+ logger.info(f"all of new settings read from file : {filepath} \n {new_settings}")
368
+
369
+ nested_settings = new_settings.get('settings',{})
370
+ logger.info(f"all of new nested settings read from file : {filepath} \n {nested_settings }")
371
+
372
+
373
+ if new_settings is None:
374
+ new_settings = {}
375
+
376
+ # Load only settings with provided keys
377
+ if keys:
378
+ new_settings = {k: new_settings[k] for k in keys if k in new_settings}
379
+ if nested_settings:
380
+ nested_settings = {k: nested_settings[k] for k in keys if k in nested_settings}
381
+
382
+ if new_settings != {}:
383
+ self.set_settings(**new_settings)
384
+ if nested_settings != {} and load_nested_settings:
385
+ self.set_settings(**nested_settings)
386
+ logger.info(
387
+ f"Loaded new_settings from {filepath}:\n new self.settings {self.settings}"
388
+ )
338
389
 
339
390
  def load_gdf_config(self, filepath: str) -> None:
340
391
  """Load features from geodataframe located in geojson file at filepath onto map.
@@ -457,55 +508,62 @@ class CoastSeg_Map:
457
508
  It replaces the coastseg_map.settings with the settings from the config file,
458
509
  and replaces the roi_settings for each ROI with the contents of the json_data.
459
510
  Finally, it saves the input dictionaries for all ROIs.
460
- Parameters:
461
- self (object): CoastsegMap instance
462
- filepath (str): The filepath to the json config file
463
- datapath(str): full path to the coastseg data directory
511
+
512
+ Args:
513
+ self (object): CoastsegMap instance
514
+ filepath (str): The filepath to the json config file
515
+ datapath (str): Full path to the coastseg data directory
516
+
464
517
  Returns:
465
518
  None
519
+
520
+ Raises:
521
+ FileNotFoundError: If the config file is not found
522
+ MissingDirectoriesError: If one or more directories specified in the config file are missing
523
+
466
524
  """
467
525
  logger.info(f"filepath: {filepath}")
468
526
  exception_handler.check_if_None(self.rois)
527
+
469
528
  json_data = common.read_json_file(filepath, raise_error=True)
470
- if json_data is None:
471
- json_data = {}
472
- # replace coastseg_map.settings with settings from config file
473
- self.set_settings(**json_data["settings"])
474
- # replace roi_settings for each ROI with contents of json_data
529
+ json_data = json_data or {}
530
+
531
+ # Replace coastseg_map.settings with settings from config file
532
+ self.set_settings(**json_data.get("settings", {}))
533
+
534
+ # Replace roi_settings for each ROI with contents of json_data
475
535
  roi_settings = {}
476
- # flag raised if a single directory is missing
477
536
  missing_directories = []
537
+ fields_of_interest = [
538
+ "dates",
539
+ "sitename",
540
+ "polygon",
541
+ "roi_id",
542
+ "sat_list",
543
+ "sitename",
544
+ "landsat_collection",
545
+ "filepath",
546
+ ]
547
+
478
548
  logger.info(f"json_data: {json_data}\n")
479
- for roi_id in json_data["roi_ids"]:
549
+
550
+ for roi_id in json_data.get("roi_ids", []):
480
551
  logger.info(f"roi_id: {roi_id}")
481
- # extract the fields of interest from the config dictionary
482
- fields_of_interest = [
483
- "dates",
484
- "sitename",
485
- "polygon",
486
- "roi_id",
487
- "sat_list",
488
- "sitename",
489
- "landsat_collection",
490
- "filepath",
491
- ]
492
- roi_data = common.extract_fields(json_data, roi_id, fields_of_interest)
493
- if not roi_data:
494
- logger.error(f"json_data: {json_data}")
495
- raise Exception(
496
- f"Invalid config.json file detected. Please add the correct roi ids to the config.json file's 'roi_ids' and try again.\nContents of config.json file's 'roi_ids':{json_data['roi_ids']}"
497
- )
498
- # update the roi location to be one relevant to the current computer
552
+ # get the fields of interest from an roi with a matching id
553
+ roi_data = common.extract_roi_data(json_data, roi_id, fields_of_interest)
554
+
499
555
  sitename = roi_data.get("sitename", "")
500
556
  roi_path = os.path.join(data_path, sitename)
501
557
  roi_data["filepath"] = data_path
558
+
502
559
  if not os.path.exists(roi_path):
503
560
  missing_directories.append(sitename)
504
- # copy setting from json file to roi
561
+
505
562
  roi_settings[str(roi_id)] = roi_data
506
563
 
507
564
  # if any directories are missing tell the user list of missing directories
508
565
  exception_handler.check_if_dirs_missing(missing_directories)
566
+
509
567
  # Save input dictionaries for all ROIs
510
568
  self.rois.roi_settings = roi_settings
511
569
  logger.info(f"roi_settings: {roi_settings}")
@@ -523,8 +581,9 @@ class CoastSeg_Map:
523
581
  # check if config files exist
524
582
  config_geojson_path = os.path.join(dir_path, "config_gdf.geojson")
525
583
  config_json_path = os.path.join(dir_path, "config.json")
526
- logger.info(f"config_geojson_path: {config_geojson_path}")
527
- logger.info(f"config_json_path: {config_json_path}")
584
+ logger.info(
585
+ f"config_gdf.geojson: {config_geojson_path} \n config.json location: {config_json_path}"
586
+ )
528
587
  # cannot load config.json file if config_gdf.geojson file is missing
529
588
  if not os.path.exists(config_geojson_path):
530
589
  logger.warning(f"config_gdf.geojson file missing at {config_geojson_path}")
@@ -590,7 +649,11 @@ class CoastSeg_Map:
590
649
  if not selected_rois.empty:
591
650
  epsg_code = selected_rois.crs
592
651
  config_gdf = common.create_config_gdf(
593
- selected_rois,shorelines_gdf=shorelines_gdf, transects_gdf=transects_gdf,bbox_gdf=bbox_gdf,epsg_code = epsg_code
652
+ selected_rois,
653
+ shorelines_gdf=shorelines_gdf,
654
+ transects_gdf=transects_gdf,
655
+ bbox_gdf=bbox_gdf,
656
+ epsg_code=epsg_code,
594
657
  )
595
658
  logger.info(f"config_gdf: {config_gdf} ")
596
659
  is_downloaded = common.were_rois_downloaded(self.rois.roi_settings, roi_ids)
@@ -636,9 +699,10 @@ class CoastSeg_Map:
636
699
  Returns:
637
700
  None
638
701
  """
702
+ logger.info(f"New Settings: {kwargs}")
639
703
  # Check if any of the keys are missing
640
704
  # if any keys are missing set the default value
641
- default_settings = {
705
+ self.default_settings = {
642
706
  "landsat_collection": "C02",
643
707
  "dates": ["2017-12-01", "2018-01-01"],
644
708
  "sat_list": ["L8"],
@@ -651,7 +715,6 @@ class CoastSeg_Map:
651
715
  # if True, allows user to adjust the position of each shoreline by changing the threshold
652
716
  "adjust_detection": False,
653
717
  "save_figure": True, # if True, saves a figure showing the mapped shoreline for each image
654
- # [ONLY FOR ADVANCED USERS] shoreline detection parameters:
655
718
  # minimum area (in metres^2) for an object to be labelled as a beach
656
719
  "min_beach_area": 4500,
657
720
  # minimum length (in metres) of shoreline perimeter to be valid
@@ -670,45 +733,79 @@ class CoastSeg_Map:
670
733
  "multiple_inter": "auto", # mode for removing outliers ('auto', 'nan', 'max')
671
734
  "prc_multiple": 0.1, # percentage of the time that multiple intersects are present to use the max
672
735
  }
673
- if kwargs:
674
- self.settings.update({key: value for key, value in kwargs.items()})
675
- self.settings.update(
676
- {
677
- key: default_settings[key]
678
- for key in default_settings
679
- if key not in self.settings
680
- }
681
- )
736
+ self.settings.update(kwargs)
737
+ if "dates" in kwargs.keys():
738
+ updated_dates = []
739
+ self.settings["dates"] = kwargs['dates']
740
+ for date_str in kwargs['dates']:
741
+ try:
742
+ dt = datetime.strptime(date_str, '%Y-%m-%dT%H:%M:%S')
743
+ except ValueError:
744
+ dt = datetime.strptime(date_str, '%Y-%m-%d')
745
+ updated_dates.append(dt.strftime('%Y-%m-%d'))
746
+ self.settings["dates"] = updated_dates
747
+
748
+ for key, value in self.default_settings.items():
749
+ self.settings.setdefault(key, value)
750
+
682
751
  logger.info(f"Settings: {self.settings}")
683
752
 
684
753
  def get_settings(self):
754
+ """
755
+ Retrieves the current settings.
756
+
757
+ Returns:
758
+ dict: A dictionary containing the current settings.
759
+
760
+ Raises:
761
+ Exception: If no settings are found. Click save settings or load a config file.
762
+
763
+ """
685
764
  SETTINGS_NOT_FOUND = (
686
765
  "No settings found. Click save settings or load a config file."
687
766
  )
688
767
  logger.info(f"self.settings: {self.settings}")
689
768
  if self.settings is None or self.settings == {}:
690
769
  raise Exception(SETTINGS_NOT_FOUND)
691
-
692
- self.settings.setdefault("cloud_mask_issue", False)
693
- self.settings.setdefault("cloud_thresh", 99.9)
694
770
  return self.settings
695
771
 
696
- def update_transects_html(self, feature, **kwargs):
697
- # Modifies html when transect is hovered over
698
- values = defaultdict(lambda: "unknown", feature["properties"])
699
- self.feature_html.value = """
700
- <div style='max-width: 230px; max-height: 200px; overflow-x: auto; overflow-y: auto'>
701
- <b>Transect</b>
702
- <p>Id: {}</p>
703
- <p>Slope: {}</p>
704
- """.format(
705
- values["id"],
706
- values["slope"],
772
+ def update_transects_html(self, feature: dict, **kwargs):
773
+ """
774
+ Modifies the HTML when a transect is hovered over.
775
+
776
+ Args:
777
+ feature (dict): The transect feature.
778
+ **kwargs: Additional keyword arguments.
779
+
780
+ Returns:
781
+ None
782
+
783
+ """
784
+ properties = feature["properties"]
785
+ transect_id = properties.get("id", "unknown")
786
+ slope = properties.get("slope", "unknown")
787
+
788
+ self.feature_html.value = (
789
+ "<div style='max-width: 230px; max-height: 200px; overflow-x: auto; overflow-y: auto'>"
790
+ "<b>Transect</b>"
791
+ f"<p>Id: {transect_id}</p>"
792
+ f"<p>Slope: {slope}</p>"
707
793
  )
708
794
 
709
795
  def update_extracted_shoreline_html(self, feature, **kwargs):
796
+ """
797
+ Modifies the HTML content when an extracted shoreline is hovered over.
798
+
799
+ Args:
800
+ feature (dict): The extracted shoreline feature.
801
+ **kwargs: Additional keyword arguments.
802
+
803
+ Returns:
804
+ None
805
+
806
+ """
710
807
  # Modifies html when extracted shoreline is hovered over
711
- values = defaultdict(lambda: "unknown", feature["properties"])
808
+ properties = defaultdict(lambda: "unknown", feature["properties"])
712
809
  self.feature_html.value = """
713
810
  <div style='max-width: 230px; max-height: 200px; overflow-x: auto; overflow-y: auto'>
714
811
  <b>Extracted Shoreline</b>
@@ -717,10 +814,10 @@ class CoastSeg_Map:
717
814
  <p>Cloud Cover: {}</p>
718
815
  <p>Satellite Name: {}</p>
719
816
  """.format(
720
- values["date"],
721
- values["geoaccuracy"],
722
- values["cloud_cover"],
723
- values["satname"],
817
+ properties["date"],
818
+ properties["geoaccuracy"],
819
+ properties["cloud_cover"],
820
+ properties["satname"],
724
821
  )
725
822
 
726
823
  def update_roi_html(self, feature, **kwargs):
@@ -1045,7 +1142,6 @@ class CoastSeg_Map:
1045
1142
  selected_rois_gdf = self.rois.gdf[self.rois.gdf["id"].isin(roi_ids)]
1046
1143
  return selected_rois_gdf
1047
1144
 
1048
-
1049
1145
  def get_cross_distance(
1050
1146
  self,
1051
1147
  roi_id: str,
@@ -1110,78 +1206,6 @@ class CoastSeg_Map:
1110
1206
 
1111
1207
  return cross_distance, failure_reason
1112
1208
 
1113
- # def get_cross_distance(self,
1114
- # roi_id: str,
1115
- # transects_in_roi_gdf:gpd.GeoDataFrame,
1116
- # settings: dict,
1117
- # output_epsg: str):
1118
- # """
1119
- # Compute the cross shore distance of transects and extracted shorelines for a given ROI.
1120
-
1121
- # Parameters:
1122
- # -----------
1123
- # roi_id : str
1124
- # The ID of the ROI to compute the cross shore distance for.
1125
- # transects_in_roi_gdf : gpd.GeoDataFrame
1126
- # All the transects in the ROI.
1127
- # Must contain the columns ["id", "geometry"]
1128
- # settings : dict
1129
- # A dictionary of settings to be used in the computation.
1130
- # output_epsg : str
1131
- # The EPSG code of the output projection.
1132
-
1133
- # Returns:
1134
- # --------
1135
- # float
1136
- # The computed cross shore distance, or 0 if there was an issue in the computation.
1137
-
1138
- # Raises:
1139
- # -------
1140
- # exceptions.No_Extracted_Shoreline
1141
- # Raised if no shorelines were extracted for the ROI with roi_id
1142
-
1143
- # Usage:
1144
- # ------
1145
- # cross_distance = get_cross_distance(roi_id, settings, output_epsg)
1146
- # """
1147
- # failure_reason = None
1148
- # cross_distance = 0
1149
-
1150
- # # get extracted shorelines object for the currently selected ROI
1151
- # roi_extracted_shoreline = self.rois.get_extracted_shoreline(roi_id)
1152
-
1153
- # # transects_in_roi_gdf = transects_in_roi_gdf[["id", "geometry"]]
1154
- # transects_in_roi_gdf = transects_in_roi_gdf.loc[:, ["id", "geometry"]]
1155
-
1156
- # if roi_extracted_shoreline is None:
1157
- # failure_reason = "No extracted shorelines were found"
1158
- # elif transects_in_roi_gdf.empty:
1159
- # failure_reason = "No transects intersected the ROI"
1160
- # else:
1161
- # extracted_shoreline_x_transect = transects_in_roi_gdf[
1162
- # transects_in_roi_gdf.intersects(roi_extracted_shoreline.gdf.unary_union)
1163
- # ]
1164
- # if extracted_shoreline_x_transect.empty:
1165
- # cross_distance = 0
1166
- # failure_reason = "No extracted shorelines intersected transects"
1167
- # else:
1168
- # # convert transects_in_roi_gdf to output_crs from settings
1169
- # transects_in_roi_gdf = transects_in_roi_gdf.to_crs(output_epsg)
1170
- # # compute cross shore distance of transects and extracted shorelines
1171
- # extracted_shorelines_dict = roi_extracted_shoreline.dictionary
1172
- # cross_distance = self.compute_transects_from_roi(
1173
- # roi_id,
1174
- # extracted_shorelines_dict,
1175
- # transects_in_roi_gdf,
1176
- # settings,
1177
- # )
1178
-
1179
- # if cross_distance == 0:
1180
- # logger.warning(f"{failure_reason} for ROI {roi_id}")
1181
- # print(f"{failure_reason} for ROI {roi_id}")
1182
-
1183
- # return cross_distance
1184
-
1185
1209
  def save_timeseries_csv(self, session_path: str, roi_id: str, rois: ROI) -> None:
1186
1210
  """Saves cross distances of transects and
1187
1211
  extracted shorelines in ROI to csv file within each ROI's directory.
@@ -1961,7 +1985,7 @@ class CoastSeg_Map:
1961
1985
  ):
1962
1986
  """
1963
1987
  Save a geographical feature (Bounding_Box, Shoreline, Transects, ROI) as a GeoJSON file.
1964
-
1988
+
1965
1989
  Args:
1966
1990
  feature (Union[Bounding_Box, Shoreline, Transects, ROI]): The geographical feature to save.
1967
1991
  feature_type (str, optional): The type of the feature, e.g. Bounding_Box, Shoreline, Transects, or ROI.