Giter Club home page Giter Club logo

satelliteshorelines / coastseg Goto Github PK

View Code? Open in Web Editor NEW
37.0 3.0 5.0 265.42 MB

An interactive toolbox for downloading satellite imagery, applying image segmentation models, mapping shoreline positions and more. The mapping extension for CoastSat and Zoo.

Home Page: https://satelliteshorelines.github.io/CoastSeg/

License: GNU General Public License v3.0

Python 17.05% Jupyter Notebook 82.83% TeX 0.12%
earth-engine jupyter python landsat colab

coastseg's People

Contributors

2320sharon avatar dbuscombe-usgs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

coastseg's Issues

New Feature: Load bbox from geojson file

I would like the ability to load a bbox onto the map from the file created by the save bbox button.
It should allow the user to open their file explorer to select a geojson file. Check if it is a valid geojson file and throw an error if not. Once the bbox is loaded onto the map shapes_list and self.bbox should be updated to include this new bbox.

CoastSat SDS_download.py retrieve_images exception handling

Bug: SDS_download.py has Bad Error Handling

CoastSat does not have specific error handling when running download_tif within retrieve _images(). If any kind of exception occurs whether that be due to the file not being downloaded, the file not being available, or anything else the user will not know what caused the exception and be unable to fix it. Furthermore, this loop should not run 100 times as this could cause 100 unnecessary prints or requests. When I fix this bug I will create a Pull Request for CoastSat. For now, I'm leaving this here as a reminder for me to dig deeper into this issue and the best ways to solve it.

Faulty Code

Filename: SDS_download.py
Function: retrieve _images

                while True:
                    try:    
                        fn_ms, fn_QA = download_tif(image_ee,ee_region,bands['ms'],fp_ms) 
                        break
                    except:
                        print('\nDownload failed, trying again...')
                        count += 1
                        if count > 100:
                            raise Exception('Too many attempts, crashed while downloading image %s'%im_meta['id'])
                        else:
                            continue

NotImplementedError: Multi-part geometries do not themselves provide the array interface

the bug

