giswqs commited on
Commit
4e14f7e
1 Parent(s): ae52a14

Add web app

Browse files
Files changed (5) hide show
  1. Dockerfile +21 -0
  2. README.md +12 -1
  3. pages/00_home.py +27 -0
  4. pages/01_imagery.py +128 -0
  5. requirements.txt +6 -0
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"]
README.md CHANGED
@@ -11,8 +11,19 @@ app_port: 8765
11
 
12
  ## TN-historical-imagery
13
 
14
- An interactive web app for visualizing Tennessee historical imagery.
 
 
 
 
 
 
15
 
16
  - Web App: <https://giswqs-tn-historical-imagery.hf.space>
17
  - GitHub: <https://github.com/giswqs/tn-historical-imagery>
18
  - Hugging Face: <https://huggingface.co/spaces/giswqs/tn-historical-imagery>
 
 
 
 
 
 
11
 
12
  ## TN-historical-imagery
13
 
14
+ A Interactive Web App for Visualizing Tennessee Historical Imagery
15
+
16
+ ### Introduction
17
+
18
+ This web app allows users to visualize historical imagery for Tennessee. The historical imagery is provided by the Tennessee Department of Transportation (TDOT) and includes aerial 2-ft resolution photos taken between 1997 and 2006.
19
+ The original imagery in MrSID format was download from the [TNGIC Google Drive](https://drive.google.com/drive/folders/1qYlPFBLkcOpO4xjvBvHwMH9RDtbsSNkv). The imagery was then converted to Cloud Optimized GeoTIFF format
20
+ and hosted on Source Cooperative.
21
 
22
  - Web App: <https://giswqs-tn-historical-imagery.hf.space>
23
  - GitHub: <https://github.com/giswqs/tn-historical-imagery>
24
  - Hugging Face: <https://huggingface.co/spaces/giswqs/tn-historical-imagery>
25
+ - Dataset: <https://source.coop/repositories/giswqs/tn-imagery>
26
+
27
+ ### Acknowledgements
28
+
29
+ This work is supported by the U.S. Geological Survey through Grant/Cooperative Agreement No. G23AP00683 (GY23-GY27) in collaboration with [AmericaView](https://americaview.org).
pages/00_home.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import solara
2
+
3
+
4
+ @solara.component
5
+ def Page():
6
+ with solara.Column(align="center"):
7
+ markdown = """
8
+ ## A Interactive Web App for Visualizing Tennessee Historical Imagery
9
+
10
+ ### Introduction
11
+
12
+ This web app allows users to visualize historical imagery for Tennessee. The historical imagery is provided by the Tennessee Department of Transportation (TDOT) and includes aerial 2-ft resolution photos taken between 1997 and 2006.
13
+ The original imagery in MrSID format was download from the [TNGIC Google Drive](https://drive.google.com/drive/folders/1qYlPFBLkcOpO4xjvBvHwMH9RDtbsSNkv). The imagery was then converted to Cloud Optimized GeoTIFF format
14
+ and hosted on Source Cooperative.
15
+
16
+ - Web App: <https://giswqs-tn-historical-imagery.hf.space>
17
+ - GitHub: <https://github.com/giswqs/tn-historical-imagery>
18
+ - Hugging Face: <https://huggingface.co/spaces/giswqs/tn-historical-imagery>
19
+ - Dataset: <https://source.coop/repositories/giswqs/tn-imagery>
20
+
21
+ ### Acknowledgements
22
+
23
+ This work is supported by the U.S. Geological Survey through Grant/Cooperative Agreement No. G23AP00683 (GY23-GY27) in collaboration with [AmericaView](https://americaview.org).
24
+
25
+ """
26
+
27
+ solara.Markdown(markdown)
pages/01_imagery.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import leafmap
3
+ import solara
4
+ import ipywidgets as widgets
5
+ import pandas as pd
6
+ import geopandas as gpd
7
+ import tempfile
8
+ from shapely.geometry import Point
9
+
10
+
11
+ def add_widgets(m):
12
+ style = {"description_width": "initial"}
13
+ padding = "0px 0px 0px 5px"
14
+
15
+ checkbox = widgets.Checkbox(
16
+ value=True,
17
+ description="Footprints",
18
+ style=style,
19
+ layout=widgets.Layout(width="90px", padding="0px"),
20
+ )
21
+
22
+ split = widgets.Checkbox(
23
+ value=False,
24
+ description="Split map",
25
+ style=style,
26
+ layout=widgets.Layout(width="92px", padding=padding),
27
+ )
28
+
29
+ reset = widgets.Checkbox(
30
+ value=False,
31
+ description="Reset",
32
+ style=style,
33
+ layout=widgets.Layout(width="75px", padding="0px"),
34
+ )
35
+
36
+ output = widgets.Output()
37
+
38
+ def reset_map(change):
39
+ if change.new:
40
+ pass
41
+
42
+ reset.observe(reset_map, names="value")
43
+
44
+ def handle_click(**kwargs):
45
+ if kwargs.get("type") == "click":
46
+ latlon = kwargs.get("coordinates")
47
+ geometry = Point(latlon[::-1])
48
+ selected = m.gdf[m.gdf.intersects(geometry)]
49
+ setattr(m, "zoom_to_layer", False)
50
+ if len(selected) > 0:
51
+ filename = selected.iloc[0]["Filename"]
52
+ county = selected.iloc[0]["County"]
53
+ year = filename.split("_")[-1][:4]
54
+ with output:
55
+ output.clear_output()
56
+ output.append_stdout(f"County: {county} | Year: {year}")
57
+ url = f"https://data.source.coop/giswqs/tn-imagery/imagery/{filename}"
58
+ layer = m.find_layer("Selected Image")
59
+ if layer is not None:
60
+ m.remove(layer)
61
+ m.default_style = {"cursor": "wait"}
62
+ m.add_cog_layer(url, name="Selected Image", zoom_to_layer=False)
63
+ m.default_style = {"cursor": "default"}
64
+ else:
65
+ with output:
66
+ output.clear_output()
67
+ output.append_stdout("No image found.")
68
+
69
+ m.on_interaction(handle_click)
70
+
71
+ box = widgets.VBox([widgets.HBox([checkbox, split, reset]), output])
72
+ m.add_widget(box, position="topright", add_header=False)
73
+
74
+
75
+ zoom = solara.reactive(8)
76
+ center = solara.reactive((35.64836915737426, -86.21246337890626))
77
+
78
+
79
+ class Map(leafmap.Map):
80
+ def __init__(self, **kwargs):
81
+ kwargs["toolbar_control"] = False
82
+ kwargs["draw_control"] = False
83
+ super().__init__(**kwargs)
84
+ basemap = {
85
+ "url": "https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}",
86
+ "attribution": "Google",
87
+ "name": "Google Satellite",
88
+ }
89
+ self.add_tile_layer(**basemap, shown=False)
90
+
91
+ wms_url = "https://tnmap.tn.gov/arcgis/services/BASEMAPS/IMAGERY_WEB_MERCATOR/MapServer/WMSServer"
92
+ self.add_wms_layer(wms_url, layers="0", name="TDOT Imagery", shown=True)
93
+
94
+ self.add_layer_manager(opened=False)
95
+ # add_widgets(self)
96
+ geojson = "https://github.com/opengeos/datasets/releases/download/vector/TN_Counties.geojson"
97
+ style = {"color": "#3388ff", "opacity": 1, "weight": 2, "fillOpacity": 0}
98
+ self.add_geojson(
99
+ geojson,
100
+ layer_name="TN Counties",
101
+ style=style,
102
+ zoom_to_layer=False,
103
+ info_mode=None,
104
+ )
105
+ gdf = gpd.read_file(geojson)
106
+ setattr(self, "gdf", gdf)
107
+ add_widgets(self)
108
+
109
+
110
+ @solara.component
111
+ def Page():
112
+ with solara.Column(style={"min-width": "500px"}):
113
+ # solara components support reactive variables
114
+ # solara.SliderInt(label="Zoom level", value=zoom, min=1, max=20)
115
+ # using 3rd party widget library require wiring up the events manually
116
+ # using zoom.value and zoom.set
117
+ Map.element( # type: ignore
118
+ zoom=zoom.value,
119
+ on_zoom=zoom.set,
120
+ center=center.value,
121
+ on_center=center.set,
122
+ scroll_wheel_zoom=True,
123
+ toolbar_ctrl=False,
124
+ data_ctrl=False,
125
+ height="780px",
126
+ )
127
+ # solara.Text(f"Center: {center.value}")
128
+ # solara.Text(f"Zoom: {zoom.value}")
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ geopandas
2
+ leafmap
3
+ pydantic< 2.0
4
+ setuptools<71
5
+ solara
6
+