roms-tools 0.0.6__py3-none-any.whl → 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,242 @@
1
+ import xarray as xr
2
+ import numpy as np
3
+ import gcm_filters
4
+ from scipy.interpolate import RegularGridInterpolator
5
+ from scipy.ndimage import label
6
+ from roms_tools.setup.datasets import fetch_topo
7
+ import warnings
8
+ from itertools import count
9
+
10
+
11
+ def _add_topography_and_mask(
12
+ ds, topography_source, smooth_factor, hmin, rmax
13
+ ) -> xr.Dataset:
14
+ lon = ds.lon_rho.values
15
+ lat = ds.lat_rho.values
16
+
17
+ # interpolate topography onto desired grid
18
+ hraw = _make_raw_topography(lon, lat, topography_source)
19
+ hraw = xr.DataArray(data=hraw, dims=["eta_rho", "xi_rho"])
20
+
21
+ # Mask is obtained by finding locations where ocean depth is positive
22
+ mask = xr.where(hraw > 0, 1, 0)
23
+
24
+ # smooth topography domain-wide with Gaussian kernel to avoid grid scale instabilities
25
+ ds["hraw"] = _smooth_topography_globally(hraw, mask, smooth_factor)
26
+ ds["hraw"].attrs = {
27
+ "long_name": "Working bathymetry at rho-points",
28
+ "source": f"Raw bathymetry from {topography_source} (smoothing diameter {smooth_factor})",
29
+ "units": "meter",
30
+ }
31
+
32
+ # fill enclosed basins with land
33
+ mask = _fill_enclosed_basins(mask.values)
34
+ ds["mask_rho"] = xr.DataArray(mask, dims=("eta_rho", "xi_rho"))
35
+ ds["mask_rho"].attrs = {
36
+ "long_name": "Mask at rho-points",
37
+ "units": "land/water (0/1)",
38
+ }
39
+
40
+ # smooth topography locally to satisfy r < rmax
41
+ ds["h"] = _smooth_topography_locally(ds["hraw"] * ds["mask_rho"], hmin, rmax)
42
+ ds["h"].attrs = {
43
+ "long_name": "Final bathymetry at rho-points",
44
+ "units": "meter",
45
+ }
46
+
47
+ ds = _add_topography_metadata(ds, topography_source, smooth_factor, hmin, rmax)
48
+
49
+ return ds
50
+
51
+
52
+ def _make_raw_topography(lon, lat, topography_source) -> np.ndarray:
53
+ """
54
+ Given a grid of (lon, lat) points, fetch the topography file and interpolate height values onto the desired grid.
55
+ """
56
+
57
+ topo_ds = fetch_topo(topography_source)
58
+
59
+ # the following will depend on the topography source
60
+ if topography_source == "etopo5":
61
+ topo_lon = topo_ds["topo_lon"].copy()
62
+ # Modify longitude values where necessary
63
+ topo_lon = xr.where(topo_lon < 0, topo_lon + 360, topo_lon)
64
+ topo_lon_minus360 = topo_lon - 360
65
+ topo_lon_plus360 = topo_lon + 360
66
+ # Concatenate along the longitude axis
67
+ topo_lon_concatenated = xr.concat(
68
+ [topo_lon_minus360, topo_lon, topo_lon_plus360], dim="lon"
69
+ )
70
+ topo_concatenated = xr.concat(
71
+ [-topo_ds["topo"], -topo_ds["topo"], -topo_ds["topo"]], dim="lon"
72
+ )
73
+
74
+ interp = RegularGridInterpolator(
75
+ (topo_ds["topo_lat"].values, topo_lon_concatenated.values),
76
+ topo_concatenated.values,
77
+ method="linear",
78
+ )
79
+
80
+ # Interpolate onto desired domain grid points
81
+ hraw = interp((lat, lon))
82
+
83
+ return hraw
84
+
85
+
86
+ def _smooth_topography_globally(hraw, wet_mask, factor) -> xr.DataArray:
87
+ # since GCM-Filters assumes periodic domain, we extend the domain by one grid cell in each dimension
88
+ # and set that margin to land
89
+ margin_mask = xr.concat([wet_mask, 0 * wet_mask.isel(eta_rho=-1)], dim="eta_rho")
90
+ margin_mask = xr.concat(
91
+ [margin_mask, 0 * margin_mask.isel(xi_rho=-1)], dim="xi_rho"
92
+ )
93
+
94
+ # we choose a Gaussian filter kernel corresponding to a Gaussian with standard deviation factor/sqrt(12);
95
+ # this standard deviation matches the standard deviation of a boxcar kernel with total width equal to factor.
96
+ filter = gcm_filters.Filter(
97
+ filter_scale=factor,
98
+ dx_min=1,
99
+ filter_shape=gcm_filters.FilterShape.GAUSSIAN,
100
+ grid_type=gcm_filters.GridType.REGULAR_WITH_LAND,
101
+ grid_vars={"wet_mask": margin_mask},
102
+ )
103
+ hraw_extended = xr.concat([hraw, hraw.isel(eta_rho=-1)], dim="eta_rho")
104
+ hraw_extended = xr.concat(
105
+ [hraw_extended, hraw_extended.isel(xi_rho=-1)], dim="xi_rho"
106
+ )
107
+
108
+ hsmooth = filter.apply(hraw_extended, dims=["eta_rho", "xi_rho"])
109
+ hsmooth = hsmooth.isel(eta_rho=slice(None, -1), xi_rho=slice(None, -1))
110
+
111
+ return hsmooth
112
+
113
+
114
+ def _fill_enclosed_basins(mask) -> np.ndarray:
115
+ """
116
+ Fills in enclosed basins with land
117
+ """
118
+
119
+ # Label connected regions in the mask
120
+ reg, nreg = label(mask)
121
+ # Find the largest region
122
+ lint = 0
123
+ lreg = 0
124
+ for ireg in range(nreg):
125
+ int_ = np.sum(reg == ireg)
126
+ if int_ > lint and mask[reg == ireg].sum() > 0:
127
+ lreg = ireg
128
+ lint = int_
129
+
130
+ # Remove regions other than the largest one
131
+ for ireg in range(nreg):
132
+ if ireg != lreg:
133
+ mask[reg == ireg] = 0
134
+
135
+ return mask
136
+
137
+
138
+ def _smooth_topography_locally(h, hmin=5, rmax=0.2):
139
+ """
140
+ Smoothes topography locally to satisfy r < rmax
141
+ """
142
+ # Compute rmax_log
143
+ if rmax > 0.0:
144
+ rmax_log = np.log((1.0 + rmax * 0.9) / (1.0 - rmax * 0.9))
145
+ else:
146
+ rmax_log = 0.0
147
+
148
+ # Apply hmin threshold
149
+ h = xr.where(h < hmin, hmin, h)
150
+
151
+ # We will smooth logarithmically
152
+ h_log = np.log(h / hmin)
153
+
154
+ cf1 = 1.0 / 6
155
+ cf2 = 0.25
156
+
157
+ for iter in count():
158
+ # Compute gradients in domain interior
159
+
160
+ # in eta-direction
161
+ cff = h_log.diff("eta_rho").isel(xi_rho=slice(1, -1))
162
+ cr = np.abs(cff)
163
+ with warnings.catch_warnings():
164
+ warnings.simplefilter("ignore") # Ignore division by zero warning
165
+ Op1 = xr.where(cr < rmax_log, 0, 1.0 * cff * (1 - rmax_log / cr))
166
+
167
+ # in xi-direction
168
+ cff = h_log.diff("xi_rho").isel(eta_rho=slice(1, -1))
169
+ cr = np.abs(cff)
170
+ with warnings.catch_warnings():
171
+ warnings.simplefilter("ignore") # Ignore division by zero warning
172
+ Op2 = xr.where(cr < rmax_log, 0, 1.0 * cff * (1 - rmax_log / cr))
173
+
174
+ # in diagonal direction
175
+ cff = (h_log - h_log.shift(eta_rho=1, xi_rho=1)).isel(
176
+ eta_rho=slice(1, None), xi_rho=slice(1, None)
177
+ )
178
+ cr = np.abs(cff)
179
+ with warnings.catch_warnings():
180
+ warnings.simplefilter("ignore") # Ignore division by zero warning
181
+ Op3 = xr.where(cr < rmax_log, 0, 1.0 * cff * (1 - rmax_log / cr))
182
+
183
+ # in the other diagonal direction
184
+ cff = (h_log.shift(eta_rho=1) - h_log.shift(xi_rho=1)).isel(
185
+ eta_rho=slice(1, None), xi_rho=slice(1, None)
186
+ )
187
+ cr = np.abs(cff)
188
+ with warnings.catch_warnings():
189
+ warnings.simplefilter("ignore") # Ignore division by zero warning
190
+ Op4 = xr.where(cr < rmax_log, 0, 1.0 * cff * (1 - rmax_log / cr))
191
+
192
+ # Update h_log in domain interior
193
+ h_log[1:-1, 1:-1] += cf1 * (
194
+ Op1[1:, :]
195
+ - Op1[:-1, :]
196
+ + Op2[:, 1:]
197
+ - Op2[:, :-1]
198
+ + cf2 * (Op3[1:, 1:] - Op3[:-1, :-1] + Op4[:-1, 1:] - Op4[1:, :-1])
199
+ )
200
+
201
+ # No gradient at the domain boundaries
202
+ h_log[0, :] = h_log[1, :]
203
+ h_log[-1, :] = h_log[-2, :]
204
+ h_log[:, 0] = h_log[:, 1]
205
+ h_log[:, -1] = h_log[:, -2]
206
+
207
+ # Update h
208
+ h = hmin * np.exp(h_log)
209
+ # Apply hmin threshold again
210
+ h = xr.where(h < hmin, hmin, h)
211
+
212
+ # compute maximum slope parameter r
213
+ r_eta, r_xi = _compute_rfactor(h)
214
+ rmax0 = np.max([r_eta.max(), r_xi.max()])
215
+ if rmax0 < rmax:
216
+ break
217
+
218
+ return h
219
+
220
+
221
+ def _compute_rfactor(h):
222
+ """
223
+ Computes slope parameter (or r-factor) r = |Delta h| / 2h in both horizontal grid directions.
224
+ """
225
+ # compute r_{i-1/2} = |h_i - h_{i-1}| / (h_i + h_{i+1})
226
+ r_eta = np.abs(h.diff("eta_rho")) / (h + h.shift(eta_rho=1)).isel(
227
+ eta_rho=slice(1, None)
228
+ )
229
+ r_xi = np.abs(h.diff("xi_rho")) / (h + h.shift(xi_rho=1)).isel(
230
+ xi_rho=slice(1, None)
231
+ )
232
+
233
+ return r_eta, r_xi
234
+
235
+
236
+ def _add_topography_metadata(ds, topography_source, smooth_factor, hmin, rmax):
237
+ ds.attrs["topography_source"] = topography_source
238
+ ds.attrs["smooth_factor"] = smooth_factor
239
+ ds.attrs["hmin"] = hmin
240
+ ds.attrs["rmax"] = rmax
241
+
242
+ return ds
@@ -1,19 +1,25 @@
1
1
  import pytest