I run app.ipynb with the older coastseg env (see #68). I execute each cell as-is, without modifying anything. I draw an ROI:

image

and get the following error

Generating ROIs please wait.

---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
File ~/anaconda3/envs/coastseg/lib/python3.8/site-packages/ipywidgets/widgets/widget_output.py:103, in Output.capture.<locals>.capture_decorator.<locals>.inner(*args, **kwargs)
    101     self.clear_output(*clear_args, **clear_kwargs)
    102 with self:
--> 103     return func(*args, **kwargs)

Input In [6], in on_gen_button_clicked(b)
     18 print("Generating ROIs please wait.") 
     19 # Generate ROIs along the coastline within the bounding box
---> 20 coastseg_map.generate_ROIS_fishnet()
     21 debug_view.clear_output(wait=True)
     22 # Add the Clickable ROIs to the map

File /media/marda/ExtraDrive1/satellites/CoastSeg/CoastSeg/coastseg_map_class.py:229, in CoastSeg_Map.generate_ROIS_fishnet(self)
    227 bbox.validate_bbox_size(self.shapes_list)
    228 # dictionary containing geojson coastline
--> 229 roi_coastline = bbox.get_coastline(CoastSeg_Map.shoreline_file, self.shapes_list)
    230 # coastline geojson styled for the map
    231 self.coastline_for_map = self.get_coastline_layer(roi_coastline)

File /media/marda/ExtraDrive1/satellites/CoastSeg/CoastSeg/bbox.py:136, in get_coastline(shoreline_file, bbox)
    119 """
    120      geojson containing the clipped portion of the coastline in bounding box
    121 
   (...)
    133 
    134 """
    135 # Read the coastline vector from a geopandas geodataframe file
--> 136 shoreline = read_gpd_file(shoreline_file)
    137 # Convert bbox to GDP
    138 geojson_bbox = create_geodataframe_from_bbox(bbox)

File /media/marda/ExtraDrive1/satellites/CoastSeg/CoastSeg/bbox.py:28, in read_gpd_file(filename)
     26 if os.path.exists(filename):
     27     with open(filename, 'r') as f:
---> 28         gpd_data = gpd.read_file(f)
     29 else:
     30     print('File does not exist. Please download the coastline_vector necessary here: https://geodata.lib.berkeley.edu/catalog/stanford-xv279yj9196 ')

File ~/anaconda3/envs/coastseg/lib/python3.8/site-packages/geopandas/io/file.py:203, in _read_file(filename, bbox, mask, rows, **kwargs)
    198 if kwargs.get("ignore_geometry", False):
    199     return pd.DataFrame(
    200         [record["properties"] for record in f_filt], columns=columns
    201     )
--> 203 return GeoDataFrame.from_features(
    204     f_filt, crs=crs, columns=columns + ["geometry"]
    205 )

File ~/anaconda3/envs/coastseg/lib/python3.8/site-packages/geopandas/geodataframe.py:587, in GeoDataFrame.from_features(cls, features, crs, columns)
    585     row.update(feature["properties"])
    586     rows.append(row)
--> 587 return GeoDataFrame(rows, columns=columns, crs=crs)

File ~/anaconda3/envs/coastseg/lib/python3.8/site-packages/geopandas/geodataframe.py:138, in GeoDataFrame.__init__(self, geometry, crs, *args, **kwargs)
    127         warnings.warn(
    128             "CRS mismatch between CRS of the passed geometries "
    129             "and 'crs'. Use 'GeoDataFrame.set_crs(crs, "
   (...)
    135             stacklevel=2,
    136         )
    137         # TODO: raise error in 0.9 or 0.10.
--> 138     self["geometry"] = _ensure_geometry(self["geometry"].values, crs)
    139 except TypeError:
    140     pass

File ~/anaconda3/envs/coastseg/lib/python3.8/site-packages/geopandas/geodataframe.py:43, in _ensure_geometry(data, crs)
     41     return GeoSeries(out, index=data.index, name=data.name)
     42 else:
---> 43     out = from_shapely(data, crs=crs)
     44     return out

File ~/anaconda3/envs/coastseg/lib/python3.8/site-packages/geopandas/array.py:168, in from_shapely(data, crs)
    152 def from_shapely(data, crs=None):
    153     """
    154     Convert a list or array of shapely objects to a GeometryArray.
    155 
   (...)
    166 
    167     """
--> 168     return GeometryArray(vectorized.from_shapely(data), crs=crs)

File ~/anaconda3/envs/coastseg/lib/python3.8/site-packages/geopandas/_vectorized.py:142, in from_shapely(data)
    140 aout = np.empty(len(data), dtype=object)
    141 with compat.ignore_shapely2_warnings():
--> 142     aout[:] = out
    143 return aout

File ~/anaconda3/envs/coastseg/lib/python3.8/site-packages/shapely/geometry/base.py:854, in BaseMultipartGeometry.__array_interface__(self)
    851 @property
    852 def __array_interface__(self):
    853     """Provide the Numpy array protocol."""
--> 854     raise NotImplementedError("Multi-part geometries do not themselves "
    855                               "provide the array interface")

NotImplementedError: Multi-part geometries do not themselves provide the array interface

Steps To Reproduce

Steps to reproduce the behavior:

  1. activate conda env
  2. jupyter notebook
  3. select app.ipynb and run the first few cells unmodified
  4. See error

Comments

I'm guessing this is a shapely version problem

Make two separate `ipynb` notebooks and rename them

There are 2 separate workflows for CoastSeg

  1. using the Coast classifier
  2. using a Gym-based deep learning classifier

These should be separate notebooks, and named appropriately. The name custom_map doesn't quite convey the meaning we need, I therefore suggest two separate ipynb files with the names

  1. 'SDS_coastsat_classifier.ipynb`
  2. SDS_unet_classifier.ipynb

The former is almost ready, and we're making progress with the latter

MNDWI SWED Model Error

MNDWI SWED Model Error

  • When I try to run the swed_water_mndwi model I get the following error which leads me to suspect the RGB_to_MNDWI() outputs are incorrect. I used the data_sample.zip associated with the model at the Zenodo release . I've included the notebook and data to replicate this issue at the following branch on GitHub https://github.com/2320sharon/CoastSeg/tree/new_feature/MNDWI_models and included the same data in this issue.
  • The notebook MNDWI_model_error_notebook.ipynb is on that branch which will let you replicate the error
  • The notebook is also the zip file I have included.

RGB_to_MNDWI()Function

  • Take three arguments :
  1. the path to the directory containing the RGB images
  2. the path to the directory containing the NIR images
  3. the path to the directory to store the MNDWI outputs in directory called 'MNDWI_outputs'
def RGB_to_MNDWI(self, RGB_dir_path:str, NIR_dir_path :str, output_path:str)->None:
        """Converts two directories of RGB and NIR imagery to MNDWI imagery in a directory named
         'MNDWI_outputs'.

        Args:
            RGB_dir_path (str): full path to directory containing RGB images
            NIR_dir_path (str): full path to directory containing NIR images
        
        Original Code from doodleverse_utils by Daniel Buscombe
        source: https://github.com/Doodleverse/doodleverse_utils
        """        
        paths=[RGB_dir_path,NIR_dir_path]
        files=[]
        for data_path in paths:
            if not os.path.exists(data_path):
                raise FileNotFoundError(f"{data_path} not found")
            f = sorted(glob(data_path+os.sep+'*.jpg'))
            if len(f)<1:
                f = sorted(glob(data_path+os.sep+'images'+os.sep+'*.jpg'))
            files.append(f)

        # creates matrix:  bands(RGB) x number of samples(NIR)
        # files=[['full_RGB_path.jpg','full_NIR_path.jpg'],
        # ['full_jpg_path.jpg','full_NIR_path.jpg']....]
        files = np.vstack(files).T

        # output_path: directory to store MNDWI outputs
        output_path += os.sep+ 'MNDWI_outputs'
        if not os.path.exists(output_path):
            os.mkdir(output_path)
        # Create subfolder to hold MNDWI ouputs in
        output_path=mk_new_dir('MNDWI_ouputs',output_path )
        

        for counter,f in enumerate(files):
            datadict={}
            # Read green band from RGB image and cast to float
            green_band = imread(f[0])[:,:,1].astype('float')
            # Read SWIR and cast to float
            swir = imread(f[1]).astype('float')
            # Transform 0 to np.NAN 
            green_band[green_band==0]=np.nan
            swir[swir==0]=np.nan
            # Mask out the NaNs
            green_band = np.ma.filled(green_band)
            swir = np.ma.filled(swir)
            
            # MNDWI imagery formula (Green – SWIR) / (Green + SWIR)
            mndwi = np.divide(swir - green_band, swir + green_band)
            # Convert the NaNs to -1
            mndwi[np.isnan(mndwi)]=-1
            # Rescale to be between 0 - 255
            mndwi = self.rescale_array(mndwi,0,255)
            # Save meta data for savez_compressed()
            datadict['arr_0'] = mndwi.astype(np.uint8)
            datadict['num_bands'] = 1
            datadict['files'] = [fi.split(os.sep)[-1] for fi in f]
            # Remove the file extension from the name
            ROOT_STRING = f[0].split(os.sep)[-1].split('.')[0]
            # save MNDWI as .npz file 
            segfile = output_path+os.sep+ROOT_STRING+'_noaug_nd_data_000000'+str(counter)+'.npz'
            np.savez_compressed(segfile, **datadict)
            del datadict, mndwi, green_band, swir
            
        return output_path

Error Message

WARNING:tensorflow:Model was constructed with shape (None, 256, 256, 1) for input KerasTensor(type_spec=TensorSpec(shape=(None, 256, 256, 1), dtype=tf.float32, name='input_1'), name='input_1', description="created by layer 'input_1'"), but it was called on an input with incompatible shape (1, 256, 256, 3).
  0%|                                                                                           | 0/16 [00:00<?, ?it/s]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_7376\3195802537.py in <module>
     18 metadatadict=zoo_model.get_metadatadict(Ww,config_files, model_types)
     19 # # Compute the segmentation
---> 20 zoo_model.compute_segmentation(model_dict["sample_direc"], model_list, metadatadict)

C:\1_USGS\CoastSeg\repos\2_CoastSeg\CoastSeg_fork\Seg2Map\CoastSeg\zoo_model_module.py in compute_segmentation(self, sample_direc, model_list, metadatadict)
     51                 self.TARGET_SIZE,
     52                 TESTTIMEAUG,
---> 53                 WRITE_MODELMETADATA)
     54 
     55     def get_model(self, Ww: list):

