diff --git a/.gitignore b/.gitignore index de95027..1ee2e21 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ SolarStationsOrg-station-catalog.csv # MyST build outputs _build + +# Jupyter book +docs/.jupyter-book-marimo diff --git a/.readthedocs.yaml b/.readthedocs.yaml index b23485d..a6f6703 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -8,15 +8,20 @@ build: python: "3.13" nodejs: "22" commands: - # Install Python dependencies - - pip install -r docs/requirements.txt + # Install Python dependencies via uv, creating .venv at the repo root + # (myst.yml's marimo plugin path, ../.venv/bin/jupyter-book-marimo, expects it there) + - UV_PROJECT_ENVIRONMENT=.venv uv sync # Install mystmd - npm install -g mystmd # Build the site (myst.yml lives in docs/, so build from there) - # --execute re-runs notebook code cells instead of using their stored outputs. - - cd docs && myst build --html --execute + - cd docs && UV_PROJECT_ENVIRONMENT=.venv uv run jupyter-book build --html # Copy the output to Read the Docs expected location - - mkdir -p $READTHEDOCS_OUTPUT/html/ - - cp -r docs/_build/html/. "$READTHEDOCS_OUTPUT/html" + - mkdir -p "$READTHEDOCS_OUTPUT/html/" + - cd docs && cp -r _build/html/. "$READTHEDOCS_OUTPUT/html/" # Clean up build artifacts - - rm -rf docs/_build + - cd docs && rm -rf _build + +python: + install: + - method: uv + command: sync diff --git a/docs/myst.yml b/docs/myst.yml index f0eb797..45d686e 100644 --- a/docs/myst.yml +++ b/docs/myst.yml @@ -20,9 +20,14 @@ project: settings: output_matplotlib_strings: remove + plugins: + - type: executable + path: ../.venv/bin/jupyter-book-marimo + toc: - file: intro.ipynb - file: station_catalog.ipynb + - file: station_catalog_marimo.md - file: station_requirements.md title: Station requirements - file: station_metadata.md diff --git a/docs/requirements.txt b/docs/requirements.txt index 080843c..df4182a 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -10,3 +10,4 @@ unidecode==1.4.0 openpyxl==3.1.5 xarray==2026.7.0 h5netcdf==1.8.1 +jupyter-book-marimo==0.0.1 diff --git a/docs/station_catalog_marimo.md b/docs/station_catalog_marimo.md new file mode 100644 index 0000000..3032f4f --- /dev/null +++ b/docs/station_catalog_marimo.md @@ -0,0 +1,72 @@ +```{marimo} python +import marimo as mo +import pandas as pd +import numpy as np +#import kgcpy +``` + + +```{marimo} python +main_url = "https://raw.githubusercontent.com/AssessingSolar/solarstations/refs/heads/main/solarstations.csv" +esmap_url = "https://raw.githubusercontent.com/AssessingSolar/solarstations/refs/heads/main/esmap_stations.csv" +country_by_continent_url = "https://raw.githubusercontent.com/AssessingSolar/solarstations/refs/heads/main/data/country_by_continent.json" +nasa_power_url = "https://raw.githubusercontent.com/AssessingSolar/solarstations/refs/heads/main/data/nasa_power_annual_irradiance_global.csv" + +main_stations = pd.read_csv(main_url, dtype={'Tier': str}).fillna('') +esmap_stations = pd.read_csv(esmap_url, dtype={'Tier': str}).fillna('') +stations = pd.concat([main_stations, esmap_stations], axis='rows', ignore_index=True) + +country_by_continent = pd.read_json(country_by_continent_url, typ="series").to_dict() + +stations['Continent'] = stations['Country'].map(country_by_continent) + +#stations['Koeppen Geiger classification'] = stations.apply(lambda x: kgcpy.lookupCZ(x['Latitude'], x['Longitude']), axis=1) +#kg_climates = {'A': 'Tropical', 'B': 'Dry', 'C': 'Temperate', 'D': 'Continental', 'E': 'Polar', 'O': 'Ocean'} +#stations['Koeppen Geiger climate zone'] = stations['Koeppen Geiger classification'].apply(lambda x: kg_climates[x[0]]) + +instrumentation = stations['Instrumentation'].str.split(';', expand=True) +is_tier_1 = (instrumentation=='G').any(axis=1) & (instrumentation=='B').any(axis=1) & (instrumentation=='D').any(axis=1) +stations['Tier'] = 2 - is_tier_1.astype(int) + +annual_irradiance = pd.read_csv(nasa_power_url, index_col=[0, 1]) +for index, row in stations.iterrows(): + lat_round = round(row['Latitude']*2-0.5, 0)/2 + 0.25 + lon_round = round(row['Longitude']*2-0.5, 0)/2 + 0.25 + try: + stations.loc[index, ['GHI_typical_kWh_m2', 'DHI_typical_kWh_m2', 'DNI_typical_kWh_m2']] = \ + annual_irradiance.loc[(lat_round, lon_round), :] + except KeyError as e: + pass + # Manual add data missing from the climatological file (data retrieved from NASA's webinterface) + if row['Station name'] == 'Funafuti': + stations.loc[index, ['GHI_typical_kWh_m2', 'DHI_typical_kWh_m2', 'DNI_typical_kWh_m2']] = \ + np.array([5.33*365, 2.12*365, 4.37*365]).astype(int) + if row['Station name'] == 'South Pole': + stations.loc[index, ['GHI_typical_kWh_m2', 'DHI_typical_kWh_m2', 'DNI_typical_kWh_m2']] = \ + np.array([3.0*365, 1.38*365, 5.13*365]).astype(int) + +stations = stations[~stations['Instrumentation'].str.contains('G;Ds')] # remove Tier 3 stations + +stations = stations.sort_values('Station name', ignore_index=True) + +## Write file containing all columns, linked to above +#stations.to_csv('./SolarStationsOrg-station-catalog.csv', index=False) + +## Format station name as hyperlinks if URL is available. +## Do this after the new CSV is written, since we don't want HTML in that. +#for index, row in stations.iterrows(): +# if row['URL'].startswith('http'): +# stations.loc[index, 'Station name'] = f'{row["Station name"]}' + + +table = mo.ui.table( + stations, + pagination=True, + freeze_columns_left=["Station name"], + hidden_columns=["URL"], +) +``` + +```{marimo} python +table +``` \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..46ab11c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,23 @@ +[project] +name = "SolarStations.org" +version = "0.1.0" +description = "A catalog of multi-component solar irradiance monitoring stations." +readme = "README.md" +requires-python = ">=3.13" +dependencies = [ + "folium==0.20.0", + "itables==2.2.2", + "jupyter-book==2.1.6", + "kgcpy==1.1.8", + "matplotlib==3.11.1", + "numpy==2.5.1", + "pandas==3.0.3", + "pvlib==0.15.2", + "unidecode==1.4.0", + "openpyxl==3.1.5", + "xarray==2026.7.0", + "h5netcdf==1.8.1", + "jupyter-book==2.1.6", + "jupyter-book-marimo>=0.0.2", + "marimo", +]