Skip to content

Commit ad65395

Browse files
committed
Add several python scripts and tests
1 parent 64cf01e commit ad65395

14 files changed

+825
-2
lines changed

.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
TIPG_NAME="OGC Features and Tiles API"
2+
DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:5432/pgrouting
3+
TIPG_DB_SCHEMAS='["public","omf","osm","results"]'

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.venv
22
__pycache__/
33
cache/
4-
.streamlit/
4+
.streamlit/
5+
tiles

Documentation/tests-visualisation.md

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,17 @@ The draft made for the final web application is provided [here](./OSM_Overture_v
2222
- [Installation](#installation-2)
2323
- [Using Dash](#using-dash)
2424
- [Review](#review-2)
25+
- [Shiny for Python](#shiny-for-python)
26+
- [Installation](#installation-3)
27+
- [Using Shiny](#using-shiny)
28+
- [Review](#review-3)
2529
- [GeoServer](#geoserver)
2630
- [Why using GeoServer?](#why-using-geoserver)
2731
- [Installing GeoServer with Docker](#installing-geoserver-with-docker)
2832
- [Configuring GeoServer](#configuring-geoserver)
2933
- [Adding layers with the app](#adding-layers-with-the-app)
3034
- [Adding layers with REST API](#adding-layers-with-rest-api)
31-
- [Review](#review-3)
35+
- [Review](#review-4)
3236

3337

3438
# QGIS
@@ -262,6 +266,36 @@ PyPlot charts (not only maps) can be displayed with Streamlit too, using `st.plo
262266

263267
Here again, it would be interesting to try to use a GeoServer for instance to query the map features in OGC Standards (WMS or WFS, depending on what we want to do), as it would probably be less demanding for the client.
264268

269+
## Shiny for Python
270+
271+
[Shiny for Python](https://shiny.posit.co/py/) or simply Shiny can, according to the website, create "Effortless Python web applications with the power of reactive programming".
272+
With Shiny, it is possible to create dashboards and also web visualisation for geospatial information.
273+
The github project can be find [here](https://github.com/posit-dev/py-shiny/).
274+
Streamlit is under the [MIT License](https://github.com/posit-dev/py-shiny/blob/main/LICENSE).
275+
276+
### Installation
277+
278+
You can find the Shiny for Python documentation [here](https://shiny.posit.co/py/docs/overview.html).
279+
280+
Shiny for python is really easy to install, just with `pip install shiny`.
281+
282+
You can then run `shiny create --template dashboard-tips` to create a first application with a preview of what it is possible to do with Shiny for Python.
283+
You will have to chose if you want to use Shiny Express or not, and the folder you will want to create the application in.
284+
Shiny Express is a more compact way for writing python files using Shiny, so you might want to use it.
285+
To see it, you might need to download the other python packages that you will find in the `requirements.txt` file created in the folder that you have chosen before.
286+
287+
### Using Shiny
288+
289+
290+
291+
### Review
292+
293+
The Shiny for Python website provides an article for a comparison between frameworks, including Streamlit framework.
294+
This article can be find [here](https://shiny.posit.co/py/docs/comp-streamlit.html).
295+
This article is written by Shiny for Python team, so of course the conclusion is that Shiny for Python is better than Streamlit in a way.
296+
Still, this article explains some core differences between the two framwork, and Shiny for Python seems less intuitive than Streamlit and probably less user-friendly at first sight, but Shiny seems to be more adapted for managing bigger database.
297+
One of the difference is the reloading of the entire script every time that a change is made with the User Interface (UI) while shiny will only reload the components
298+
265299
# GeoServer
266300

267301
[GeoServer](https://geoserver.org) is, according to the website, "an open source server for sharing geospatial data".

Python/Web/Shiny/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This template gives you a more "complete" dashboard for exploring the tips dataset. For an overview of what's here, visit [this article](https://shiny.posit.co/py/docs/user-interfaces.html).

Python/Web/Shiny/app.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import geopandas as gpd
2+
import pandas as pd
3+
from shiny import reactive
4+
from shiny.express import input, ui
5+
from shinywidgets import render_widget, reactive_read
6+
import sqlalchemy
7+
import ipywidgets
8+
from lonboard import Map, ScatterplotLayer, PathLayer
9+
10+
def getEngine(database:str,
11+
host:str="127.0.0.1",
12+
user:str="postgres",
13+
password:str="postgres",
14+
port:str="5432") -> sqlalchemy.engine.base.Engine:
15+
"""Get sqlalchemy engine to connect to the database.
16+
17+
Args:
18+
database (str): Database to connect to.
19+
host (str, optional): Ip address for the database connection. The default is "127.0.0.1"
20+
user (str, optional): Username for the database connection. The default is "postgres".
21+
password (str, optional): Password for the database connection. The default is "postgres".
22+
port (str, optional): Port for the connection. The default is "5432".
23+
24+
Returns:
25+
sqlalchemy.engine.base.Engine: Engine with the database connection.
26+
"""
27+
engine = sqlalchemy.create_engine(f"postgresql://{user}:{password}@{host}:{port}/{database}")
28+
return engine
29+
30+
engine = getEngine("pgrouting")
31+
32+
sqlQueryTable = """SELECT table_catalog, table_schema, table_name FROM information_schema.tables AS t
33+
WHERE t.table_schema != 'pg_catalog' AND t.table_schema != 'information_schema'
34+
ORDER BY t.table_schema, t.table_name"""
35+
36+
tables = pd.read_sql_query(sqlQueryTable, engine)
37+
38+
print(type(tables))
39+
40+
tables[["table_schema"]]
41+
42+
tables.to_numpy()
43+
44+
# schemas = tables[["table_schema"]].unique()
45+
46+
# schemas
47+
48+
# schemas = pd.unique(tables[["table_schema"]])
49+
50+
# schemas
51+
52+
# ui.input_select("select_schema", "Choose a schema", choices=schemas[["table_schema"]])
53+
54+
55+
56+
@render_widget
57+
def colorPickerPoint():
58+
color_picker_point = ipywidgets.ColorPicker(concise=True, description='Point color', value='#000000')
59+
return color_picker_point
60+
61+
@render_widget
62+
def colorPickerLine():
63+
color_picker_line = ipywidgets.ColorPicker(concise=True, description='Line color', value='#000000')
64+
return color_picker_line
65+
66+
@render_widget
67+
def map():
68+
gdf = gpd.GeoDataFrame.from_postgis("SELECT * FROM omf.node_tokyo", engine)
69+
layer = ScatterplotLayer.from_geopandas(gdf, radius_min_pixels=2)
70+
gdf_line = gpd.GeoDataFrame.from_postgis("SELECT * FROM omf.edge_with_cost_tokyo", engine)
71+
line = PathLayer.from_geopandas(gdf_line, width_min_pixels=2)
72+
return Map([layer, line])
73+
74+
75+
@reactive.effect
76+
def set_fill_color():
77+
# Point
78+
# map.widget.layers[0].get_fill_color = colors_point[input.color_select_point()]
79+
80+
hexPoint = reactive_read(colorPickerPoint.widget, "value")
81+
colorPoint = list(int(hexPoint[i:i+2], 16) for i in (1, 3, 5))
82+
map.widget.layers[0].get_fill_color = colorPoint
83+
84+
85+
# Line
86+
# map.widget.layers[1].get_fill_color = colors_line[input.color_select_line()]
87+
88+
hexLine = reactive_read(colorPickerLine.widget, "value")
89+
colorLine = list(int(hexLine[i:i+2], 16) for i in (1, 3, 5))
90+
map.widget.layers[1].get_color = colorLine

Python/Web/Shiny/requirements.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
faicons
2+
shiny
3+
shinywidgets
4+
plotly
5+
pandas
6+
ridgeplot

Python/Web/Shiny/shared.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from pathlib import Path
2+
3+
import pandas as pd
4+
5+
app_dir = Path(__file__).parent
6+
tips = pd.read_csv(app_dir / "tips.csv")

Python/Web/Shiny/styles.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
:root {
2+
--bslib-sidebar-main-bg: #f8f8f8;
3+
}
4+
5+
.popover {
6+
--bs-popover-header-bg: #222;
7+
--bs-popover-header-color: #fff;
8+
}
9+
10+
.popover .btn-close {
11+
filter: var(--bs-btn-close-white-filter);
12+
}

0 commit comments

Comments
 (0)