~\anaconda3\envs\coastseg\lib\site-packages\doodleverse_utils\prediction_imports.py in do_seg(f, M, metadatadict, sample_direc, NCLASSES, N_DATA_BANDS, TARGET_SIZE, TESTTIMEAUG, WRITE_MODELMETADATA)
    169             # heatmap = make_gradcam_heatmap(tf.expand_dims(image, 0) , model)
    170 
--> 171             est_label = model.predict(tf.expand_dims(image, 0), batch_size=1).squeeze()
    172 
    173             if TESTTIMEAUG == True:

~\anaconda3\envs\coastseg\lib\site-packages\keras\utils\traceback_utils.py in error_handler(*args, **kwargs)
     65     except Exception as e:  # pylint: disable=broad-except
     66       filtered_tb = _process_traceback_frames(e.__traceback__)
---> 67       raise e.with_traceback(filtered_tb) from None
     68     finally:
     69       del filtered_tb

~\anaconda3\envs\coastseg\lib\site-packages\keras\engine\training.py in tf__predict_function(iterator)
     13                 try:
     14                     do_return = True
---> 15                     retval_ = ag__.converted_call(ag__.ld(step_function), (ag__.ld(self), ag__.ld(iterator)), None, fscope)
     16                 except:
     17                     do_return = False

ValueError: in user code:

    File "C:\Users\Sharon\anaconda3\envs\coastseg\lib\site-packages\keras\engine\training.py", line 1845, in predict_function  *
        return step_function(self, iterator)
    File "C:\Users\Sharon\anaconda3\envs\coastseg\lib\site-packages\keras\engine\training.py", line 1834, in step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    File "C:\Users\Sharon\anaconda3\envs\coastseg\lib\site-packages\keras\engine\training.py", line 1823, in run_step  **
        outputs = model.predict_step(data)
    File "C:\Users\Sharon\anaconda3\envs\coastseg\lib\site-packages\keras\engine\training.py", line 1791, in predict_step
        return self(x, training=False)
    File "C:\Users\Sharon\anaconda3\envs\coastseg\lib\site-packages\keras\utils\traceback_utils.py", line 67, in error_handler
        raise e.with_traceback(filtered_tb) from None
    File "C:\Users\Sharon\anaconda3\envs\coastseg\lib\site-packages\keras\engine\input_spec.py", line 249, in assert_input_compatibility
        f'Input {input_index} of layer "{layer_name}" is '

    ValueError: Exception encountered when calling layer "model" (type Functional).
    
    Input 0 of layer "conv2d" is incompatible with the layer: expected axis -1 of input shape to have value 1, but received input with shape (1, 256, 256, 3)
    
    Call arguments received by layer "model" (type Functional):
      • inputs=tf.Tensor(shape=(1, 256, 256, 3), dtype=float64)
      • training=False
      • mask=None


Notebook to Replicate Issue

  • You will need to checkout to branch https://github.com/2320sharon/CoastSeg/tree/new_feature/MNDWI_models to run this notebook properly
  • The notebook MNDWI_model_error_notebook.ipynb is on that branch which will let you replicate the error

Data

I included the sample data I used to create the MNDWI outputs as well as the outputs I generated
[zenodo_sample_data.zip](https://github
MNDWI_model_error_notebook.zip
.com/dbuscombe-usgs/CoastSeg/files/9162860/zenodo_sample_data.zip)
MNDWI_ouputs_2022-07-21__07_hr_57_min14.zip

This toolbox facilitates automated/batched download of imagery in tiles

Zoo and Doodler work with relatively small sized imagery

  • import shoreline vectors (start with US only)
  • Grids must be created and overlain that intersect these vectors
  • Grids can be manipulated based on criteria such as size(independently in x and y), and stride (number of grids to "skip")

Button to Upload Transects

There should be a button that can load transects from a geojson file. This button would allow the user to select a geojson file containing transects and load the transects onto the map

manually copy over `classification/models` from `CoastSat`

Using main 2320sharon@fc61aa7, in order to use extract_shorelines_from_rois in satellite_derived_shorelines.ipynb, you need to manually copy over classification/models from CoastSat

It is inconvenient and a novice user would not know to do this, so we should come up with a strategy for packaging up the classification models. These are .pkl files that carry out the image segmentation in CoastSat

How should ROI size be calculated?

Discussed in #77

Transferring this Discussion to an Issue so we can migrate this repo to the new org

Originally posted by 2320sharon September 7, 2022

How ROI Size is Currently defined

CoastSeg's ROI size should be accurate across all of the Earth so the user knows how much land their ROIs cover. Currently, the ROI's size is defined in meters according to ESPG 3857 and converted back to ESPG 4326 so it can be displayed on the ipyleaflet map. Unfortunately ESPG 3857 is not accurate across all of the world because in some regions the meters are squished together while in others they are much farther apart.

How to Proceed?

I am no expert on CRS and I don't know when I should convert from one to another. How should the size of the ROIs be defined in a way that's more accurate than the current method of defining it in meters in ESPG 3857?

Resources

  1. This post explains how each espg is used for Google Maps and Google Earth.
  2. Here is the units for espg 3857.
  3. https://www.esri.com/arcgis-blog/products/arcgis-pro/mapping/coordinate-systems-difference/

ImportError: cannot import name 'exception_handler' from 'coastseg'

With a refresh clone and a refresh install of the coastseg conda environment, I get the following error when running cell 9

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
Cell In [9], line 1
----> 1 from src.coastseg.map_UI import UI
      2 coastseg_ui = UI(coastsegmap)
      3 coastseg_ui.create_dashboard()

File ~\github_clones\CoastSeg\src\coastseg\map_UI.py:10
      8 from coastseg.tkinter_window_creator import Tkinter_Window_Creator
      9 from coastseg import exceptions
---> 10 from coastseg import exception_handler
     12 # external python imports
     13 import ipywidgets

ImportError: cannot import name 'exception_handler' from 'coastseg' (C:\Users\dbuscombe\Anaconda3\envs\coastseg\lib\site-packages\coastseg\__init__.py)

notebooks/prototype 6: recommendations for default ROI and bounding box size

After playing with prototype 6 (great) and looking at the imagery I'm downloading, I have recommendations over default roi size and max bounding box size

First, I recommend size=0.04 in create_reactangles

I realize that is not the most efficient in terms of downloading, but that it a better size for the ML

Second, MAX_BBOX_SIZE=3000000000 seems better for check_bbox_size

Fix CoastSat Jpg Save Issue

The latest version of CoastSat saves the jpgs as a matplotlib plot with the filename. The jpgs need to be saved as standard jpgs so that they can be used as inputs to machine learning models.

Create Automated Testing with GitHub Actions

Automated testing needs to be in place so that when new code is added to the project or CoastSat updates come it can be quickly determined if it breaks anything in the code. One problem that may be encountered when trying to build the testing suite is testing the functions that download imagery from Google Earth Engine because they require an authentication token. I believe the best solution to this problem is to mock the functions for now and ensure the rest of the logic works properly.

I think the testing of CoastSat functions should be left alone for now since CoastSat is still under serious development a subject to change. The testing for the rest of the modules should be done for now.

Kernel crashed during Zoo model implementation and also in `extract_shorelines_from_rois`

Using main 2320sharon@fc61aa7 and within an activated coastseg conda environment on Windows, I'm getting kernel crashes when running CoastSeg notebooks.

I used the default satellite list and date range and the attached ROI

coastseg-3
coastseg-2
coastseg-1

The jupyter kernel died when extract_shorelines_from_rois got through 5% of the L8 imagery

segmentation_data_2022-08-26__17_hr_51_min49.zip

Possibly related, when I run custom_map with default settings, and the default selected model landsat_6229071 without GPU, and in the same region (but not the exact same ROI), my kernel dies again ....it starts to run the models, then crashes

custommap-1
custommap-2

ID12022-08-26__17_hr_38_min20.zip

ID02022-08-26__17_hr_38_min20.zip

ID42022-08-26__17_hr_38_min20.zip

ID32022-08-26__17_hr_38_min20.zip

ID22022-08-26__17_hr_38_min20.zip

shorelines.zip

Thanks, let me know if you need more info @2320sharon

prototype 7 EE authentication issue

I made a new CoastSeg env on Windows and I'm getting an error when I run this cell

try:
    try:
        list_of_inputs=check_images_available_selected_ROI(selected_ROI)
        list_of_inputs
        if list_of_inputs == []:
            print("Error: No ROIs were selected. Please click a valid ROI on the map")
    except ee.EEException as exception:
        print(exception)
        raise AuthenticationError
except AuthenticationError:
    handle_AuthenticationError()

The output is

2022-02-03 15:12:20.946567
---------------------------------------------------------------------------
EEException                               Traceback (most recent call last)
~\github_clones\CoastSeg\notebooks\coastsat\SDS_download.py in check_images_available(inputs)
    388     try:
--> 389         ee.ImageCollection('LANDSAT/LT05/C01/T1_TOA')
    390     except:

~\Anaconda3\envs\new_coastseg\lib\site-packages\ee\computedobject.py in __call__(cls, *args, **kwargs)
     31     else:
---> 32       return type.__call__(cls, *args, **kwargs)
     33 

~\Anaconda3\envs\new_coastseg\lib\site-packages\ee\imagecollection.py in __init__(self, args)
     37     """
---> 38     self.initialize()
     39 

~\Anaconda3\envs\new_coastseg\lib\site-packages\ee\imagecollection.py in initialize(cls)
     71     if not cls._initialized:
---> 72       super(ImageCollection, cls).initialize()
     73       apifunction.ApiFunction.importApi(

~\Anaconda3\envs\new_coastseg\lib\site-packages\ee\collection.py in initialize(cls)
     31     if not cls._initialized:
---> 32       apifunction.ApiFunction.importApi(cls, 'Collection', 'Collection')
     33       apifunction.ApiFunction.importApi(

~\Anaconda3\envs\new_coastseg\lib\site-packages\ee\apifunction.py in importApi(cls, target, prefix, type_name, opt_prepend)
    182     """
--> 183     cls.initialize()
    184     prepend = opt_prepend or ''

~\Anaconda3\envs\new_coastseg\lib\site-packages\ee\apifunction.py in initialize(cls)
    153     if not cls._api:
--> 154       signatures = data.getAlgorithms()
    155       api = {}

~\Anaconda3\envs\new_coastseg\lib\site-packages\ee\data.py in getAlgorithms()
    980   try:
--> 981     call = _get_cloud_api_resource().projects().algorithms().list(
    982         parent=_get_projects_path(), prettyPrint=False)

~\Anaconda3\envs\new_coastseg\lib\site-packages\ee\data.py in _get_cloud_api_resource()
    288     raise ee_exception.EEException(
--> 289         'Earth Engine client library not initialized. Run `ee.Initialize()`')
    290   return _cloud_api_resource

EEException: Earth Engine client library not initialized. Run `ee.Initialize()`

During handling of the above exception, another exception occurred:

RefreshError                              Traceback (most recent call last)
~\AppData\Local\Temp\2\ipykernel_14904\1530565413.py in <module>
      1 try:
      2     try:
----> 3         list_of_inputs=check_images_available_selected_ROI(selected_ROI)
      4         list_of_inputs
      5         if list_of_inputs == []:

~\AppData\Local\Temp\2\ipykernel_14904\1653218588.py in check_images_available_selected_ROI(selected_ROI)
     34             inputs = {'polygon': polygon, 'dates': dates, 'sat_list': sat_list, 'sitename': sitename, 'filepath':filepath}
     35             # before downloading the images, check how many images are available for your inputs
---> 36             SDS_download.check_images_available(inputs)
     37             list_of_inputs.append(inputs)
     38     return list_of_inputs

~\github_clones\CoastSeg\notebooks\coastsat\SDS_download.py in check_images_available(inputs)
    389         ee.ImageCollection('LANDSAT/LT05/C01/T1_TOA')
    390     except:
--> 391         ee.Initialize()
    392 
    393     print('Images available between %s and %s:'%(inputs['dates'][0],inputs['dates'][1]), end='\n')

~\Anaconda3\envs\new_coastseg\lib\site-packages\ee\__init__.py in Initialize(credentials, opt_url, cloud_api_key, http_transport, project)
    121       cloud_api_key=cloud_api_key,
    122       project=project,
--> 123       http_transport=http_transport)
    124   # Initialize the dynamically loaded functions on the objects that want them.
    125   ApiFunction.initialize()

~\Anaconda3\envs\new_coastseg\lib\site-packages\ee\data.py in initialize(credentials, api_base_url, tile_base_url, cloud_api_base_url, cloud_api_key, project, http_transport)
    197   _http_transport = http_transport
    198 
--> 199   _install_cloud_api_resource()
    200 
    201   if project is not None:

~\Anaconda3\envs\new_coastseg\lib\site-packages\ee\data.py in _install_cloud_api_resource()
    271       headers_supplier=_make_request_headers,
    272       response_inspector=_handle_profiling_response,
--> 273       http_transport=_http_transport)
    274 
    275   _cloud_api_resource_raw = _cloud_api_utils.build_cloud_resource(

~\Anaconda3\envs\new_coastseg\lib\site-packages\ee\_cloud_api_utils.py in build_cloud_resource(api_base_url, api_key, credentials, timeout, headers_supplier, response_inspector, http_transport, raw)
    149       requestBuilder=request_builder,
    150       model=alt_model,
--> 151       cache_discovery=False)
    152   resource._baseUrl = api_base_url
    153   return resource

~\Anaconda3\envs\new_coastseg\lib\site-packages\googleapiclient\_helpers.py in positional_wrapper(*args, **kwargs)
    129                 elif positional_parameters_enforcement == POSITIONAL_WARNING:
    130                     logger.warning(message)
--> 131             return wrapped(*args, **kwargs)
    132 
    133         return positional_wrapper

~\Anaconda3\envs\new_coastseg\lib\site-packages\googleapiclient\discovery.py in build(serviceName, version, http, discoveryServiceUrl, developerKey, model, requestBuilder, credentials, cache_discovery, cache, client_options, adc_cert_path, adc_key_path, num_retries, static_discovery, always_use_jwt_access)
    294                 developerKey,
    295                 num_retries=num_retries,
--> 296                 static_discovery=static_discovery,
    297             )
    298             service = build_from_document(

~\Anaconda3\envs\new_coastseg\lib\site-packages\googleapiclient\discovery.py in _retrieve_discovery_doc(url, http, cache_discovery, serviceName, version, cache, developerKey, num_retries, static_discovery)
    418     # Note that it will already raise an error if we don't get a 2xx response
    419     req = HttpRequest(http, HttpRequest.null_postproc, actual_url)
--> 420     resp, content = req.execute(num_retries=num_retries)
    421 
    422     try:

~\Anaconda3\envs\new_coastseg\lib\site-packages\googleapiclient\_helpers.py in positional_wrapper(*args, **kwargs)
    129                 elif positional_parameters_enforcement == POSITIONAL_WARNING:
    130                     logger.warning(message)
--> 131             return wrapped(*args, **kwargs)
    132 
    133         return positional_wrapper

~\Anaconda3\envs\new_coastseg\lib\site-packages\googleapiclient\http.py in execute(self, http, num_retries)
    929             method=str(self.method),
    930             body=self.body,
--> 931             headers=self.headers,
    932         )
    933 

~\Anaconda3\envs\new_coastseg\lib\site-packages\googleapiclient\http.py in _retry_request(http, num_retries, req_type, sleep, rand, uri, method, *args, **kwargs)
    188         try:
    189             exception = None
--> 190             resp, content = http.request(uri, method, *args, **kwargs)
    191         # Retry on SSL errors and socket timeout errors.
    192         except _ssl_SSLError as ssl_error:

~\Anaconda3\envs\new_coastseg\lib\site-packages\google_auth_httplib2.py in request(self, uri, method, body, headers, redirections, connection_type, **kwargs)
    207         request_headers = headers.copy() if headers is not None else {}
    208 
--> 209         self.credentials.before_request(self._request, method, uri, request_headers)
    210 
    211         # Check if the body is a file-like stream, and if so, save the body

~\Anaconda3\envs\new_coastseg\lib\site-packages\google\auth\credentials.py in before_request(self, request, method, url, headers)
    131         # the http request.)
    132         if not self.valid:
--> 133             self.refresh(request)
    134         self.apply(headers)
    135 

~\Anaconda3\envs\new_coastseg\lib\site-packages\google\oauth2\credentials.py in refresh(self, request)
    308             scopes=scopes,
    309             rapt_token=self._rapt_token,
--> 310             enable_reauth_refresh=self._enable_reauth_refresh,
    311         )
    312 

~\Anaconda3\envs\new_coastseg\lib\site-packages\google\oauth2\reauth.py in refresh_grant(request, token_uri, refresh_token, client_id, client_secret, scopes, rapt_token, enable_reauth_refresh)
    345 
    346     if not response_status_ok:
--> 347         _client._handle_error_response(response_data)
    348     return _client._handle_refresh_grant_response(response_data, refresh_token) + (
    349         rapt_token,

~\Anaconda3\envs\new_coastseg\lib\site-packages\google\oauth2\_client.py in _handle_error_response(response_data)
     58         error_details = json.dumps(response_data)
     59 
---> 60     raise exceptions.RefreshError(error_details, response_data)
     61 
     62 

RefreshError: ('invalid_grant: Token has been expired or revoked.', {'error': 'invalid_grant', 'error_description': 'Token has been expired or revoked.'})

Instructions and Documentation Improvement

Instructions and Documentation Improvement

The documentation and instructions need to be improved so the user understands what the following options and code do.

  1. What does use GPU mean ?
  2. Where does use data store the outputs? How does it work?
  3. What is an ROI? How is it used? How is the ROI created?

Thank you to @venuswku for finding all these.

New Feature: Slider to Control ROI Sizes and Overlap

Create two sliders that control the sizes of the fishnet ROIs that are generated onto the map. The user can control the sizes of the individual ROIs that compose the large and small fishnets that are added to the map.

Make sure the instructions tell the user how the sliders are used to create the ROIs, the metrics for the ROI size, and link to the wiki with an example of various sizes.

image

Draw or upload a ROI with arbitrary shape

Currently, CoastSeg facilitates drawing square or rectangular ROIs. Often, coastlines and other features are linear and narrow, so it would be advantageous to have the ability to draw and also upload polygons consisting of more than 4 vertices to define the ROI. These would essentially be polygons of arbitrary shape.

"No Model Info Passed" Exception for Newly Added Models

When I was trying out different models for the satellite images that I downloaded, there was a No Model Info Passed exception thrown for the following 3 models:

  • landsat_6229071
  • SWED-RGB_6824384
  • coast-train-RGB_6950479.

All the other models work.
@2320sharon said these models are some of the newly added models, and it could possibly be an issue with the download function.

Error Message

Called Run Model
Not using the GPU
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
File ~\anaconda3\envs\coastseg\lib\site-packages\ipywidgets\widgets\widget_output.py:103, in Output.capture.<locals>.capture_decorator.<locals>.inner(*args, **kwargs)
    101     self.clear_output(*clear_args, **clear_kwargs)
    102 with self:
--> 103     return func(*args, **kwargs)

Input In [13], in run_model_button_clicked(button)
    117 Ww=zoo_model.get_weights_list(model_choice)
    118 # Load the model from the config files
--> 119 model, model_list, config_files, model_types=zoo_model.get_model(Ww)
    120 metadatadict=zoo_model.get_metadatadict(Ww,config_files, model_types)
    121 # # Compute the segmentation

File ~\Projects\CoastSeg\CoastSeg\zoo_model_module.py:64, in Zoo_Model.get_model(self, Ww)
     62 model_types = []
     63 if Ww == []:
---> 64     raise Exception("No Model Info Passed")
     65 for weights in Ww:
     66     configfile = weights.replace('.h5', '.json').replace('weights', 'config')

Exception: No Model Info Passed

Replicate Issue

No shoreline available?

We're trying to use this for a large-scale coastal analysis project in the Great Lakes but it doesn't appear that the reference shoreline from 2014 has any information in the Great Lakes. When trying to Generate ROI for any part of the Lake Michigan coast, for example, I am receiving the following error:

Generating ROIs please wait.

 Loading the file province1244_ref_shoreline.geojson now.

---------------------------------------------------------------------------
CPLE_OpenFailedError                      Traceback (most recent call last)
File fiona\_shim.pyx:83, in fiona._shim.gdal_open_vector()

File fiona\_err.pyx:291, in fiona._err.exc_wrap_pointer()

CPLE_OpenFailedError: Failed to read GeoJSON data

During handling of the above exception, another exception occurred:

DriverError                               Traceback (most recent call last)
File C:\ProgramData\Anaconda3\envs\coastseg\lib\site-packages\ipywidgets\widgets\widget_output.py:103, in Output.capture.<locals>.capture_decorator.<locals>.inner(*args, **kwargs)
    101     self.clear_output(*clear_args, **clear_kwargs)
    102 with self:
--> 103     return func(*args, **kwargs)

Input In [6], in on_gen_button_clicked(b)
     41 print("Generating ROIs please wait.") 
     42 # Generate ROIs along the coastline within the bounding box
---> 43 coastseg_map.generate_ROIS_fishnet()
     44 debug_view.clear_output(wait=True)
     45 # Add the Clickable ROIs to the map

File ~\GitHub\CoastSeg\CoastSeg\coastseg_map_class.py:959, in CoastSeg_Map.generate_ROIS_fishnet(self, large_fishnet, small_fishnet)
    957 # save bbox 
    958 if self.shorelines_gdf.empty:
--> 959     self.load_shoreline_on_map()
    960 # Large fishnet cannot be 0. Throw an error
    961 if large_fishnet == 0:

File ~\GitHub\CoastSeg\CoastSeg\coastseg_map_class.py:873, in CoastSeg_Map.load_shoreline_on_map(self)
    871 if  os.path.exists(shoreline_path):
    872     print(f"\n Loading the file {os.path.basename(shoreline_path)} now.")
--> 873     shoreline=bbox.read_gpd_file(shoreline_path)
    874 else:
    875     print("\n The geojson shoreline file does not exist. Downloading it now.")

File ~\GitHub\CoastSeg\CoastSeg\bbox.py:24, in read_gpd_file(filename)
     22 if os.path.exists(filename):
     23     with open(filename, 'r') as f:
---> 24         gpd_data = gpd.read_file(f)
     25 else:
     26     print('File does not exist. Please download the coastline_vector necessary here: https://geodata.lib.berkeley.edu/catalog/stanford-xv279yj9196 ')

File C:\ProgramData\Anaconda3\envs\coastseg\lib\site-packages\geopandas\io\file.py:253, in _read_file(filename, bbox, mask, rows, engine, **kwargs)
    250     path_or_bytes = filename
    252 if engine == "fiona":
--> 253     return _read_file_fiona(
    254         path_or_bytes, from_bytes, bbox=bbox, mask=mask, rows=rows, **kwargs
    255     )
    256 elif engine == "pyogrio":
    257     return _read_file_pyogrio(
    258         path_or_bytes, bbox=bbox, mask=mask, rows=rows, **kwargs
    259     )

File C:\ProgramData\Anaconda3\envs\coastseg\lib\site-packages\geopandas\io\file.py:294, in _read_file_fiona(path_or_bytes, from_bytes, bbox, mask, rows, **kwargs)
    291     reader = fiona.open
    293 with fiona_env():
--> 294     with reader(path_or_bytes, **kwargs) as features:
    295 
    296         # In a future Fiona release the crs attribute of features will
    297         # no longer be a dict, but will behave like a dict. So this should
    298         # be forwards compatible
    299         crs = (
    300             features.crs["init"]
    301             if features.crs and "init" in features.crs
    302             else features.crs_wkt
    303         )
    305         # handle loading the bounding box

File C:\ProgramData\Anaconda3\envs\coastseg\lib\site-packages\fiona\collection.py:555, in BytesCollection.__init__(self, bytesbuf, **kwds)
    552 self.virtual_file = buffer_to_virtual_file(self.bytesbuf, ext=ext)
    554 # Instantiate the parent class.
--> 555 super(BytesCollection, self).__init__(self.virtual_file, vsi=filetype, **kwds)

File C:\ProgramData\Anaconda3\envs\coastseg\lib\site-packages\fiona\collection.py:162, in Collection.__init__(self, path, mode, driver, schema, crs, encoding, layer, vsi, archive, enabled_drivers, crs_wkt, ignore_fields, ignore_geometry, **kwargs)
    160 if self.mode == 'r':
    161     self.session = Session()
--> 162     self.session.start(self, **kwargs)
    163 elif self.mode in ('a', 'w'):
    164     self.session = WritingSession()

File fiona\ogrext.pyx:540, in fiona.ogrext.Session.start()

File fiona\_shim.pyx:90, in fiona._shim.gdal_open_vector()

DriverError: Failed to read GeoJSON data

Is there any idea of whether support for this large freshwater system might be included in the future? ArcGIS has some reference shorelines that include the Great Lakes and may be of use (just a thought).

Feature: Model Input Type Options

There needs to be a set of options for the type of input data that the user wants to run the model on. The user's choice will impact the model options shown to the user. For instance, if the user selects RGB then only the models that can be run on RGB will be shown to the user. This feature will also impact the button use data as it will need to check what kind of data needs to be copied to the new folder.

More user variables to declare at the start of the notebook

I recommend the following variables are declared at the top of the notebook, for easy editing by the user

dates = ['2018-12-01', '2019-01-01']
sat_list = ['S2','L7','L8']

that would require the function check_images_available_selected_ROI to accept those inputs

Similarly, it now makes sense to move the CoastSat user variables to near the top

    pre_process_settings = { 
    # general parameters:
    'cloud_thresh': 0.5,        # threshold on maximum cloud cover
    'output_epsg': 3857,        # epsg code of spatial reference system desired for the output   
    # quality control:
    'check_detection': True,    # if True, shows each shoreline detection to the user for validation
    'adjust_detection': False,  # if True, allows user to adjust the postion of each shoreline by changing the threhold
    'save_figure': True,        # if True, saves a figure showing the mapped shoreline for each image
    # [ONLY FOR ADVANCED USERS] shoreline detection parameters:
    'min_beach_area': 4500,     # minimum area (in metres^2) for an object to be labelled as a beach
    'buffer_size': 150,         # radius (in metres) of the buffer around sandy pixels considered in the shoreline detection
    'min_length_sl': 200,       # minimum length (in metres) of shoreline perimeter to be valid
    'cloud_mask_issue': False,  # switch this parameter to True if sand pixels are masked (in black) on many images  
    'sand_color': 'default',    # 'default', 'dark' (for grey/black sand beaches) or 'bright' (for white sand beaches)
    # add the inputs defined previously
    'inputs': inputs,
    }

Create widgets to extract shorelines and transects

Describe the solution you'd like
Currently, there is no user-friendly way for the user to extract shorelines from the imagery they downloaded using CoastSeg. There are two functions used to extract shorelines and transects extract_shorelines_from_rois and compute_transects which have no widgets associated with them. These functions currently don't have a good way to inform users when there were no valid shorelines extracted from their data nor a way to choose which data they want to extract shorelines from. There should also be a more user-friendly way to display and save the shorelines and transects extracted.

CoastSeg yml is not installing

Currently when the user attempts to install the coastseg environment in anaconda using the .yml file under install it never installs and just spins forever. Update the yml file to include the latest dependencies with version numbers as well as include instructions for how to create the coastseg environment without the yml. CoastSat had a similar issue and updated their install instructions so the user didn't need to use the .yml file.

Add the new instructions to the readme as well as an .md under the install directory.

New Feature: Load ROIs from a geojson file

The ability to load ROIs from a geojson file would make CoastSeg experiments more reproducible. I would like a new button to load a geojson file onto the map and throw an error if the geojson isn't valid. When the new ROIs are loaded onto the map the self.data should be updated to these ROIs. These ROIs should be converted to json and styled according to the following code taken from generate_ROIS_fishnet

        fishnet_geojson = fishnet_intersect_gpd.to_json()
        fishnet_dict = json.loads(fishnet_geojson)
        # Add style to each feature in the geojson
        for feature in fishnet_dict["features"]:
            feature["properties"]["style"] = {
                "color": "black",
                "weight": 3,
                "fillColor": "grey",
                "fillOpacity": 0.1,
            }

Create a Logger

Currently, CoastSeg does not have any logging which makes it difficult to recreate bugs encountered by users. A simple logger that tracks what buttons the user has pressed, error messages, prints, and files created would be very useful.

Feature: Ability to Run Multiple Models on a Single Folder

Description of Feature

I would like the ability to run multiple models on a folder full of data I downloaded. Currently, only one model can run on one folder of downloaded data. I would like a new subdirectory to be created for the outputs of each kind of model run on the data. Using this approach multiple models can be run on the same data and their outputs can be stored in easily identifiable subdirectories.

Speed up Download Times with JobLib and Parallel Processing

Download speeds for the models, geojson files, and jpgs are very slow right now. Parallel processing with Joblib or another library could help speed up the download times.

Incorporate Joblib or another library to speed up the download times for:

  1. CoastSat's retrieve images
  2. download_url - for the Zenodo models
  3. geosjon shoreline files

Create a feature to allow users to upload their own reference shorelines

Currently, there is no way for users to upload their own shorelines if the shorelines are not in a zendo release that can be downloaded. I would like a workflow to be created that would allow users to upload a geojson file containing their shoreline. If the shoreline is too large an error message would be displayed to the user. I think a button that opens a file selection widget that will allow the user to select their shoreline geojson file from the command line will be best.

Update Installation Instructions

Installation Instructions are Out of Date

The installation instructions in the readme tell the user to git clone from git clone --depth 1 https://github.com/dbuscombe-usgs/CoastSeg.git which is no longer correct after CoastSeg was moved to Satellite Shorelines.

Once the coastsat_package is officially released the installation instructions should inform the user how to install it.

Merged conda env for coastsat, rio-tiler, localtileserver

A first cut is this

## conda env create --file env/environment.yml
name: coastseg
channels:
- defaults
- conda-forge
dependencies:
- python=3.7
- earthengine-api
- google-api-python-client
- gdal
- rasterio
- pandas
- geopandas
- numpy
- matplotlib
- pillow
- pytz
- scikit-image
- scikit-learn
- shapely
- scipy
- astropy
- jupyter
- ipython
- pip
- pip:
   - localtileserver
   - rio-tiler

this is a bloated environment that is slow/ hard to install

  • need to revisit whether pytz, astropy, shapely, and possibly others are required

Config File for ROIs, bbox and settings

Describe the solution you'd like
Currently, a user must use all the interactive prompts in order to select an ROI, download it, extract shorelines, and run models on the data. There should be a series of config files and a new script that would allow the user to download all the data they want without ever interacting with the jupyter notebook. Having a series of config files to configure machine learning processes is a recommended best practice in the paper "Operationalizing Machine Learning: An Interview Study" as it makes experiments more reproducible and minimizes user error due to incorrect inputs. I propose splitting these settings across 4 different config files to promote a degree of data separation as well as to prevent the user accidentally from modifying settings they don't want to change. This would also make the config files easier to understand instead of a single giant config file.

I recommend creating 4 config files: preprocess_settings, model_settings, ROI_settings, and shoreline_settings. The preprocess_settings config file would control the preprocess settings for coastsat which control data quality settings like cloud cover threshold, controls for CoastSat's machine learning models, and more. The model_settings would control which of the models from segmentation_zoo was selected, whether to use CRF postprocessing and other settings related to running the models on the downloaded data. The ROI settings config file would control the number of ROIs requested, the location, dates, and satellites of the requested ROIs. Lastly, the shoreline settings config file would control which ROI files had their shorelines extracted, the transects used, and more.

Documentation
In order for the user to know how to properly use the config files there would need to be associated documentation that explains what each field in the config file means as well a sample config file. Another page with a sample config and script with outputs would be helpful for showing the user what to expect from their outputs.

Feedback Requested
@dbuscombe-usgs @ebgoldstein
Do you think having 4 config files is too much?

pydensecrf no longer a dependency for Gym or Zoo

As of release v0.0.14 doodleverse-utils no longer has pydensecrf as a dependency. It is a rarely used function that affords little benefit, and it is not available on pip which could cause deployment problems. See Doodleverse/doodleverse_utils#16

Update src/coastseg/UI_models.py to remove use_CRF option

Update src/coastseg/zoo_model.py to remove do_crf option

Update /refactored_custom_map_official.ipynb to remove reference to CRF

Update /custom_map.ipynb to remove reference to CRF

This toolbox uses Zoo models

In order of priority and complexity, we can deploy

  • pre-trained unet and residual-unet models for Landsat and Sentinel imagery based on Coast Train imagery
  • ensembles of pre-trained unet and residual-unet models for Landsat and Sentinel imagery based on Coast Train imagery
  • model recategorization on a new class distribution, by user input
  • new model training, by user input (i.e. "geospatial Doodler")

notebooks/prototype 6: imagery downloaded from coastsat needs a sitename per ROI

Currently, all imagery that is downloaded goes into the same 'sitename' folder. That causes the files from different ROIs to overwrite the previous.

Potential solution: each ROI could be assigned a unique 'sitename' using geocoder or similar. This would involve computing the mean coordinates (latitude and longitude) from coastSatBBOX and passing them to geocoder for the sitename

e.g.

lat_lon = [tuple(np.mean(l['polygon'],axis=1).squeeze()) for l in list_of_inputs]
import geocoder
g = geocoder.google(lat_lon[0][::-1], method='reverse')
g

However, I get a "denied request" error

<[REQUEST_DENIED] Google - Reverse [empty]>

The other downside is that most ROIs are small enough that they would have the same city/county info

Therefore, I suggest sitename is, at least for now, simply a numeric identifier, perhaps a simple counter from 1

e,g. sitename = 'ID'+str(counter)

Open to other ideas

Explore possibility of serving notebooks as Panel apps

It would be really nice to explore the possibility of using Panel to make a webapp, using

panel serve SDS_coastsat_classifier.ipynb

What are the current limitations (if any)? Dependency issues? Widgets not rendering properly? other?

Google Earth Engine Authentication Error

Sometimes when working with CoastSeg the Google Earth Engine Authentication token expires and the user needs to create a new one. The function handle_AuthenticationError(): is supposed allow the user to create a new token when called by download_imagery(), but it isn't activating like it used to meaning the user has to manually call
ee.Authenticate()
ee.Initialize()
within the jupyter notebook to reauthenticate.

"Run model" `do_crf` flag needed for `do_seg()`

the bug

In app.ipynb using all the default settings and using a small ROI, when I hit 'Run Model', I get the following error

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
File ~/anaconda3/envs/coastseg_test/lib/python3.8/site-packages/ipywidgets/widgets/widget_output.py:103, in Output.capture.<locals>.capture_decorator.<locals>.inner(*args, **kwargs)
    101     self.clear_output(*clear_args, **clear_kwargs)
    102 with self:
--> 103     return func(*args, **kwargs)

Input In [8], in run_model_button_clicked(button)
    108 metadatadict=zoo_model.get_metadatadict(Ww,config_files, model_types)
    109 # # Compute the segmentation
--> 110 zoo_model.compute_segmentation(model_dict["sample_direc"], model_list, metadatadict)

File /media/marda/ExtraDrive1/satellites/CoastSeg/CoastSeg/zoo_model_module.py:44, in Zoo_Model.compute_segmentation(self, sample_direc, model_list, metadatadict)
     42 # Compute the segmentation for each of the files
     43 for f in tqdm(sample_filenames):
---> 44     do_seg(
     45         f,
     46         model_list,
     47         metadatadict,
     48         sample_direc,
     49         self.NCLASSES,
     50         self.N_DATA_BANDS,
     51         self.TARGET_SIZE,
     52         TESTTIMEAUG,
     53         WRITE_MODELMETADATA)

TypeError: do_seg() missing 1 required positional argument: 'do_crf'

Steps To Reproduce

Steps to reproduce the behavior:

  1. from activated coastseg_test env, run jupyter notebook
  2. run app.ipynb
  3. run all cells with defualt values and hit 'run model' button
  4. See error

Expected behavior

This just requires a new flag do_crf. If True, the crf_refine function will be used in do_seg (part of doodleverse_utils). Should be "False" by default, with an option to set to true. Call it "Use CRF post-processing"

Create static map of available coastlines, and guidance for users to upload their own reference shoreline

Referencing issues #69 and #53

it would be helpful to

  • create a static map of each available shoreline segment to see which regions are not covered
  • post guidance to users working in regions that have no available shorelines. the guidance should include reference to existing capability of CoastSeg to upload a user-defined reference shoreline, and the geojson format that shoreline should be in

CoastSeg conda env is very slow. Abandon yml?

The current approach to install the coastseg conda env, which is fairly complex as it contains large dependencies such as tensorflow, gdal, panel, ipywidgets, etc, (conda env create --file install/coastseg.yml) is quite slow

It may possibly be faster if we first installed mamba, then used mamba to find a solution and install the dependencies

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.