From 4a98b85aaa7e29883cbd33df0bbe3e1eb937525e Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Mon, 31 Mar 2025 16:39:50 +0200 Subject: [PATCH 01/17] next --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a39da93..5cb11bc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "caribic-dash" -version = "0.0.18" +version = "0.0.19" description = "IRISCC dashboard with CARIBIC data" readme = "README.md" requires-python = ">=3.12" diff --git a/uv.lock b/uv.lock index a1b94f1..703fdae 100644 --- a/uv.lock +++ b/uv.lock @@ -80,7 +80,7 @@ wheels = [ [[package]] name = "caribic-dash" -version = "0.0.18" +version = "0.0.19" source = { virtual = "." } dependencies = [ { name = "dash" }, -- GitLab From 83a8035588e5ae3c0190ae9cf37ac8ad697c9c3f Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Mon, 31 Mar 2025 17:09:25 +0200 Subject: [PATCH 02/17] add traj data info --- CHANGELOG.md | 6 +++++- src/layout.py | 22 ++++++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f99247..a7cf880 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ Types of changes ## TODOs -- set log level via config +- disable the "show trajectories" checkbox if no data - add sources for BB tagging and ACN background - investigate if data caching is necessary (load-from-thredds)? - scatter-plot: plot as line if sufficient data is available? @@ -35,6 +35,10 @@ Types of changes ## [Unreleased] +### Added + +- trajectory data info + ## v0.0.18, 2025-03-31 ### Fixed diff --git a/src/layout.py b/src/layout.py index b76dca3..58d9a7f 100644 --- a/src/layout.py +++ b/src/layout.py @@ -263,10 +263,24 @@ def create(df: pd.DataFrame, config: DotDict) -> list: ), ), ), - html.Label( - "BB flagging: BB influence if ACN > (145 ppt + 3*ACN_prc)", - id="flagging-info", - style={"margin-left": "15px", "font-size": "12px"}, + html.Div( + children=[ + html.Div( + html.Label( + "BB flagging: BB influence if ACN > (145 ppt + 3*ACN_prc)", + id="flagging-info", + style={"margin-left": "15px", "font-size": "12px"}, + ) + ), + html.Div( + html.Label( + "Trajectories: KNMI Trajectory Model TRAJKS, driven by ECMWF re-analysis data", + id="trajectory-info", + style={"margin-left": "15px", "font-size": "12px"}, + ) + ), + ], + style={"padding-top": "10px"}, ), ] ), -- GitLab From 360dbdc4284c83b61f24324f54d4053053735cfd Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Mon, 31 Mar 2025 17:09:28 +0200 Subject: [PATCH 03/17] cleanup --- src/callbacks.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/callbacks.py b/src/callbacks.py index e0779e9..0dd0b31 100644 --- a/src/callbacks.py +++ b/src/callbacks.py @@ -68,8 +68,6 @@ def register_map_plot( # try to find the trajectory file for selected flight if trajs := trajectory_data.get(selected_flight): # make plots if trajectory file found - print(trajs["latitude"].dtype.byteorder) - print(trajs["longitude"].dtype.byteorder) for i in range(trajs.trajectory.size): try: fig_map.add_trace( -- GitLab From c0ed357ebe0f26a58a89fcc160d6cdfba1a63ebc Mon Sep 17 00:00:00 2001 From: FObersteiner <f.obersteiner@posteo.de> Date: Mon, 31 Mar 2025 19:48:59 +0200 Subject: [PATCH 04/17] add author --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 5cb11bc..3d11354 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,6 +2,7 @@ name = "caribic-dash" version = "0.0.19" description = "IRISCC dashboard with CARIBIC data" +authors = [{ name = "Florian Obersteiner", email = "f.obersteiner@kit.edu" }] readme = "README.md" requires-python = ">=3.12" classifiers = [ -- GitLab From 810330c83b015f2508a01a586aada16087185633 Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Tue, 1 Apr 2025 08:34:55 +0200 Subject: [PATCH 05/17] show static pressure as secondary var by default --- CHANGELOG.md | 7 +++++++ src/layout.py | 6 ++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7cf880..76f66d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,9 +16,11 @@ Types of changes ## TODOs - disable the "show trajectories" checkbox if no data +- put trajectory info and checkbox below map plot? - add sources for BB tagging and ACN background - investigate if data caching is necessary (load-from-thredds)? - scatter-plot: plot as line if sufficient data is available? +- prevent footer from hiding BB flagging info ## v0.1.0 release @@ -26,6 +28,7 @@ Types of changes ## Backlog +- containerize & auto-deploy - use a polars dataframe or [fireducks](https://fireducks-dev.github.io/) for better performance - if that turns out to be a bottleneck. (!) Keep this in mind when using pandas-specific functions. - add tests - add pre-commit @@ -39,6 +42,10 @@ Types of changes - trajectory data info +### Changed + +- select a secondary parameter by default + ## v0.0.18, 2025-03-31 ### Fixed diff --git a/src/layout.py b/src/layout.py index 58d9a7f..71da70c 100644 --- a/src/layout.py +++ b/src/layout.py @@ -9,7 +9,7 @@ from dash import dcc, html from .config import DotDict -def create(df: pd.DataFrame, config: DotDict) -> list: +def create(df: pd.DataFrame, config: DotDict) -> list[html.Header]: """ Create the layout for the dashboard. @@ -40,6 +40,8 @@ def create(df: pd.DataFrame, config: DotDict) -> list: if vo["label"] == "ACN": var_sel_idx = idx + var2_sel_idx = 3 + return [ html.Header( [ @@ -171,7 +173,7 @@ def create(df: pd.DataFrame, config: DotDict) -> list: dcc.Dropdown( id="second-variable-dropdown", options=([{"value": "None", "label": "(None)"}] + var_opts), # type: ignore - value="None", # type: ignore + value=var_opts[var2_sel_idx]["value"], # type: ignore clearable=False, searchable=True, style={ -- GitLab From a80327037e71730bd10926ec0e41526b41717bb7 Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Tue, 1 Apr 2025 10:02:46 +0200 Subject: [PATCH 06/17] cosmetics --- CHANGELOG.md | 3 ++- src/callbacks.py | 3 ++- src/layout.py | 2 +- uv.lock | 6 +++--- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76f66d9..dda235e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ Types of changes - add sources for BB tagging and ACN background - investigate if data caching is necessary (load-from-thredds)? - scatter-plot: plot as line if sufficient data is available? -- prevent footer from hiding BB flagging info +- prevent footer from hiding BB flagging info? ## v0.1.0 release @@ -45,6 +45,7 @@ Types of changes ### Changed - select a secondary parameter by default +- same bg color for both plots ## v0.0.18, 2025-03-31 diff --git a/src/callbacks.py b/src/callbacks.py index 0dd0b31..69024eb 100644 --- a/src/callbacks.py +++ b/src/callbacks.py @@ -143,6 +143,7 @@ def register_map_plot( }, margin={"l": 0, "r": 10, "t": 0, "b": 0}, showlegend=False, + paper_bgcolor="#fbf8f3", ) return [fig_map, show_trajdata_warn] @@ -218,7 +219,7 @@ def register_timeseries_plot(app: Dash, timeseries_data: pd.DataFrame, var_info: ) fig_ts.update_layout( - paper_bgcolor="#e8e8e8", + paper_bgcolor="#fbf8f3", margin={"l": 45, "r": 10, "t": 20, "b": 50}, legend={ "x": 0.01, diff --git a/src/layout.py b/src/layout.py index 71da70c..b8a711d 100644 --- a/src/layout.py +++ b/src/layout.py @@ -320,7 +320,7 @@ def create(df: pd.DataFrame, config: DotDict) -> list[html.Header]: html.A( [ html.I(className="fab fa-gitlab", style={"marginRight": "5px"}), - f"src ({config.VERSION})", + f"src {config.VERSION}", ], href=config.CODEURL, target="_blank", diff --git a/uv.lock b/uv.lock index 703fdae..aebf8af 100644 --- a/uv.lock +++ b/uv.lock @@ -392,11 +392,11 @@ wheels = [ [[package]] name = "narwhals" -version = "1.32.0" +version = "1.33.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c1/e5/aa97891440bf6bc4239e9b918d89fea58eb87dff1d8d14a69b45ef677e66/narwhals-1.32.0.tar.gz", hash = "sha256:bd0aa41434737adb4b26f8593f3559abc7d938730ece010fe727b58bc363580d", size = 258915 } +sdist = { url = "https://files.pythonhosted.org/packages/85/fd/484aa8bb557f97a1781f38c78b79f795a2fa320e4165c4230f679937d1e8/narwhals-1.33.0.tar.gz", hash = "sha256:6233d2457debf4b5fe4a1da54530c6fe2d84326f4a8e3bca35bbbff580a347cb", size = 262554 } wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/96/79a6168dc7a5098066e097c01a45d01608c8df6552dfb92a2676ce623186/narwhals-1.32.0-py3-none-any.whl", hash = "sha256:8bdbf3f76155887412eea04b0b06303856ac1aa3d9e8bda5b5e54612855fa560", size = 320073 }, + { url = "https://files.pythonhosted.org/packages/41/c1/e9bc6b67c774e7c1f939c91ea535f18f7644fedc61b20d6baa861ad52b34/narwhals-1.33.0-py3-none-any.whl", hash = "sha256:f653319112fd121a1f1c18a40cf70dada773cdacfd53e62c2aa0afae43c17129", size = 322750 }, ] [[package]] -- GitLab From 7ac9447f9667f3390479691a02a3b49cc89e1509 Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Tue, 1 Apr 2025 12:05:05 +0200 Subject: [PATCH 07/17] show map source attribution on top of map --- assets/custom.css | 190 +++++++++++++++++++++++++++------------------- 1 file changed, 113 insertions(+), 77 deletions(-) diff --git a/assets/custom.css b/assets/custom.css index 5d16dcf..bb16e74 100644 --- a/assets/custom.css +++ b/assets/custom.css @@ -1,124 +1,160 @@ :root { - --neon-pink: #ff71ce; - --neon-blue: #01cdfe; - --neon-green: #05ff81; - --neon-purple: #b967ff; - --neon-yellow: #fdfb96; - --grey-bg: #404040; - --grey-bg-bright: #d4d4d4; - --dark-bg: #1a1a1a; - --darker-bg: #121212; - --grid-color: rgba(33, 33, 99, 0.8); + --neon-pink: #ff71ce; + --neon-blue: #01cdfe; + --neon-green: #05ff81; + --neon-purple: #b967ff; + --neon-yellow: #fdfb96; + --grey-bg: #404040; + --grey-bg-bright: #d4d4d4; + --dark-bg: #1a1a1a; + --darker-bg: #121212; + --grid-color: rgba(33, 33, 99, 0.8); } body { - background-color: var(--dark-bg); - background-image: - linear-gradient(0deg, var(--grid-color) 1px, transparent 1px), - linear-gradient(90deg, var(--grid-color) 1px, transparent 1px); - background-size: 20px 20px; - color: white; - font-family: 'VT323', 'Courier New', monospace; - margin-top: 70px; - padding: 15px; + background-color: var(--dark-bg); + background-image: linear-gradient( + 0deg, + var(--grid-color) 1px, + transparent 1px + ), + linear-gradient(90deg, var(--grid-color) 1px, transparent 1px); + background-size: 20px 20px; + color: white; + font-family: "VT323", "Courier New", monospace; + margin-top: 70px; + padding: 15px; } .title-bar { - position: fixed; - top: 0; - left: 0; - width: 100%; - background-color: var(--grey-bg); - padding: 10px 20px; - display: flex; - justify-content: space-between; - align-items: center; - border-bottom: 1px solid var(--grid-color); - z-index: 1000; - box-sizing: border-box; - height: 60px; + position: fixed; + top: 0; + left: 0; + width: 100%; + background-color: var(--grey-bg); + padding: 10px 20px; + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid var(--grid-color); + z-index: 1000; + box-sizing: border-box; + height: 60px; } .title-text { - color: white; - font-size: 1.4rem; - font-weight: bold; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 70%; + color: white; + font-size: 1.4rem; + font-weight: bold; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 70%; } .logo-container { - display: flex; - align-items: center; + display: flex; + align-items: center; } .header-logo { - height: 40px; - background-color: var(--grey-bg-bright); - border-radius: 4px; + height: 40px; + background-color: var(--grey-bg-bright); + border-radius: 4px; } /* Logo wrapper to create the background box */ .logo-wrapper { - display: flex; - align-items: center; - justify-content: center; - background-color: var(--grey-bg-bright); - border-radius: 0.4rem; - padding: 0.3rem 0.7rem 0.3rem 0.7rem; - margin-left: 0.5rem; - border: 1px solid var(--grid-color); + display: flex; + align-items: center; + justify-content: center; + background-color: var(--grey-bg-bright); + border-radius: 0.4rem; + padding: 0.3rem 0.7rem 0.3rem 0.7rem; + margin-left: 0.5rem; + border: 1px solid var(--grid-color); } /* Responsive adjustments */ @media (max-width: 600px) { - .logo-wrapper { - padding: 0.3rem; - } + .logo-wrapper { + padding: 0.3rem; + } - .header-logo { - height: 2rem; - } + .header-logo { + height: 2rem; + } } /* ----- drop boxes ----- */ .Select-control { - background-color: var(--dark-bg); + background-color: var(--dark-bg); } .Select-control:hover { - background-color: var(--grey-bg); + background-color: var(--grey-bg); } .Select-value-label { - color: white !important; + color: white !important; } .Select-menu-outer { - background-color: var(--dark-bg); - color: white; + background-color: var(--dark-bg); + color: white; } +/* The following styles ensure the attribution tag floats above the map and should be removed if the issue is fixed in a future plotly release. */ +.maplibregl-ctrl-bottom-right { + bottom: 5px; + left: 10px; +} + +.maplibregl-ctrl-bottom-left, +.maplibregl-ctrl-bottom-right, +.maplibregl-ctrl-top-left, +.maplibregl-ctrl-top-right { + pointer-events: none; + position: absolute; + z-index: 2; +} + +.maplibregl-map { + font: + 12px/20px Helvetica Neue, + Arial, + Helvetica, + sans-serif; + font-family: + Helvetica Neue, + Arial, + Helvetica, + sans-serif; + color: var(--grey-bg); +} + +/*This is necessary to remove spacing below the canvas.*/ +.maplibregl-canvas { + display: block; +} .footer { - position: fixed; - bottom: 0; - left: 0; - width: 100%; - background-color: var(--dark-bg); - padding: 10px 20px; - display: flex; - justify-content: space-between; - align-items: center; - border-top: 1px solid var(--grid-color); - z-index: 1000; - box-sizing: border-box; - font-size: 0.9rem; + position: fixed; + bottom: 0; + left: 0; + width: 100%; + background-color: var(--dark-bg); + padding: 10px 20px; + display: flex; + justify-content: space-between; + align-items: center; + border-top: 1px solid var(--grid-color); + z-index: 1000; + box-sizing: border-box; + font-size: 0.9rem; } /* Add some bottom margin to the main content to prevent overlap with footer */ .main-content { - margin-bottom: 20px; + margin-bottom: 20px; } -- GitLab From 4214f4fa569b501c9ab3b32e4516b7c1732c1d2b Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Tue, 1 Apr 2025 13:39:47 +0200 Subject: [PATCH 08/17] add ci script --- .gitlab-ci.yml | 17 +++++++++++++++++ CHANGELOG.md | 1 + 2 files changed, 18 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..6f47bd3 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,17 @@ +stages: + - test + +# Only run the pipeline for tag pushes matching the pattern "v*" +workflow: + rules: + - if: $CI_COMMIT_TAG =~ /^v.*-pre/ + +# Run tests for your Python application +test: + stage: test + image: python:3.9 + script: + - pip install -r requirements.txt + - pytest -v + only: + - tags diff --git a/CHANGELOG.md b/CHANGELOG.md index dda235e..0596cb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ Types of changes - select a secondary parameter by default - same bg color for both plots +- show map attribution on top of map instead of hiding it below timeseries plot ## v0.0.18, 2025-03-31 -- GitLab From 2b5abf8866450f4bbbc63f0f22b2c0067c778a94 Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Tue, 1 Apr 2025 13:49:29 +0200 Subject: [PATCH 09/17] uv ? --- .gitlab-ci.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6f47bd3..9227d2d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,14 @@ stages: - test +variables: + UV_VERSION: 0.6 + PYTHON_VERSION: 3.12 + BASE_LAYER: bookworm-slim + # GitLab CI creates a separate mountpoint for the build directory, + # so we need to copy instead of using hard links. + UV_LINK_MODE: copy + # Only run the pipeline for tag pushes matching the pattern "v*" workflow: rules: @@ -9,9 +17,10 @@ workflow: # Run tests for your Python application test: stage: test - image: python:3.9 + # image: python:3.9 + image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYER script: - - pip install -r requirements.txt - - pytest -v + - uv pip install -r requirements.txt + - uv run pytest . -v only: - tags -- GitLab From db9e9cd12a298d6775b0f04590b81c1cc8eb3c28 Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Tue, 1 Apr 2025 13:52:25 +0200 Subject: [PATCH 10/17] update requirements.txt --- requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 3944ec7..ae8e7bd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -36,7 +36,7 @@ markupsafe==3.0.2 # via # jinja2 # werkzeug -narwhals==1.32.0 +narwhals==1.33.0 # via plotly nest-asyncio==1.6.0 # via dash @@ -63,7 +63,7 @@ plotly==6.0.1 # via # caribic-dash (pyproject.toml) # dash -protobuf==6.30.1 +protobuf==6.30.2 # via siphon python-dateutil==2.9.0.post0 # via pandas @@ -99,7 +99,7 @@ werkzeug==3.0.6 # via # dash # flask -xarray==2025.3.0 +xarray==2025.3.1 # via caribic-dash (pyproject.toml) zipp==3.21.0 # via importlib-metadata -- GitLab From ee56d3b3553ce90c4267f0770e7a004c103fc70f Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Tue, 1 Apr 2025 13:55:52 +0200 Subject: [PATCH 11/17] py 3.12 --- .gitlab-ci.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9227d2d..76fd1c6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,10 +17,14 @@ workflow: # Run tests for your Python application test: stage: test - # image: python:3.9 - image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYER + image: python:3.12 script: - - uv pip install -r requirements.txt - - uv run pytest . -v + - pip install pip --upgrade + - pip install -r requirements.txt + - pytest . -v + # image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYER + # script: + # - uv pip install -r requirements.txt + # - uv run pytest . -v only: - tags -- GitLab From 0b87c098d44e9189c4106bbc8f11b99590c8c74e Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Tue, 1 Apr 2025 14:22:20 +0200 Subject: [PATCH 12/17] update layout --- src/layout.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/layout.py b/src/layout.py index b8a711d..7141063 100644 --- a/src/layout.py +++ b/src/layout.py @@ -249,6 +249,18 @@ def create(df: pd.DataFrame, config: DotDict) -> list[html.Header]: ) ), ), + html.Div( + children=[ + html.Div( + html.Label( + "Trajectories: KNMI Trajectory Model TRAJKS, driven by ECMWF re-analysis data", + id="trajectory-info", + style={"margin-left": "15px", "font-size": "12px"}, + ) + ), + ], + style={"padding-top": "5px", "padding-bottom": "10px"}, + ), dcc.Loading( id="loading-ts", type="circle", # Options: "graph", "cube", "circle", "dot", or "default" @@ -274,15 +286,8 @@ def create(df: pd.DataFrame, config: DotDict) -> list[html.Header]: style={"margin-left": "15px", "font-size": "12px"}, ) ), - html.Div( - html.Label( - "Trajectories: KNMI Trajectory Model TRAJKS, driven by ECMWF re-analysis data", - id="trajectory-info", - style={"margin-left": "15px", "font-size": "12px"}, - ) - ), ], - style={"padding-top": "10px"}, + style={"padding-top": "5px", "padding-bottom": "10px"}, ), ] ), -- GitLab From cac6c2379d4d62c22da6781deb4bd8ff8bc3c928 Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Tue, 1 Apr 2025 14:24:53 +0200 Subject: [PATCH 13/17] uv retry --- .gitlab-ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 76fd1c6..b5d3687 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,14 +17,14 @@ workflow: # Run tests for your Python application test: stage: test - image: python:3.12 - script: - - pip install pip --upgrade - - pip install -r requirements.txt - - pytest . -v - # image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYER + # image: python:3.12 # script: - # - uv pip install -r requirements.txt - # - uv run pytest . -v + # - pip install pip --upgrade + # - pip install -r requirements.txt + # - pytest . -v + image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYER + script: + - uv pip install -r requirements.txt + - uv run pytest . -v only: - tags -- GitLab From a969d64df973c2f13eb031789744d4fef015242b Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Tue, 1 Apr 2025 14:27:20 +0200 Subject: [PATCH 14/17] uv sync --- .gitlab-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b5d3687..e4b973d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -24,7 +24,8 @@ test: # - pytest . -v image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYER script: - - uv pip install -r requirements.txt + - uv sync - uv run pytest . -v + - uv cache prune --ci only: - tags -- GitLab From 7ad6b5ae3b029fca22348c1d1c7507002b011c9a Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Tue, 1 Apr 2025 14:38:08 +0200 Subject: [PATCH 15/17] prepare deploy --- .gitlab-ci.yml | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e4b973d..1287b3c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,5 +1,6 @@ stages: - test + # - build_and_deploy variables: UV_VERSION: 0.6 @@ -9,19 +10,19 @@ variables: # so we need to copy instead of using hard links. UV_LINK_MODE: copy -# Only run the pipeline for tag pushes matching the pattern "v*" +# Only run the pipeline for tag pushes matching the pattern "v*-pre" workflow: rules: - if: $CI_COMMIT_TAG =~ /^v.*-pre/ -# Run tests for your Python application +# Run tests... test: stage: test # image: python:3.12 # script: # - pip install pip --upgrade # - pip install -r requirements.txt - # - pytest . -v + # - python -m pytest . -v image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYER script: - uv sync @@ -29,3 +30,26 @@ test: - uv cache prune --ci only: - tags +# +# +# # Build and deploy the Docker container directly on the server +# build_and_deploy: +# stage: build_and_deploy +# script: +# - echo "Starting build and deployment of $APP_NAME version $CI_COMMIT_TAG" +# # Build the Docker image locally +# - docker build -t $APP_NAME:$CI_COMMIT_TAG . +# # Stop and remove existing container if it exists +# - | +# if docker ps -a | grep -q $APP_NAME; then +# docker stop $APP_NAME +# docker rm $APP_NAME +# fi +# # Start the new container +# - docker run -d --name $APP_NAME -p $HOST_PORT:$CONTAINER_PORT --restart unless-stopped $APP_NAME:$CI_COMMIT_TAG +# - echo "Build and deployment complete!" +# only: +# - tags +# # This ensures the job runs on the specific runner on your server +# tags: +# - deployment-server -- GitLab From cfce3ce0282d3513586b2ace242c8b5e2093ff29 Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Tue, 1 Apr 2025 14:55:44 +0200 Subject: [PATCH 16/17] traj checkbox below map plot --- CHANGELOG.md | 3 +-- src/layout.py | 48 +++++++++++++++++++++++++++--------------------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0596cb7..f3da1d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,11 +16,9 @@ Types of changes ## TODOs - disable the "show trajectories" checkbox if no data -- put trajectory info and checkbox below map plot? - add sources for BB tagging and ACN background - investigate if data caching is necessary (load-from-thredds)? - scatter-plot: plot as line if sufficient data is available? -- prevent footer from hiding BB flagging info? ## v0.1.0 release @@ -47,6 +45,7 @@ Types of changes - select a secondary parameter by default - same bg color for both plots - show map attribution on top of map instead of hiding it below timeseries plot +- put 'show trajectories' button below map plot ## v0.0.18, 2025-03-31 diff --git a/src/layout.py b/src/layout.py index 7141063..ffa7f03 100644 --- a/src/layout.py +++ b/src/layout.py @@ -202,26 +202,6 @@ def create(df: pd.DataFrame, config: DotDict) -> list[html.Header]: "vertical-align": "middle", }, ), - html.Div( - [ - html.Label( - "Show trajectories", - style={"margin-right": "10px", "vertical-align": "middle"}, - ), - dcc.Checklist( - id="trajectories-checkbox", - options=[{"label": "", "value": 1}], - inline=True, - style={"display": "inline-block", "vertical-align": "middle"}, - ), - ], - style={ - "width": "25%", - "display": "inline-block", - "text-align": "right", - "vertical-align": "middle", - }, - ), ], style={ "display": "flex", @@ -258,8 +238,34 @@ def create(df: pd.DataFrame, config: DotDict) -> list[html.Header]: style={"margin-left": "15px", "font-size": "12px"}, ) ), + html.Div( + [ + html.Label( + "Show trajectories", + style={"margin-right": "10px"}, + ), + dcc.Checklist( + id="trajectories-checkbox", + options=[{"label": "", "value": 1}], + inline=True, + style={"display": "inline-block", "vertical-align": "right"}, + ), + ], + style={ + "text-align": "right", + "vertical-align": "right", + }, + ), ], - style={"padding-top": "5px", "padding-bottom": "10px"}, + style={ + "display": "flex", + "justify-content": "space-between", + "align-items": "center", + "padding-top": "5px", + "padding-bottom": "10px", + "padding-left": "5px", + "padding-right": "15px", + }, ), dcc.Loading( id="loading-ts", -- GitLab From db37ce751f205d5706709003effe1cb240b17320 Mon Sep 17 00:00:00 2001 From: FObersteiner <florian.obersteiner@kit.edu> Date: Tue, 1 Apr 2025 16:51:02 +0200 Subject: [PATCH 17/17] add containerconfig --- .dockerignore | 16 ++++++++++++++++ CHANGELOG.md | 1 + Dockerfile | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ab996e1 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,16 @@ +Dockerfile +.dockerignore +.git +.gitignore +__pycache__/ +*.pyc +*.pyo +*.pyd +venv/ +.venv/ +env/ +*.env +*.db +*.sqlite3 +instance/ +experiments/ diff --git a/CHANGELOG.md b/CHANGELOG.md index f3da1d3..03a3804 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ Types of changes ### Added - trajectory data info +- dockerfile and dockerignore ### Changed diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..84a6d16 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,42 @@ +# ### +# generated with Gemini 2.5 pro/experimental +# ### +# +# Use an official Python runtime as a parent image +# Choose a specific version for reproducibility, -slim versions are smaller +FROM python:3.12-slim + +# Set environment variables +# Prevents Python from writing pyc files to disc (optional) +ENV PYTHONDONTWRITEBYTECODE=1 +# Ensures Python output is sent straight to terminal (useful for logs) +ENV PYTHONUNBUFFERED=1 + +# Set the working directory in the container +WORKDIR /app + +# Copy the requirements file into the container at /app +COPY requirements.txt . + +# Install any needed packages specified in requirements.txt +# --no-cache-dir reduces image size +# --upgrade pip ensures you have the latest pip +# RUN pip install --no-cache-dir --upgrade pip && \ +# pip install --no-cache-dir -r requirements.txt + +# uv variant: +RUN pip install --no-cache-dir uv +RUN uv pip install --no-cache -r requirements.txt --system + +# Copy the rest of the application code into the container at /app +# Assumes your Dockerfile is in the root of your project directory +COPY . . + +# Make port 19000 available to the world outside this container +EXPOSE 19000 + +# Define the command to run your app using Gunicorn +# Binds Gunicorn to 0.0.0.0 so it's accessible from outside the container +# 'app:server' assumes your Dash app instance is 'app' in 'app.py' +# Gunicorn needs the underlying Flask server instance, typically 'app.server' +CMD ["gunicorn", "-b", ":19000", "main:server", "-w", "2"] -- GitLab