2
2
  import numpy as np
3
3
  import numpy.testing as npt
4
-
4
+ from scipy.ndimage import label
5
5
  from roms_tools import Grid
6
+ from roms_tools.setup.topography import _compute_rfactor
7
+ from roms_tools.setup.tides import TPXO
8
+ import os
9
+ import tempfile
6
10
 
7
11
 
8
12
  class TestCreateGrid:
9
13
  def test_simple_regression(self):
10
- grid = Grid(nx=1, ny=1, size_x=100, size_y=100, center_lon=-20, center_lat=0)
14
+ grid = Grid(
15
+ nx=1, ny=1, size_x=100, size_y=100, center_lon=-20, center_lat=0, rot=0
16
+ )
11
17
 
12
18
  expected_lat = np.array(
13
19
  [
14
- [1.79855429e00, 1.79855429e00, 1.79855429e00],
15
- [1.72818690e-14, 1.70960078e-14, 1.70960078e-14],
16
- [-1.79855429e00, -1.79855429e00, -1.79855429e00],
20
+ [-8.99249453e-01, -8.99249453e-01, -8.99249453e-01],
21
+ [0.0, 0.0, 0.0],
22
+ [8.99249453e-01, 8.99249453e-01, 8.99249453e-01],
17
23
  ]
18
24
  )
19
25
  expected_lon = np.array(
@@ -24,18 +30,18 @@ class TestCreateGrid:
24
30
  ]
25
31
  )
26
32
 
27
- npt.assert_allclose(grid.ds["lat_rho"], expected_lat)
28
- npt.assert_allclose(grid.ds["lon_rho"], expected_lon)
33
+ # TODO: adapt tolerances according to order of magnitude of respective fields
34
+ npt.assert_allclose(grid.ds["lat_rho"], expected_lat, atol=1e-8)
35
+ npt.assert_allclose(grid.ds["lon_rho"], expected_lon, atol=1e-8)
29
36
 
30
- def test_raise_if_crossing_dateline(self):
31
- with pytest.raises(ValueError, match="cannot cross Greenwich Meridian"):
32
- # test grid centered over London
33
- Grid(nx=3, ny=3, size_x=100, size_y=100, center_lon=0, center_lat=51.5)
37
+ def test_raise_if_domain_too_large(self):
38
+ with pytest.raises(ValueError, match="Domain size has to be smaller"):
39
+ Grid(nx=3, ny=3, size_x=30000, size_y=30000, center_lon=0, center_lat=51.5)
34
40
 
35
- # test Iceland grid which is rotated specifically to avoid Greenwich Meridian
41
+ # test grid with reasonable domain size
36
42
  grid = Grid(
37
- nx=100,
38
- ny=100,
43
+ nx=3,
44
+ ny=3,
39
45
  size_x=1800,
40
46
  size_y=2400,
41
47
  center_lon=-21,
@@ -44,11 +50,132 @@ class TestCreateGrid:
44
50
  )
