eo-tides 0.7.4.dev7__tar.gz → 0.7.5.dev1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/.github/workflows/paper.yml +1 -15
  2. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/.github/workflows/update-changelog.yml +1 -2
  3. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/.pre-commit-config.yaml +2 -8
  4. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/PKG-INFO +1 -1
  5. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/notebooks/Case_study_intertidal.ipynb +3 -3
  6. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/notebooks/Model_tides.ipynb +8 -9
  7. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/notebooks/Satellite_data.ipynb +5 -5
  8. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/notebooks/Tide_statistics.ipynb +5 -5
  9. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/notebooks/Validating_tides.ipynb +2 -1
  10. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/eo_tides/eo.py +2 -3
  11. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/eo_tides/model.py +3 -12
  12. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/eo_tides/stats.py +2 -5
  13. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/eo_tides/utils.py +6 -8
  14. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/eo_tides/validation.py +3 -5
  15. eo_tides-0.7.4.dev7/paper/paper.pdf → eo_tides-0.7.5.dev1/paper/10.21105.joss.07786.pdf +0 -0
  16. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/paper/benchmarking.ipynb +4 -2
  17. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/pyproject.toml +31 -7
  18. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/tests/conftest.py +2 -4
  19. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/tests/test_eo.py +2 -2
  20. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/tests/test_model.py +6 -6
  21. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/tests/test_utils.py +2 -4
  22. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/.editorconfig +0 -0
  23. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  24. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  25. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/.github/actions/setup-python-env/action.yml +0 -0
  26. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/.github/dependabot.yml +0 -0
  27. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/.github/release.yml +0 -0
  28. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/.github/workflows/check-links.yml +0 -0
  29. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/.github/workflows/publish.yml +0 -0
  30. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/.github/workflows/tests.yml +0 -0
  31. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/.github/workflows/update-version.yml +0 -0
  32. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/.gitignore +0 -0
  33. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/CITATION.cff +0 -0
  34. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/CONTRIBUTING.md +0 -0
  35. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/Dockerfile +0 -0
  36. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/LICENSE +0 -0
  37. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/Makefile +0 -0
  38. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/README.md +0 -0
  39. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/codecov.yaml +0 -0
  40. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/api.md +0 -0
  41. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/assets/dtu23_download.jpg +0 -0
  42. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/assets/eo-tides-abstract.gif +0 -0
  43. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/assets/eo-tides-logo-128.png +0 -0
  44. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/assets/eo-tides-logo-256.png +0 -0
  45. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/assets/eo-tides-logo.gif +0 -0
  46. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/assets/eo-tides-logo.png +0 -0
  47. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/assets/eot20_download.jpg +0 -0
  48. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/assets/fes_ftp.jpg +0 -0
  49. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/assets/fes_myproducts.jpg +0 -0
  50. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/assets/fes_productselection.jpg +0 -0
  51. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/assets/fes_subscriptions.jpg +0 -0
  52. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/assets/got_download.jpg +0 -0
  53. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/assets/tide_models_clipped.jpg +0 -0
  54. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/assets/tpxo_download.jpg +0 -0
  55. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/changelog.md +0 -0
  56. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/credits.md +0 -0
  57. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/index.md +0 -0
  58. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/install.md +0 -0
  59. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/migration.md +0 -0
  60. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/setup.md +0 -0
  61. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/docs/stylesheets/extra.css +0 -0
  62. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/eo_tides/__init__.py +0 -0
  63. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/mkdocs.yml +0 -0
  64. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/paper/figures/joss_abstract.png +0 -0
  65. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/paper/figures/joss_fig_gesla.png +0 -0
  66. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/paper/figures/joss_fig_list.png +0 -0
  67. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/paper/figures/joss_fig_pixel.png +0 -0
  68. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/paper/figures/joss_fig_stats.png +0 -0
  69. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/paper/paper.bib +0 -0
  70. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/paper/paper.md +0 -0
  71. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/tests/data/GESLA3.0_ALL/broome-62650-aus-bom +0 -0
  72. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/tests/data/GESLA3.0_ALL/san_diego_ca-569a-usa-uhslc +0 -0
  73. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/tests/data/GESLA3.0_ALL/sydney_fort_denison-60370-aus-bom +0 -0
  74. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/tests/data/GESLA3_ALL 2.csv +0 -0
  75. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/tests/data/IDO71013_2020.csv +0 -0
  76. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/tests/data/tide_models.tar.gz +0 -0
  77. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/tests/test_stats.py +0 -0
  78. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/tests/test_validation.py +0 -0
  79. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/tests/testing.ipynb +0 -0
  80. {eo_tides-0.7.4.dev7 → eo_tides-0.7.5.dev1}/uv.lock +0 -0
