CognitiveScience giswqs commited on
Commit
ff0fe90
·
0 Parent(s):

Duplicate from giswqs/solara-maxar

Browse files

Co-authored-by: Qiusheng Wu <[email protected]>

Files changed (9) hide show
  1. .gitattributes +35 -0
  2. .github/workflows/sync-hf.yml +20 -0
  3. .gitignore +162 -0
  4. Dockerfile +21 -0
  5. LICENSE +21 -0
  6. README.md +13 -0
  7. pages/00_home.py +20 -0
  8. pages/01_morocco.py +154 -0
  9. requirements.txt +4 -0
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.github/workflows/sync-hf.yml ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Sync to Hugging Face hub
2
+ on:
3
+ push:
4
+ branches: [main]
5
+
6
+ # to run this workflow manually from the Actions tab
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ sync-to-hub:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v3
14
+ with:
15
+ fetch-depth: 0
16
+ lfs: true
17
+ - name: Push to hub
18
+ env:
19
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
20
+ run: git push --force https://giswqs:[email protected]/spaces/giswqs/solara-maxar main
.gitignore ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ private/
6
+
7
+ # C extensions
8
+ *.so
9
+
10
+ # Distribution / packaging
11
+ .Python
12
+ build/
13
+ develop-eggs/
14
+ dist/
15
+ downloads/
16
+ eggs/
17
+ .eggs/
18
+ lib/
19
+ lib64/
20
+ parts/
21
+ sdist/
22
+ var/
23
+ wheels/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+ private/
30
+
31
+ # PyInstaller
32
+ # Usually these files are written by a python script from a template
33
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Installer logs
38
+ pip-log.txt
39
+ pip-delete-this-directory.txt
40
+
41
+ # Unit test / coverage reports
42
+ htmlcov/
43
+ .tox/
44
+ .nox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ nosetests.xml
49
+ coverage.xml
50
+ *.cover
51
+ *.py,cover
52
+ .hypothesis/
53
+ .pytest_cache/
54
+ cover/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Django stuff:
61
+ *.log
62
+ local_settings.py
63
+ db.sqlite3
64
+ db.sqlite3-journal
65
+
66
+ # Flask stuff:
67
+ instance/
68
+ .webassets-cache
69
+
70
+ # Scrapy stuff:
71
+ .scrapy
72
+
73
+ # Sphinx documentation
74
+ docs/_build/
75
+
76
+ # PyBuilder
77
+ .pybuilder/
78
+ target/
79
+
80
+ # Jupyter Notebook
81
+ .ipynb_checkpoints
82
+
83
+ # IPython
84
+ profile_default/
85
+ ipython_config.py
86
+
87
+ # pyenv
88
+ # For a library or package, you might want to ignore these files since the code is
89
+ # intended to run in multiple environments; otherwise, check them in:
90
+ # .python-version
91
+
92
+ # pipenv
93
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
94
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
95
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
96
+ # install all needed dependencies.
97
+ #Pipfile.lock
98
+
99
+ # poetry
100
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
101
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
102
+ # commonly ignored for libraries.
103
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
104
+ #poetry.lock
105
+
106
+ # pdm
107
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
108
+ #pdm.lock
109
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
110
+ # in version control.
111
+ # https://pdm.fming.dev/#use-with-ide
112
+ .pdm.toml
113
+
114
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
115
+ __pypackages__/
116
+
117
+ # Celery stuff
118
+ celerybeat-schedule
119
+ celerybeat.pid
120
+
121
+ # SageMath parsed files
122
+ *.sage.py
123
+
124
+ # Environments
125
+ .env
126
+ .venv
127
+ env/
128
+ venv/
129
+ ENV/
130
+ env.bak/
131
+ venv.bak/
132
+
133
+ # Spyder project settings
134
+ .spyderproject
135
+ .spyproject
136
+
137
+ # Rope project settings
138
+ .ropeproject
139
+
140
+ # mkdocs documentation
141
+ /site
142
+
143
+ # mypy
144
+ .mypy_cache/
145
+ .dmypy.json
146
+ dmypy.json
147
+
148
+ # Pyre type checker
149
+ .pyre/
150
+
151
+ # pytype static type analyzer
152
+ .pytype/
153
+
154
+ # Cython debug symbols
155
+ cython_debug/
156
+
157
+ # PyCharm
158
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
159
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
160
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
161
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
162
+ #.idea/
Dockerfile ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM jupyter/base-notebook:latest
2
+
3
+ RUN mamba install -c conda-forge leafmap geopandas localtileserver -y && \
4
+ fix-permissions "${CONDA_DIR}" && \
5
+ fix-permissions "/home/${NB_USER}"
6
+
7
+ COPY requirements.txt .
8
+ RUN pip install -r requirements.txt
9
+
10
+ RUN mkdir ./pages
11
+ COPY /pages ./pages
12
+
13
+ ENV PROJ_LIB='/opt/conda/share/proj'
14
+
15
+ USER root
16
+ RUN chown -R ${NB_UID} ${HOME}
17
+ USER ${NB_USER}
18
+
19
+ EXPOSE 8765
20
+
21
+ CMD ["solara", "run", "./pages", "--host=0.0.0.0"]
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Open Geospatial Solutions
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Solara Maxar
3
+ emoji: 🏃
4
+ colorFrom: blue
5
+ colorTo: green
6
+ sdk: docker
7
+ pinned: false
8
+ license: mit
9
+ app_port: 8765
10
+ duplicated_from: giswqs/solara-maxar
11
+ ---
12
+
13
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
pages/00_home.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import solara
2
+
3
+
4
+ @solara.component
5
+ def Page():
6
+ with solara.Column(align="center"):
7
+ markdown = """
8
+ ## A Solara Web App for Visualizing [Maxar Open Data](https://www.maxar.com/open-data)
9
+
10
+ ### Introduction
11
+
12
+ **A collection of [Solara](https://github.com/widgetti/solara) web apps for geospatial applications.**
13
+
14
+ - Web App: <https://giswqs-solara-maxar.hf.space>
15
+ - GitHub: <https://github.com/opengeos/solara-maxar>
16
+ - Hugging Face: <https://huggingface.co/spaces/giswqs/solara-maxar>
17
+
18
+ """
19
+
20
+ solara.Markdown(markdown)
pages/01_morocco.py ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import leafmap
3
+ import solara
4
+ import ipyleaflet
5
+ import ipywidgets as widgets
6
+ import pandas as pd
7
+
8
+ url = 'https://open.gishub.org/maxar-open-data'
9
+ repo = 'https://github.com/opengeos/maxar-open-data/blob/master/datasets'
10
+
11
+
12
+ def get_datasets():
13
+ datasets = f'{url}/datasets.csv'
14
+ df = pd.read_csv(datasets)
15
+ return df
16
+
17
+
18
+ def get_catalogs(name):
19
+ dataset = f'{url}/datasets/{name}.tsv'
20
+
21
+ dataset_df = pd.read_csv(dataset, sep='\t')
22
+ catalog_ids = dataset_df['catalog_id'].unique().tolist()
23
+ catalog_ids.sort()
24
+ return catalog_ids
25
+
26
+
27
+ def add_widgets(m):
28
+ datasets = get_datasets()['dataset'].tolist()
29
+
30
+ style = {"description_width": "initial"}
31
+ padding = "0px 0px 0px 5px"
32
+ dataset = widgets.Dropdown(
33
+ options=datasets,
34
+ description='Event:',
35
+ value="Morocco-Earthquake-Sept-2023",
36
+ style=style,
37
+ layout=widgets.Layout(width="270px", padding=padding),
38
+ )
39
+
40
+ image = widgets.Dropdown(
41
+ value=None,
42
+ options=get_catalogs(dataset.value),
43
+ description='Image:',
44
+ style=style,
45
+ layout=widgets.Layout(width="270px", padding=padding),
46
+ )
47
+
48
+ checkbox = widgets.Checkbox(
49
+ value=True,
50
+ description='Show footprints',
51
+ style=style,
52
+ layout=widgets.Layout(width="130px", padding=padding),
53
+ )
54
+
55
+ split = widgets.Checkbox(
56
+ value=False,
57
+ description='Split map',
58
+ style=style,
59
+ layout=widgets.Layout(width="130px", padding=padding),
60
+ )
61
+
62
+ def change_dataset(change):
63
+ default_geojson = f'{url}/datasets/{change.new}.geojson'
64
+ m.layers = m.layers[:2]
65
+ m.controls = m.controls[:-1]
66
+ m.add_geojson(default_geojson, layer_name='Footprint', zoom_to_layer=True)
67
+ image.options = get_catalogs(change.new)
68
+
69
+ dataset.observe(change_dataset, names='value')
70
+
71
+ def change_image(change):
72
+ if change.new:
73
+ mosaic = f'{url}/datasets/{dataset.value}/{image.value}.json'
74
+ m.add_stac_layer(mosaic, name=image.value)
75
+
76
+ image.observe(change_image, names='value')
77
+
78
+ def change_footprint(change):
79
+ geojson_layer = m.find_layer('Footprint')
80
+ if change.new:
81
+ geojson_layer.visible = True
82
+ else:
83
+ geojson_layer.visible = False
84
+
85
+ checkbox.observe(change_footprint, names='value')
86
+
87
+ def change_split(change):
88
+ if change.new:
89
+ if image.value is not None:
90
+ left_layer = m.find_layer(image.value)
91
+ right_layer = m.find_layer('Google Satellite')
92
+ right_layer.visible = True
93
+ footprint_layer = m.find_layer('Footprint')
94
+ footprint_layer.visible = False
95
+ m.split_map(
96
+ left_layer=left_layer,
97
+ right_layer=right_layer,
98
+ add_close_button=True,
99
+ )
100
+ split.value = False
101
+ else:
102
+ left_layer = None
103
+
104
+ split.observe(change_split, names='value')
105
+
106
+ event_control = ipyleaflet.WidgetControl(widget=dataset, position='topright')
107
+ image_control = ipyleaflet.WidgetControl(widget=image, position='topright')
108
+ checkboxes = widgets.HBox([checkbox, split])
109
+ checkbox_control = ipyleaflet.WidgetControl(widget=checkboxes, position='topright')
110
+
111
+ m.add(event_control)
112
+ m.add(image_control)
113
+ m.add(checkbox_control)
114
+
115
+
116
+ zoom = solara.reactive(2)
117
+ center = solara.reactive((20, 0))
118
+
119
+
120
+ class Map(leafmap.Map):
121
+ def __init__(self, **kwargs):
122
+ kwargs['toolbar_control'] = False
123
+ super().__init__(**kwargs)
124
+ basemap = {
125
+ "url": "https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}",
126
+ "attribution": "Google",
127
+ "name": "Google Satellite",
128
+ }
129
+ self.add_tile_layer(**basemap, shown=False)
130
+ self.add_layer_manager(opened=False)
131
+ add_widgets(self)
132
+ default_geojson = f'{url}/datasets/Morocco-Earthquake-Sept-2023.geojson'
133
+ self.add_geojson(default_geojson, layer_name='Footprint', zoom_to_layer=True)
134
+
135
+
136
+ @solara.component
137
+ def Page():
138
+ with solara.Column(style={"min-width": "500px"}):
139
+ # solara components support reactive variables
140
+ # solara.SliderInt(label="Zoom level", value=zoom, min=1, max=20)
141
+ # using 3rd party widget library require wiring up the events manually
142
+ # using zoom.value and zoom.set
143
+ Map.element( # type: ignore
144
+ zoom=zoom.value,
145
+ on_zoom=zoom.set,
146
+ center=center.value,
147
+ on_center=center.set,
148
+ scroll_wheel_zoom=True,
149
+ toolbar_ctrl=False,
150
+ data_ctrl=False,
151
+ height="780px",
152
+ )
153
+ solara.Text(f"Center: {center.value}")
154
+ solara.Text(f"Zoom: {zoom.value}")
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ leafmap
2
+ solara
3
+ geopandas
4
+ pydantic< 2.0