45
51
  assert isinstance(grid, Grid)
46
52
 
53
+ def test_grid_straddle_crosses_meridian(self):
54
+ grid = Grid(
55
+ nx=3,
56
+ ny=3,
57
+ size_x=100,
58
+ size_y=100,
59
+ center_lon=0,
60
+ center_lat=61,
61
+ rot=20,
62
+ )
63
+ assert grid.straddle
64
+
65
+ grid = Grid(
66
+ nx=3,
67
+ ny=3,
68
+ size_x=100,
69
+ size_y=100,
70
+ center_lon=180,
71
+ center_lat=61,
72
+ rot=20,
73
+ )
74
+ assert not grid.straddle
47
75
 
48
- class TestGridFromFile:
49
- def test_equal_to_from_init(self):
50
- ...
51
76
 
77
+ class TestGridFromFile:
52
78
  def test_roundtrip(self):
53
79
  """Test that creating a grid, saving it to file, and re-opening it is the same as just creating it."""
54
- ...
80
+
81
+ # Initialize a Grid object using the initializer
82
+ grid_init = Grid(
83
+ nx=10,
84
+ ny=15,
85
+ size_x=100.0,
86
+ size_y=150.0,
87
+ center_lon=0.0,
88
+ center_lat=0.0,
89
+ rot=0.0,
90
+ topography_source="etopo5",
91
+ smooth_factor=2,
92
+ hmin=5.0,
93
+ rmax=0.2,
94
+ )
95
+
96
+ # Create a temporary file
97
+ with tempfile.NamedTemporaryFile(delete=False) as tmpfile:
98
+ filepath = tmpfile.name
99
+
100
+ try:
101
+ # Save the grid to a file
102
+ grid_init.save(filepath)
103
+
104
+ # Load the grid from the file
105
+ grid_from_file = Grid.from_file(filepath)
106
+
107
+ # Assert that the initial grid and the loaded grid are equivalent (including the 'ds' attribute)
108
+ assert grid_init == grid_from_file
109
+
110
+ finally:
111
+ os.remove(filepath)
112
+
113
+
114
+ class TestTopography:
115
+ def test_enclosed_regions(self):
116
+ """Test that there are only two connected regions, one dry and one wet."""
117
+
118
+ grid = Grid(
119
+ nx=100,
120
+ ny=100,
121
+ size_x=1800,
122
+ size_y=2400,
123
+ center_lon=30,
124
+ center_lat=61,
125
+ rot=20,
126
+ )
127
+
128
+ reg, nreg = label(grid.ds.mask_rho)
129
+ npt.assert_equal(nreg, 2)
130
+
131
+ def test_rmax_criterion(self):
132
+ grid = Grid(
133
+ nx=100,
134
+ ny=100,
135
+ size_x=1800,
136
+ size_y=2400,
137
+ center_lon=30,
138
+ center_lat=61,
139
+ rot=20,
140
+ smooth_factor=4,
141
+ rmax=0.2,
142
+ )
143
+ r_eta, r_xi = _compute_rfactor(grid.ds.h)
144
+ rmax0 = np.max([r_eta.max(), r_xi.max()])
145
+ npt.assert_array_less(rmax0, grid.rmax)
146
+
147
+ def test_hmin_criterion(self):
148
+ grid = Grid(
149
+ nx=100,
150
+ ny=100,
151
+ size_x=1800,
152
+ size_y=2400,
153
+ center_lon=30,
154
+ center_lat=61,
155
+ rot=20,
156
+ smooth_factor=2,
157
+ rmax=0.2,
158
+ hmin=5,
159
+ )
160
+
161
+ assert np.less_equal(grid.hmin, grid.ds.h.min())
162
+
163
+
164
+ class TestTPXO:
165
+ def test_load_data_file_not_found(self):
166
+ # Test loading data from a non-existing file
167
+ with pytest.raises(FileNotFoundError):
168
+ TPXO.load_data("non_existing_file.nc")
169
+
170
+ def test_load_data_checksum_mismatch(self):
171
+ # Create a temporary file for testing
172
+ filename = "test_tidal_data.nc"
173
+ with open(filename, "wb") as file:
174
+ # Write some data to the file
175
+ file.write(b"test data")
176
+ # Test loading data with incorrect checksum
177
+ with open(filename, "wb") as file:
178
+ with pytest.raises(ValueError):
179
+ TPXO.load_data(filename)
180
+ # Remove temporary file
181
+ os.remove(filename)
@@ -0,0 +1,89 @@
1
+ Metadata-Version: 2.1
2
+ Name: roms-tools
3
+ Version: 0.1.0
4
+ Summary: Tools for running and analysing UCLA-ROMS simulations
5
+ Author-email: Nora Loose <nora.loose@gmail.com>, Thomas Nicholas <tom@cworthy.org>
6
+ License: Apache-2
7
+ Project-URL: Home, https://github.com/CWorthy-ocean/roms-tools
8
+ Project-URL: Documentation, https://roms-tools.readthedocs.io/en/latest/
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Topic :: Scientific/Engineering
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: xarray >=2022.6.0
22
+ Requires-Dist: numpy
23
+ Requires-Dist: netcdf4
24
+ Requires-Dist: pooch
25
+ Requires-Dist: matplotlib
26
+ Requires-Dist: cartopy
27
+ Requires-Dist: packaging
28
+ Requires-Dist: scipy
29
+ Requires-Dist: gcm-filters
30
+ Requires-Dist: numba
31
+
32
+ # ROMS-Tools
33
+
34
+ [![Documentation Status](https://readthedocs.org/projects/roms-tools/badge/?version=latest)](https://roms-tools.readthedocs.io/en/latest/?badge=latest)
35
+ [![PyPI version](https://badge.fury.io/py/roms-tools.svg)](https://badge.fury.io/py/roms-tools)
36
+
37
+ ## Overview
38
+
39
+ A suite of python tools for setting up a [ROMS](https://github.com/CESR-lab/ucla-roms) simulation.
40
+
41
+ ## Installation instructions
42
+
43
+ ### Installation from pip
44
+
45
+ ```bash
46
+ pip install roms-tools
47
+ ```
48
+
49
+ ### Installation from GitHub
50
+
51
+ To obtain the latest development version, clone the source repository and install it:
52
+
53
+ ```bash
54
+ git clone https://github.com/CWorthy-ocean/roms-tools.git
55
+ cd roms-tools
56
+ pip install -e .
57
+ ```
58
+
59
+
60
+ ### Run the tests
61
+
62
+ Before running the tests you can install and activate the following conda environment:
63
+
64
+ ```bash
65
+ cd roms-tools
66
+ conda env create -f ci/environment.yml
67
+ conda activate romstools
68
+ ```
69
+
70
+ Check the installation of `ROMS-Tools` has worked by running the test suite
71
+ ```bash
72
+ pytest
73
+ ```
74
+
75
+ ## Getting Started
76
+
77
+ To learn how to use `ROMS-Tools`, check out the [documentation](https://roms-tools.readthedocs.io/en/latest/).
78
+
79
+ ## Feedback and contributions
80
+
81
+ **If you find a bug, have a feature suggestion, or any other kind of feedback, please start a Discussion.**
82
+
83
+ We also accept contributions in the form of Pull Requests.
84
+
85
+
86
+ ## See also
87
+
88
+ - [ROMS source code](https://github.com/CESR-lab/ucla-roms)
89
+ - [C-Star](https://github.com/CWorthy-ocean/C-Star)
@@ -0,0 +1,17 @@
1
+ ci/environment.yml,sha256=OzTO5aTfzirFobAM6TmzJXZ622liCwIzreZH-x7n4mU,394
2
+ roms_tools/__init__.py,sha256=9MiZw2yYthIwOrktbOKwNptyZPmMV4_p4aCK4HymzUM,489
3
+ roms_tools/_version.py,sha256=FGsmFbZ942cZk42U_qHqxgRCbsD--5Vld_eR6xKJ-mQ,72
4
+ roms_tools/setup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ roms_tools/setup/atmospheric_forcing.py,sha256=A6wPmEfjeCIO3tu4TLt4Sul_J6AnF_peWZdON3I_6iw,34790
6
+ roms_tools/setup/datasets.py,sha256=0Hcsr7VzE-jo51kSMZ0ltHnIqc3fHe2v9lAC6ig2rH0,1943
7
+ roms_tools/setup/fill.py,sha256=8Klt77rkJqyXQ54TUv75KK_5iHcAwH-3bBtO3eoBieM,8701
8
+ roms_tools/setup/grid.py,sha256=p8AgCzUx5CkuxFcjFX6X65pYwEyOzxslx_nZDNJd-M4,26449
9
+ roms_tools/setup/plot.py,sha256=LZjTB4NHpXGsju_VZSCBwTfyox08nXHh6TkqmNBvz5Y,1809
10
+ roms_tools/setup/tides.py,sha256=aOez64Zv6MM1VFs1WIClKPpSg9vySvogqfqbg2eHKHA,20942
11
+ roms_tools/setup/topography.py,sha256=hj_IEbMTaazEtp6rrNbqAtGgPesWcCs8eHko0XHEhJg,8010
12
+ roms_tools/tests/test_setup.py,sha256=L90eM0IroRhYQ8ZY9BVOyUQND41lzdJKB_y2n7Aihmc,5102
13
+ roms_tools-0.1.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
14
+ roms_tools-0.1.0.dist-info/METADATA,sha256=XtN4Icf1h7Sh_ZbL9OFNCr9wIkvRpqTuo95szsLNtcg,2567
15
+ roms_tools-0.1.0.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
16
+ roms_tools-0.1.0.dist-info/top_level.txt,sha256=aAf4T4nYQSkay5iKJ9kmTjlDgd4ETdp9OSlB4sJdt8Y,19
17
+ roms_tools-0.1.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: setuptools (70.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,134 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: roms-tools
3
- Version: 0.0.6
4
- Summary: Tools for running and analysing UCLA-ROMS simulations
5
- Author-email: Thomas Nicholas <tom@cworthy.org>
6
- License: Apache-2
7
- Project-URL: Home, https://github.com/CWorthy-ocean/roms-tools
8
- Project-URL: Documentation, https://github.com/CWorthy-ocean/roms-tools#readme
9
- Classifier: Development Status :: 3 - Alpha
10
- Classifier: Intended Audience :: Science/Research
11
- Classifier: Topic :: Scientific/Engineering
12
- Classifier: License :: OSI Approved :: Apache Software License
13
- Classifier: Operating System :: OS Independent
14
- Classifier: Programming Language :: Python
15
- Classifier: Programming Language :: Python :: 3.9
16
- Classifier: Programming Language :: Python :: 3.10
17
- Classifier: Programming Language :: Python :: 3.11
18
- Classifier: Programming Language :: Python :: 3.12
19
- Requires-Python: >=3.9
20
- Description-Content-Type: text/markdown
21
- License-File: LICENSE
22
- Requires-Dist: xarray >=2022.6.0
23
- Requires-Dist: numpy
24
- Requires-Dist: netcdf4
25
- Requires-Dist: matplotlib
26
- Requires-Dist: cartopy
27
- Requires-Dist: packaging
28
-
29
- # ROMS-tools
30
-
31
- ## Overview
32
-
33
- A suite of python tools for setting up a [ROMS](https://github.com/CESR-lab/ucla-roms) simulation.
34
-
35
- _Note these tools are for the [Center for Earth Systems Research Group](http://research.atmos.ucla.edu/cesr/) at UCLA's version of ROMS._
36
-
37
- ## Installation instructions
38
-
39
- Install via pip
40
-
41
- ```bash
42
- pip install roms-tools
43
- ```
44
-
45
- Check the installation has worked by running the tests (you will need to also install pytest to run these)
46
- ```bash
47
- pytest
48
- ```
49
-
50
- Dependencies required are xarray and netcdf4, plus matplotlib and cartopy for visualising grids.
51
-
52
- ROMS-tools should run on any platform that can install the above dependencies.
53
-
54
-
55
- ## Usage instructions
56
-
57
- To set up all the input files for a new ROMS simulation from scratch, follow these steps in order.
58
-
59
- ### Step 1: Make Grid
60
-
61
- The first step is choosing the domain size, location, and resolution. Do this by creating an instance of the `Grid` class:
62
-
63
- ```python
64
- from roms_tools import Grid
65
-
66
- grid = Grid(
67
- nx=100, # number of points in the x-direction (not including 2 boundary cells on either end)
68
- ny=100, # number of points in the y-direction (not including 2 boundary cells on either end)
69
- size_x=1800, # size of the domain in the x-direction (in km)
70
- size_y=2400, # size of the domain in the y-direction (in km)
71
- center_lon=-21, # longitude of the center of the domain
72
- center_lat=61, # latitude of the center of the domain
73
- rot=20, # rotation of the grid's x-direction from lines of constant longitude, with positive values being a counter-clockwise rotation
74
- )
75
- ```
76
-
77
- To visualize the grid we have just created, use the `.plot` method:
78
-
79
- ```python
80
- grid.plot()
81
- ```
82
-
83
- ![iceland_grid](https://github.com/CWorthy-ocean/roms-tools/assets/35968931/de8c03ab-3c61-4ba5-a9b7-65592fd9280f)
84
-
85
- To see the values of the grid variables you can examine the `xarray.Dataset` object returned by the `.ds` property
86
-
87
- ```python
88
- grid.ds
89
- ```
90
- ```
91
- <xarray.Dataset>
92
- Dimensions: (eta_rho: 3, xi_rho: 3, one: 1)
93
- Dimensions without coordinates: eta_rho, xi_rho, one
94
- Data variables:
95
- angle (eta_rho, xi_rho) float64 0.0 0.0 0.0 -1.46e-16 ... 0.0 0.0 0.0
96
- f0 (eta_rho, xi_rho) float64 4.565e-06 4.565e-06 ... -4.565e-06
97
- pn (eta_rho, xi_rho) float64 5e-06 5e-06 5e-06 ... 5e-06 5e-06 5e-06
98
- lon_rho (eta_rho, xi_rho) float64 339.1 340.0 340.9 ... 339.1 340.0 340.9
99
- lat_rho (eta_rho, xi_rho) float64 1.799 1.799 1.799 ... -1.799 -1.799
100
- spherical (one) <U1 'T'
101
- tra_lon (one) int64 -20
102
- tra_lat (one) int64 0
103
- rotate (one) int64 0
104
- Attributes:
105
- Title: ROMS grid. Settings: nx: 1 ny: 1 xsize: 0.1 ysize: 0.1 rotate:...
106
- Date: 2023-11-20
107
- Type: ROMS grid produced by roms-tools
108
- ```
109
-
110
- Once we are happy with our grid, we can save it as a netCDF file via the `.save` method:
111
-
112
- ```python
113
- grid.save('grids/my_new_roms_grid.nc')
114
- ```
115
-
116
- The basic grid domain is now ready for use by ROMS.
117
-
118
-
119
- ### Steps 2-7:
120
-
121
- Coming soon!
122
-
123
-
124
- ## Feedback and contributions
125
-
126
- **If you find a bug, have a feature suggestion, or any other kind of feedback, please start a Discussion.**
127
-
128
- We also accept contributions in the form of Pull Requests.
129
-
130
-
131
- ## See also
132
-
133
- - [ROMS source code](https://github.com/CESR-lab/ucla-roms)
134
- - [C-Star](https://github.com/CWorthy-ocean/C-Star)