@@ -1,19 +1,5 @@
1
1
  name: Draft paper PDF
2
- on:
3
- push:
4
- branches:
5
- - main
6
- - JOSS_paper
7
- paths:
8
- - paper/**
9
- - .github/workflows/paper.yml
10
- pull_request:
11
- branches:
12
- - main
13
- - JOSS_paper
14
- paths:
15
- - paper/**
16
- - .github/workflows/paper.yml
2
+ on: workflow_dispatch
17
3
 
18
4
  jobs:
19
5
  paper:
@@ -32,10 +32,9 @@ jobs:
32
32
  title: "Update changelog for ${{ github.event.release.tag_name }}"
33
33
  body: |
34
34
  This PR updates the changelog with details from the release [${{ github.event.release.tag_name }}](${{ github.event.release.html_url }}).
35
- commit-message: "Update changelog for ${{ github.event.release.tag_name }} ["
35
+ commit-message: "Update changelog for ${{ github.event.release.tag_name }} [skip ci]"
36
36
  branch: update-changelog-${{ github.event.release.tag_name }}
37
37
  base: ${{ github.event.release.target_commitish }}
38
38
  add-paths: |
39
39
  docs/changelog.md
40
- uv.lock
41
40
  delete-branch: true
@@ -10,16 +10,10 @@ repos:
10
10
  - id: trailing-whitespace
11
11
 
12
12
  - repo: https://github.com/astral-sh/ruff-pre-commit
13
- # Ruff version.
14
13
  rev: v0.6.4
15
14
  hooks:
16
- # Run the linter.
17
- - id: ruff
18
- types_or: [python, pyi]
19
- args: [--fix, --select=I] # --select=ALL, I
20
- # Run the formatter.
21
- - id: ruff-format
22
- types_or: [python, pyi]
15
+ - id: ruff # Run linter using pyproject.toml config
16
+ - id: ruff-format # Run formatter using pyproject.toml config
23
17
 
24
18
  - repo: https://github.com/pre-commit/mirrors-prettier
25
19
  rev: "v3.0.3"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eo-tides
3
- Version: 0.7.4.dev7
3
+ Version: 0.7.5.dev1
4
4
  Summary: Tide modelling tools for large-scale satellite earth observation analysis
5
5
  Project-URL: Homepage, https://GeoscienceAustralia.github.io/eo-tides/
6
6
  Project-URL: Repository, https://github.com/GeoscienceAustralia/eo-tides
@@ -49,10 +49,10 @@
49
49
  "metadata": {},
50
50
  "outputs": [],
51
51
  "source": [
52
+ "import matplotlib.pyplot as plt\n",
52
53
  "import odc.stac\n",
53
- "import pystac_client\n",
54
54
  "import planetary_computer\n",
55
- "import matplotlib.pyplot as plt\n",
55
+ "import pystac_client\n",
56
56
  "\n",
57
57
  "from eo_tides.eo import tag_tides\n",
58
58
  "from eo_tides.stats import tide_stats\n",
@@ -264,7 +264,7 @@
264
264
  ],
265
265
  "source": [
266
266
  "# Calculate NDWI\n",
267
- "ds[[\"ndwi\"]] = (ds.green - ds.nir08) / (ds.green + ds.nir08) \n",
267
+ "ds[[\"ndwi\"]] = (ds.green - ds.nir08) / (ds.green + ds.nir08)\n",
268
268
  "\n",
269
269
  "# Plot a single timestep\n",
270
270
  "ds.ndwi.isel(time=1).plot.imshow(vmin=-0.5, vmax=0.5, cmap=\"RdBu\")"
@@ -222,9 +222,10 @@
222
222
  }
223
223
  ],
224
224
  "source": [
225
- "from eo_tides.model import model_tides\n",
226
225
  "import pandas as pd\n",
227
226
  "\n",
227
+ "from eo_tides.model import model_tides\n",
228
+ "\n",
228
229
  "tide_df = model_tides(\n",
229
230
  " x=122.2186,\n",
230
231
  " y=-18.0008,\n",
@@ -680,13 +681,11 @@
680
681
  }
681
682
  ],
682
683
  "source": [
683
- "df = pd.DataFrame(\n",
684
- " {\n",
685
- " \"time\": pd.date_range(start=\"2018-01-01\", end=\"2018-01-31\", periods=2),\n",
686
- " \"x\": [122.21, 122.22],\n",
687
- " \"y\": [-18.20, -18.21],\n",
688
- " }\n",
689
- ")\n",
684
+ "df = pd.DataFrame({\n",
685
+ " \"time\": pd.date_range(start=\"2018-01-01\", end=\"2018-01-31\", periods=2),\n",
686
+ " \"x\": [122.21, 122.22],\n",
687
+ " \"y\": [-18.20, -18.21],\n",
688
+ "})\n",
690
689
  "df"
691
690
  ]
692
691
  },
@@ -1496,7 +1495,7 @@
1496
1495
  " x=122.2186,\n",
1497
1496
  " y=-18.0008,\n",
1498
1497
  " time=pd.date_range(start=\"2018-01-01\", end=\"2018-01-02\", freq=\"5h\"),\n",
1499
- " time_offset='30 min',\n",
1498
+ " time_offset=\"30 min\",\n",
1500
1499
  " directory=directory,\n",
1501
1500
  ")"
1502
1501
  ]
@@ -109,8 +109,8 @@
109
109
  ],
110
110
  "source": [
111
111
  "import odc.stac\n",
112
- "import pystac_client\n",
113
112
  "import planetary_computer\n",
113
+ "import pystac_client\n",
114
114
  "\n",
115
115
  "# Connect to STAC catalog\n",
116
116
  "catalog = pystac_client.Client.open(\n",
@@ -1031,7 +1031,7 @@
1031
1031
  ")\n",
1032
1032
  "\n",
1033
1033
  "# Plot the first four timesteps in our data\n",
1034
- "tides_lowres.isel(time=[0, 1, 2, 3]).plot.imshow(col=\"time\", vmin=-3, vmax=3, cmap=\"RdBu\")\n"
1034
+ "tides_lowres.isel(time=[0, 1, 2, 3]).plot.imshow(col=\"time\", vmin=-3, vmax=3, cmap=\"RdBu\")"
1035
1035
  ]
1036
1036
  },
1037
1037
  {
@@ -2071,14 +2071,14 @@
2071
2071
  "import pandas as pd\n",
2072
2072
  "\n",
2073
2073
  "custom_times = pd.date_range(\n",
2074
- " start=\"2022-01-01\", \n",
2075
- " end=\"2022-01-02\", \n",
2074
+ " start=\"2022-01-01\",\n",
2075
+ " end=\"2022-01-02\",\n",
2076
2076
  " freq=\"6h\",\n",
2077
2077
  ")\n",
2078
2078
  "\n",
2079
2079
  "# Model tides spatially\n",
2080
2080
  "tides_highres = pixel_tides(\n",
2081
- " data=ds, \n",
2081
+ " data=ds,\n",
2082
2082
  " time=custom_times,\n",
2083
2083
  " model=model,\n",
2084
2084
  " directory=directory,\n",
@@ -701,8 +701,8 @@
701
701
  ],
702
702
  "source": [
703
703
  "import odc.stac\n",
704
- "import pystac_client\n",
705
704
  "import planetary_computer\n",
705
+ "import pystac_client\n",
706
706
  "\n",
707
707
  "# Connect to STAC catalog\n",
708
708
  "catalog = pystac_client.Client.open(\n",
@@ -807,7 +807,7 @@
807
807
  " data=ds_s2,\n",
808
808
  " model=model,\n",
809
809
  " directory=directory,\n",
810
- ")\n"
810
+ ")"
811
811
  ]
812
812
  },
813
813
  {
@@ -1603,7 +1603,7 @@
1603
1603
  " data=ds_s1,\n",
1604
1604
  " model=model,\n",
1605
1605
  " directory=directory,\n",
1606
- ")\n"
1606
+ ")"
1607
1607
  ]
1608
1608
  },
1609
1609
  {
@@ -2411,7 +2411,7 @@
2411
2411
  " plot_var=\"satellite_name\",\n",
2412
2412
  " model=model,\n",
2413
2413
  " directory=directory,\n",
2414
- ")\n"
2414
+ ")"
2415
2415
  ]
2416
2416
  },
2417
2417
  {
@@ -3110,7 +3110,7 @@
3110
3110
  "import matplotlib.pyplot as plt\n",
3111
3111
  "\n",
3112
3112
  "stats_ds.spread.plot.imshow()\n",
3113
- "plt.gca().set_title(\"Spread (%)\");\n"
3113
+ "plt.gca().set_title(\"Spread (%)\");"
3114
3114
  ]
3115
3115
  },
3116
3116
  {
@@ -158,9 +158,10 @@
158
158
  }
159
159
  ],
160
160
  "source": [
161
- "from eo_tides.model import model_tides\n",
162
161
  "import pandas as pd\n",
163
162
  "\n",
163
+ "from eo_tides.model import model_tides\n",
164
+ "\n",
164
165
  "x, y = 122.2186, -18.0008\n",
165
166
  "start_time = \"2018-01-01\"\n",
166
167
  "end_time = \"2018-01-31\"\n",
@@ -58,7 +58,7 @@ def _standardise_inputs(
58
58
  """
59
59
 
60
60
  # If `data` is an xarray object, extract its GeoBox and time
61
- if isinstance(data, (xr.DataArray, xr.Dataset)):
61
+ if isinstance(data, xr.DataArray | xr.Dataset):
62
62
  # Try to extract GeoBox
63
63
  try:
64
64
  gbox: GeoBox = data.odc.geobox
@@ -544,14 +544,13 @@ def pixel_tides(
544
544
  # Reproject into original high resolution grid
545
545
  if resample:
546
546
  print("Reprojecting tides into original resolution")
547
- tides_highres = _pixel_tides_resample(
547
+ return _pixel_tides_resample(
548
548
  tides_lowres,
549
549
  gbox,
550
550
  resample_method,
551
551
  dask_chunks,
552
552
  dask_compute,
553
553
  )
554
- return tides_highres
555
554
 
556
555
  print("Returning low resolution tide array")
557
556
  return tides_lowres
@@ -55,10 +55,7 @@ def _parallel_splits(
55
55
  raw_value = os.environ.get("CPU_GUARANTEE") or psutil.cpu_count(logical=False) or os.cpu_count() or 1
56
56
 
57
57
  # Convert to integer
58
- if isinstance(raw_value, str):
59
- parallel_max = int(float(raw_value))
60
- else:
61
- parallel_max = int(raw_value)
58
+ parallel_max = int(float(raw_value)) if isinstance(raw_value, str) else int(raw_value)
62
59
 
63
60
  # Calculate optimal number of splits based on constraints
64
61
  splits_by_size = total_points / min_points_per_split
@@ -66,8 +63,7 @@ def _parallel_splits(
66
63
  optimal_splits = min(splits_by_size, splits_by_cpu)
67
64
 
68
65
  # Convert to integer and ensure at least 1 split
69
- final_split_count = int(max(1, optimal_splits))
70
- return final_split_count
66
+ return int(max(1, optimal_splits))
71
67
 
72
68
 
73
69
  def _model_tides(
@@ -170,12 +166,7 @@ def _model_tides(
170
166
  hc = amp * np.exp(cph)
171
167
 
172
168
  # Compute delta times based on model
173
- if pytmd_model.corrections in ("OTIS", "ATLAS", "TMD3", "netcdf"):
174
- # Use delta time at 2000.0 to match TMD outputs
175
- deltat = np.zeros_like(ts.tt_ut1)
176
- else:
177
- # Use interpolated delta times
178
- deltat = ts.tt_ut1
169
+ deltat = np.zeros_like(ts.tt_ut1) if pytmd_model.corrections in ("OTIS", "ATLAS", "TMD3", "netcdf") else ts.tt_ut1
179
170
 
180
171
  # In "one-to-many" mode, extracted tidal constituents and timesteps
181
172
  # are repeated/multiplied out to match the number of input points and
@@ -44,7 +44,7 @@ def _tide_statistics(obs_tides, all_tides, min_max_q=(0.0, 1.0), dim="time"):
44
44
  offset_high = offset_high_m / tr
45
45
 
46
46
  # Combine into a single dataset
47
- stats_ds = xr.merge(
47
+ return xr.merge(
48
48
  [
49
49
  mot.rename("mot"),
50
50
  mat.rename("mat"),
@@ -61,8 +61,6 @@ def _tide_statistics(obs_tides, all_tides, min_max_q=(0.0, 1.0), dim="time"):
61
61
  compat="override",
62
62
  )
63
63
 
64
- return stats_ds
65
-
66
64
 
67
65
  def _stats_plain_english(mot, mat, hot, hat, lot, lat, otr, tr, spread, offset_low, offset_high):
68
66
  # Plain text descriptors
@@ -568,7 +566,7 @@ def pixel_stats(
568
566
  # Reproject statistics into original high resolution grid
569
567
  if resample:
570
568
  print("Reprojecting statistics into original resolution")
571
- stats_highres = _pixel_tides_resample(
569
+ return _pixel_tides_resample(
572
570
  stats_lowres,
573
571
  gbox,
574
572
  resample_method,
@@ -576,7 +574,6 @@ def pixel_stats(
576
574
  dask_compute,
577
575
  None,
578
576
  )
579
- return stats_highres
580
577
 
581
578
  print("Returning low resolution statistics array")
582
579
  return stats_lowres
@@ -7,7 +7,7 @@ import pathlib
7
7
  import textwrap
8
8
  import warnings
9
9
  from collections import Counter
10
- from typing import List, Union
10
+ from typing import TypeAlias
11
11
 
12
12
  import numpy as np
13
13
  import odc.geo
@@ -21,7 +21,7 @@ from scipy.spatial import cKDTree as KDTree
21
21
  from tqdm import tqdm
22
22
 
23
23
  # Type alias for all possible inputs to "time" params
24
- DatetimeLike = Union[np.ndarray, pd.DatetimeIndex, pd.Timestamp, datetime.datetime, str, List[str]]
24
+ DatetimeLike: TypeAlias = np.ndarray | pd.DatetimeIndex | pd.Timestamp | datetime.datetime | str | list[str]
25
25
 
26
26
 
27
27
  def _get_duplicates(array):
@@ -54,8 +54,7 @@ def _set_directory(
54
54
  directory = pathlib.Path(directory).expanduser()
55
55
  if not directory.exists():
56
56
  raise FileNotFoundError(f"No valid tide model directory found at path `{directory}`")
57
- else:
58
- return directory
57
+ return directory
59
58
 
60
59
 
61
60
  def _standardise_time(
@@ -161,7 +160,7 @@ def _standardise_models(
161
160
  raise ValueError(error_text)
162
161
 
163
162
  # Return set of all ensemble plus any other requested models
164
- models_to_process = sorted(list(set(ensemble_models + [m for m in models_requested if m != "ensemble"])))
163
+ models_to_process = sorted(set(ensemble_models + [m for m in models_requested if m != "ensemble"]))
165
164
 
166
165
  # Otherwise, models to process are the same as those requested
167
166
  else:
@@ -271,7 +270,7 @@ def _clip_model_file(
271
270
  for i in ["lat_z", "lat_v", "lat_u", "con"]:
272
271
  try:
273
272
  nc_clipped[i] = nc_clipped[i].isel(nx=0)
274
- except:
273
+ except KeyError:
275
274
  pass
276
275
 
277
276
  return nc_clipped
@@ -558,8 +557,7 @@ def list_models(
558
557
 
559
558
  if raise_error:
560
559
  raise Exception(warning_msg)
561
- else:
562
- warnings.warn(warning_msg, UserWarning)
560
+ warnings.warn(warning_msg, UserWarning)
563
561
 
564
562
  # Return list of available and supported models
565
563
  return available_models, supported_models
@@ -164,7 +164,7 @@ def _load_gesla_dataset(site, path, na_value):
164
164
  )
165
165
 
166
166
  # Combine two date fields
167
- gesla_df = (
167
+ return (
168
168
  gesla_df.assign(
169
169
  time=pd.to_datetime(gesla_df["date"] + " " + gesla_df["time"]),
170
170
  site_code=site,
@@ -173,8 +173,6 @@ def _load_gesla_dataset(site, path, na_value):
173
173
  .set_index("time")
174
174
  )
175
175
 
176
- return gesla_df
177
-
178
176
 
179
177
  def _nearest_row(gdf, x, y, max_distance=None):
180
178
  # Create a point to find the nearest neighbor for
@@ -288,7 +286,7 @@ def load_gauge_gesla(
288
286
  site_code = [site_code] if not isinstance(site_code, list) else site_code
289
287
 
290
288
  # If x and y are tuples, use xy bounds to identify sites
291
- elif isinstance(x, (tuple, list)) & isinstance(y, (tuple, list)):
289
+ elif isinstance(x, tuple | list) & isinstance(y, tuple | list):
292
290
  bbox = BoundingBox.from_xy(x, y)
293
291
  site_code = metadata_gdf.cx[bbox.left : bbox.right, bbox.top : bbox.bottom].index
294
292
 
@@ -317,7 +315,7 @@ def load_gauge_gesla(
317
315
  # Prepare times
318
316
  if time is None:
319
317
  time = ["1800", str(datetime.datetime.now().year)]
320
- time = [time] if not isinstance(time, (list, tuple)) else time
318
+ time = [time] if not isinstance(time, list | tuple) else time
321
319
  start_time = _round_date_strings(time[0], round_type="start")
322
320
  end_time = _round_date_strings(time[-1], round_type="end")
323
321
 
@@ -27,9 +27,11 @@
27
27
  "source": [
28
28
  "import os\n",
29
29
  "import platform\n",
30
- "import psutil\n",
31
- "import pandas as pd\n",
30
+ "\n",
32
31
  "import numpy as np\n",
32
+ "import pandas as pd\n",
33
+ "import psutil\n",
34
+ "\n",
33
35
  "from eo_tides.model import model_tides"
34
36
  ]
35
37
  },
@@ -107,18 +107,42 @@ allow_redefinition = true
107
107
  testpaths = ["tests"]
108
108
 
109
109
  [tool.ruff]
110
- target-version = "py310"
111
- line-length = 120
112
- fix = true
113
-
114
- [tool.ruff.format]
115
- preview = true
110
+ target-version = "py310" # Target Python 3.10 syntax
111
+ line-length = 120 # Set max line length
112
+ fix = true # Allow auto-fix when used without pre-commit
113
+ lint.select = [
114
+ "I", # Import sorting
115
+ "W", # PyCodeStyle warnings
116
+ "F", # Pyflakes (unused vars, imports, etc.)
117
+ "E", # pycodestyle (spacing, etc.)
118
+ "UP", # Modern Python idioms
119
+ "B006", # Mutable default args
120
+ "B007", # Reusing loop variables
121
+ "C4", # Catch incorrect use of comprehensions, dict, list, etc
122
+ "FA", # Enforce from __future__ import annotations
123
+ "ISC", # Correct use of string concatenation
124
+ "ICN", # Common import conventions
125
+ "RET", # Good return practices
126
+ "SIM", # Common simplification rules
127
+ "TID", # Some good import practices
128
+ "PTH", # Use pathlib instead of os.path
129
+ "NPY", # Some numpy-specific things
130
+ ]
131
+ lint.ignore = [
132
+ "E501", # Don't enforce line length
133
+ "SIM105", # contextlib.suppress
134
+ ]
135
+ exclude = ["tests/testing.ipynb"] # Don't modify testing notebook
116
136
 
117
137
  [tool.ruff.lint.per-file-ignores]
118
138
  "tests/*" = [
119
- "S101" # Assert
139
+ "S101", # Allow `assert` in test files
140
+ "NPY002" # Allow legacy numpy random generation
120
141
  ]
121
142
 
143
+ [tool.ruff.format]
144
+ preview = true # Enable experimental formatting improvements
145
+
122
146
  [tool.deptry.per_rule_ignores]
123
147
  DEP002 = [
124
148
  "folium",
@@ -127,7 +127,7 @@ def satellite_ds_load(request):
127
127
  )
128
128
 
129
129
  # Search the STAC catalog for all items matching the query
130
- ds = odc.stac.load(
130
+ return odc.stac.load(
131
131
  list(query.items()),
132
132
  bands=["nbart_red"],
133
133
  crs=crs,
@@ -138,8 +138,6 @@ def satellite_ds_load(request):
138
138
  chunks={},
139
139
  )
140
140
 
141
- return ds
142
-
143
141
 
144
142
  @pytest.fixture
145
143
  def satellite_ds(satellite_ds_load):
@@ -250,7 +248,7 @@ def create_synthetic_eot20(base_dir="tests/data/tide_models_synthetic"):
250
248
  "real": (("lat", "lon"), data),
251
249
  },
252
250
  coords={"lat": lat, "lon": lon},
253
- attrs={"title": f"DGFI-TUM global empirical ocean tide model"},
251
+ attrs={"title": "DGFI-TUM global empirical ocean tide model"},
254
252
  )
255
253
 
256
254
  # Export
@@ -358,7 +358,7 @@ def test_pixel_tides_ensemble(satellite_ds):
358
358
  ensemble_models=ENSEMBLE_MODELS,
359
359
  )
360
360
 
361
- assert set(modelled_tides_ds.tide_model.values) == set([
361
+ assert set(modelled_tides_ds.tide_model.values) == {
362
362
  "EOT20",
363
363
  "HAMTIDE11",
364
364
  "ensemble-best",
@@ -366,4 +366,4 @@ def test_pixel_tides_ensemble(satellite_ds):
366
366
  "ensemble-mean-top2",
367
367
  "ensemble-mean-weighted",
368
368
  "ensemble-mean",
369
- ])
369
+ }
@@ -369,8 +369,8 @@ def test_model_tides_ensemble():
369
369
  # least one of the other models
370
370
  assert set(modelled_tides_df.columns) == set(models)
371
371
  assert all(
372
- (modelled_tides_df.EOT20 == modelled_tides_df.ensemble)
373
- | (modelled_tides_df.HAMTIDE11 == modelled_tides_df.ensemble)
372
+ (modelled_tides_df.ensemble == modelled_tides_df.EOT20)
373
+ | (modelled_tides_df.ensemble == modelled_tides_df.HAMTIDE11)
374
374
  )
375
375
 
376
376
  # Check that correct model is the closest at each row
@@ -404,7 +404,7 @@ def test_model_tides_ensemble():
404
404
  )
405
405
 
406
406
  # Check that expected models exist, and that valid data is produced
407
- assert set(modelled_tides_df.columns) == set([
407
+ assert set(modelled_tides_df.columns) == {
408
408
  "EOT20",
409
409
  "HAMTIDE11",
410
410
  "ensemble-best",
@@ -412,7 +412,7 @@ def test_model_tides_ensemble():
412
412
  "ensemble-mean-top2",
413
413
  "ensemble-mean-weighted",
414
414
  "ensemble-mean",
415
- ])
415
+ }
416
416
  assert all(modelled_tides_df.notnull())
417
417
 
418
418
  # Long mode, custom functions
@@ -427,7 +427,7 @@ def test_model_tides_ensemble():
427
427
  )
428
428
 
429
429
  # Check that expected models exist in "tide_model" column
430
- assert set(modelled_tides_df.tide_model) == set([
430
+ assert set(modelled_tides_df.tide_model) == {
431
431
  "EOT20",
432
432
  "HAMTIDE11",
433
433
  "ensemble-best",
@@ -435,7 +435,7 @@ def test_model_tides_ensemble():
435
435
  "ensemble-mean-top2",
436
436
  "ensemble-mean-weighted",
437
437
  "ensemble-mean",
438
- ])
438
+ }
439
439
 
440
440
 
441
441
  # Test ensemble dtype is set correctly
@@ -1,9 +1,7 @@
1
1
  import pathlib
2
- import tempfile
3
2
  from datetime import datetime
4
3
 
5
4
  import numpy as np
6
- import odc.geo.geom
7
5
  import pandas as pd
8
6
  import pytest
9
7
 
@@ -67,8 +65,8 @@ def test_clip_models():
67
65
  )
68
66
 
69
67
  # Assert that files were exported for all available models
70
- output_files = set([i.stem for i in out_dir.iterdir()])
71
- assert output_files == set(["GOT5", "EOT20", "hamtide"])
68
+ output_files = {i.stem for i in out_dir.iterdir()}
69
+ assert output_files == {"GOT5", "EOT20", "hamtide"}
72
70
 
73
71
  # Set modelling location
74
72
  x, y = 122.28, -18.06
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes