nadata 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.
- nadata/__init__.py +15 -0
- nadata/api.py +894 -0
- nadata/cli.py +445 -0
- nadata/console.py +486 -0
- nadata/core/__init__.py +0 -0
- nadata/core/database/__init__.py +38 -0
- nadata/core/database/builtins.py +87 -0
- nadata/core/database/database.py +958 -0
- nadata/core/database/dumper.py +285 -0
- nadata/core/database/entity_id.py +142 -0
- nadata/core/database/instance.py +706 -0
- nadata/core/database/network_index.py +1142 -0
- nadata/core/database/page_manager.py +175 -0
- nadata/core/database/persistence/__init__.py +28 -0
- nadata/core/database/persistence/binary_cells.py +1141 -0
- nadata/core/database/persistence/compaction.py +97 -0
- nadata/core/database/persistence/dumper.py +798 -0
- nadata/core/database/persistence/lazy_instances.py +1537 -0
- nadata/core/database/persistence/loader.py +424 -0
- nadata/core/database/persistence/record_store.py +228 -0
- nadata/core/database/persistence/serialization.py +605 -0
- nadata/core/database/query_engine.py +222 -0
- nadata/core/database/queryset.py +508 -0
- nadata/core/database/reconciliation.py +287 -0
- nadata/core/database/slotted_page.py +190 -0
- nadata/core/database/spatial_index.py +1080 -0
- nadata/core/expressions/__init__.py +44 -0
- nadata/core/expressions/autograd.py +2909 -0
- nadata/core/expressions/builtins.py +4673 -0
- nadata/core/expressions/expression.py +2658 -0
- nadata/core/expressions/io_builtins.py +972 -0
- nadata/core/expressions/scope.py +336 -0
- nadata/core/expressions/statement.py +953 -0
- nadata/core/struct/__init__.py +14 -0
- nadata/core/struct/struct.py +218 -0
- nadata/core/struct/struct_attribute.py +100 -0
- nadata/core/struct/struct_method.py +324 -0
- nadata/core/types/__init__.py +33 -0
- nadata/core/types/bits/__init__.py +0 -0
- nadata/core/types/bits/bits.py +686 -0
- nadata/core/types/home_types/__init__.py +19 -0
- nadata/core/types/home_types/color.py +102 -0
- nadata/core/types/home_types/coordinate.py +1008 -0
- nadata/core/types/home_types/datetime.py +362 -0
- nadata/core/types/home_types/geogrid.py +92 -0
- nadata/core/types/home_types/geometry.py +1223 -0
- nadata/core/types/home_types/graph.py +0 -0
- nadata/core/types/home_types/planet.py +359 -0
- nadata/core/types/home_types/sea_level.py +98 -0
- nadata/core/types/home_types/vec.py +0 -0
- nadata/core/types/types.py +1345 -0
- nadata/core/values/__init__.py +14 -0
- nadata/core/values/values.py +1568 -0
- nadata/parser/__init__.py +0 -0
- nadata/parser/expressions/__init__.py +6 -0
- nadata/parser/expressions/dependencies.py +318 -0
- nadata/parser/expressions/expression_parser.py +993 -0
- nadata/parser/expressions/splitter.py +98 -0
- nadata/parser/expressions/statement_parser.py +1425 -0
- nadata/parser/expressions/tokenizer.py +402 -0
- nadata/parser/expressions/type_parser.py +187 -0
- nadata/parser/nadata_loader/__init__.py +8 -0
- nadata/parser/nadata_loader/loader.py +951 -0
- nadata/parser/nastruct_parser/__init__.py +0 -0
- nadata/parser/nastruct_parser/declaration.py +105 -0
- nadata/parser/nastruct_parser/imports.py +164 -0
- nadata/parser/nastruct_parser/nastruct_parser.py +209 -0
- nadata/parser/nastruct_parser/parse_attributes.py +149 -0
- nadata/parser/nastruct_parser/parse_callables.py +436 -0
- nadata/parser/nastruct_parser/parse_expression.py +59 -0
- nadata/parser/nastruct_parser/parse_structs.py +206 -0
- nadata/parser/nastruct_parser/parser_state.py +84 -0
- nadata/parser/nastruct_parser/resolver.py +1412 -0
- nadata/parser/nastruct_parser/struct_body_state.py +50 -0
- nadata/parser/nastruct_parser/tmp_structs.py +156 -0
- nadata/parser/utils/__init__.py +20 -0
- nadata/parser/utils/brackets.py +252 -0
- nadata/parser/utils/comments_remove.py +149 -0
- nadata/parser/utils/identifiers.py +121 -0
- nadata/session.py +868 -0
- nadata-0.1.0.dist-info/METADATA +191 -0
- nadata-0.1.0.dist-info/RECORD +86 -0
- nadata-0.1.0.dist-info/WHEEL +5 -0
- nadata-0.1.0.dist-info/entry_points.txt +2 -0
- nadata-0.1.0.dist-info/licenses/LICENSE +21 -0
- nadata-0.1.0.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Planet representations for Nadata.
|
|
3
|
+
|
|
4
|
+
Provides the Planet class describing the shape of the world coordinates
|
|
5
|
+
live on: a perfect sphere (single radius) or an oblate/prolate spheroid
|
|
6
|
+
(equatorial and polar radii). Also hosts the session-level current
|
|
7
|
+
planet, resolved from project settings (planet.kind, planet.radius,
|
|
8
|
+
planet.equatorial_radius, planet.polar_radius) and consulted by
|
|
9
|
+
geodesy builtins when no explicit planet override is passed.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
# Import Modules
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from typing import Any, Optional
|
|
16
|
+
import math
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Reference radii (meters)
|
|
21
|
+
EARTH_EQUATORIAL_RADIUS: float = 6378137.0
|
|
22
|
+
EARTH_POLAR_RADIUS: float = 6356752.314245
|
|
23
|
+
EARTH_MEAN_RADIUS: float = 6371008.8
|
|
24
|
+
|
|
25
|
+
# Kind names for planet settings
|
|
26
|
+
KIND_SPHERE: str = "sphere"
|
|
27
|
+
KIND_ELLIPSOID: str = "ellipsoid"
|
|
28
|
+
|
|
29
|
+
# Session-level current planet (seeded by the loader from project
|
|
30
|
+
# settings; single-process assumption, see the map plan open points)
|
|
31
|
+
_current_planet: Optional["Planet"] = None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _require_positive_length(name: str, value: Any) -> float:
|
|
36
|
+
"""
|
|
37
|
+
Validates a length argument.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
name (str): Argument name for error messages.
|
|
41
|
+
value (Any): Candidate length.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
float: The validated length.
|
|
45
|
+
|
|
46
|
+
Raises:
|
|
47
|
+
TypeError: If the value is not a real number.
|
|
48
|
+
ValueError: If the value is not strictly positive.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
if isinstance(value, bool) or not isinstance(value, (int, float)):
|
|
52
|
+
raise TypeError(f"Planet {name} must be a number, got '{type(value).__name__}'")
|
|
53
|
+
|
|
54
|
+
if not math.isfinite(float(value)) or float(value) <= 0.0:
|
|
55
|
+
raise ValueError(f"Planet {name} must be a finite positive length, got {value}")
|
|
56
|
+
|
|
57
|
+
return float(value)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class Planet:
|
|
62
|
+
"""
|
|
63
|
+
Describes the shape of a world: sphere or spheroid.
|
|
64
|
+
|
|
65
|
+
Attributes:
|
|
66
|
+
equatorial_radius (float): Equatorial radius in meters.
|
|
67
|
+
polar_radius (Optional[float]): Polar radius in meters, or None
|
|
68
|
+
for a perfect sphere.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
def __init__(
|
|
72
|
+
self,
|
|
73
|
+
equatorial_radius: float = EARTH_MEAN_RADIUS,
|
|
74
|
+
polar_radius: Optional[float] = None,
|
|
75
|
+
) -> None:
|
|
76
|
+
"""
|
|
77
|
+
Initializes the Planet instance.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
equatorial_radius (float, optional): Equatorial radius in
|
|
81
|
+
meters. Defaults to the Earth mean radius.
|
|
82
|
+
polar_radius (Optional[float], optional): Polar radius in
|
|
83
|
+
meters. None yields a perfect sphere. Defaults to None.
|
|
84
|
+
|
|
85
|
+
Raises:
|
|
86
|
+
TypeError: If a radius is not a real number.
|
|
87
|
+
ValueError: If a radius is not a finite positive length.
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
self.equatorial_radius: float = _require_positive_length(
|
|
91
|
+
name="equatorial_radius", value=equatorial_radius
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
self.polar_radius: Optional[float] = (
|
|
95
|
+
None
|
|
96
|
+
if polar_radius is None
|
|
97
|
+
else _require_positive_length(name="polar_radius", value=polar_radius)
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
def sphere(cls, radius: float) -> "Planet":
|
|
102
|
+
"""
|
|
103
|
+
Creates a perfect sphere planet.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
radius (float): Sphere radius in meters.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Planet: The sphere planet.
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
return cls(equatorial_radius=radius, polar_radius=None)
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def is_sphere(self) -> bool:
|
|
116
|
+
"""
|
|
117
|
+
Returns whether the planet is a perfect sphere.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
bool: True when no distinct polar radius is set.
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
return self.polar_radius is None
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def polar_radius_value(self) -> float:
|
|
127
|
+
"""
|
|
128
|
+
Returns the effective polar radius (equals the equatorial
|
|
129
|
+
radius for spheres).
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
float: Polar radius in meters.
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
self.equatorial_radius
|
|
137
|
+
if self.polar_radius is None
|
|
138
|
+
else self.polar_radius
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def flattening(self) -> float:
|
|
143
|
+
"""
|
|
144
|
+
Returns the flattening f = (a - b) / a.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
float: Flattening (0.0 for spheres).
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
return (self.equatorial_radius - self.polar_radius_value) / self.equatorial_radius
|
|
151
|
+
|
|
152
|
+
@property
|
|
153
|
+
def eccentricity_squared(self) -> float:
|
|
154
|
+
"""
|
|
155
|
+
Returns the first eccentricity squared e^2 = 2f - f^2.
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
float: Eccentricity squared (0.0 for spheres).
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
flattening: float = self.flattening
|
|
162
|
+
|
|
163
|
+
return 2.0 * flattening - flattening * flattening
|
|
164
|
+
|
|
165
|
+
@property
|
|
166
|
+
def quadratic_mean_radius(self) -> float:
|
|
167
|
+
"""
|
|
168
|
+
Returns the quadratic mean radius sqrt((a^2 + b^2) / 2), used as
|
|
169
|
+
the sphere fallback for near-antipodal spheroid distances.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
float: Quadratic mean radius in meters.
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
squares: float = (
|
|
176
|
+
self.equatorial_radius ** 2 + self.polar_radius_value ** 2
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
return math.sqrt(squares / 2.0)
|
|
180
|
+
|
|
181
|
+
@property
|
|
182
|
+
def authalic_radius(self) -> float:
|
|
183
|
+
"""
|
|
184
|
+
Returns the authalic (equal-area) radius: the radius of the
|
|
185
|
+
sphere with the same surface area as the spheroid. Used to
|
|
186
|
+
scale spherical polygon areas to spheroids.
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
float: Authalic radius in meters.
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
if self.is_sphere:
|
|
193
|
+
return self.equatorial_radius
|
|
194
|
+
|
|
195
|
+
e: float = math.sqrt(self.eccentricity_squared)
|
|
196
|
+
|
|
197
|
+
if e == 0.0:
|
|
198
|
+
return self.equatorial_radius
|
|
199
|
+
|
|
200
|
+
surface_area: float = (
|
|
201
|
+
2.0
|
|
202
|
+
* math.pi
|
|
203
|
+
* self.equatorial_radius ** 2
|
|
204
|
+
* (1.0 + (1.0 - e * e) / e * math.atanh(e))
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
return math.sqrt(surface_area / (4.0 * math.pi))
|
|
208
|
+
|
|
209
|
+
def surface_radius(self, lat_deg: float) -> float:
|
|
210
|
+
"""
|
|
211
|
+
Returns the distance from the planet center to the surface at a
|
|
212
|
+
geodetic latitude.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
lat_deg (float): Geodetic latitude in degrees.
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
float: Surface radius in meters.
|
|
219
|
+
"""
|
|
220
|
+
|
|
221
|
+
if self.is_sphere:
|
|
222
|
+
return self.equatorial_radius
|
|
223
|
+
|
|
224
|
+
lat_rad: float = math.radians(lat_deg)
|
|
225
|
+
sin_lat: float = math.sin(lat_rad)
|
|
226
|
+
|
|
227
|
+
prime_vertical: float = self.equatorial_radius / math.sqrt(
|
|
228
|
+
1.0 - self.eccentricity_squared * sin_lat * sin_lat
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
x: float = prime_vertical * math.cos(lat_rad)
|
|
232
|
+
z: float = prime_vertical * (1.0 - self.eccentricity_squared) * sin_lat
|
|
233
|
+
|
|
234
|
+
return math.hypot(x, z)
|
|
235
|
+
|
|
236
|
+
def geocentric_latitude(self, lat_deg: float) -> float:
|
|
237
|
+
"""
|
|
238
|
+
Converts a geodetic latitude to the geocentric latitude of the
|
|
239
|
+
surface point below it.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
lat_deg (float): Geodetic latitude in degrees.
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
float: Geocentric latitude in degrees.
|
|
246
|
+
"""
|
|
247
|
+
|
|
248
|
+
if self.is_sphere:
|
|
249
|
+
return lat_deg
|
|
250
|
+
|
|
251
|
+
ratio: float = (self.polar_radius_value ** 2) / (self.equatorial_radius ** 2)
|
|
252
|
+
|
|
253
|
+
return math.degrees(math.atan(ratio * math.tan(math.radians(lat_deg))))
|
|
254
|
+
|
|
255
|
+
def __eq__(self, other: Any) -> bool:
|
|
256
|
+
"""
|
|
257
|
+
Checks equality with another Planet.
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
other (Any): Object to compare with.
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
bool: True when both radii match.
|
|
264
|
+
"""
|
|
265
|
+
|
|
266
|
+
if not isinstance(other, Planet):
|
|
267
|
+
return False
|
|
268
|
+
|
|
269
|
+
return (
|
|
270
|
+
self.equatorial_radius == other.equatorial_radius
|
|
271
|
+
and self.polar_radius == other.polar_radius
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
def __repr__(self) -> str:
|
|
275
|
+
"""
|
|
276
|
+
Returns string representation of the Planet.
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
str: Planet constructor string.
|
|
280
|
+
"""
|
|
281
|
+
|
|
282
|
+
if self.is_sphere:
|
|
283
|
+
return f"Planet({self.equatorial_radius})"
|
|
284
|
+
|
|
285
|
+
return f"Planet({self.equatorial_radius}, {self.polar_radius})"
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
# Default planet: a perfect sphere of the Earth mean radius
|
|
289
|
+
DEFAULT_PLANET: Planet = Planet(equatorial_radius=EARTH_MEAN_RADIUS)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def get_current_planet() -> Planet:
|
|
293
|
+
"""
|
|
294
|
+
Returns the session current planet, falling back to the default
|
|
295
|
+
Earth sphere when no project has configured one.
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
Planet: The current planet.
|
|
299
|
+
"""
|
|
300
|
+
|
|
301
|
+
return _current_planet if _current_planet is not None else DEFAULT_PLANET
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def set_current_planet(planet: Planet) -> None:
|
|
305
|
+
"""
|
|
306
|
+
Replaces the session current planet.
|
|
307
|
+
|
|
308
|
+
Args:
|
|
309
|
+
planet (Planet): The new current planet.
|
|
310
|
+
"""
|
|
311
|
+
|
|
312
|
+
global _current_planet
|
|
313
|
+
|
|
314
|
+
if not isinstance(planet, Planet):
|
|
315
|
+
raise TypeError(f"Expected Planet, got '{type(planet).__name__}'")
|
|
316
|
+
|
|
317
|
+
_current_planet = planet
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def planet_from_settings(settings: dict[str, Any]) -> Planet:
|
|
321
|
+
"""
|
|
322
|
+
Builds a Planet from project settings.
|
|
323
|
+
|
|
324
|
+
Recognized keys:
|
|
325
|
+
- "planet.kind": "sphere" (default) or "ellipsoid".
|
|
326
|
+
- "planet.radius": sphere radius (sphere kind).
|
|
327
|
+
- "planet.equatorial_radius" / "planet.polar_radius": spheroid
|
|
328
|
+
radii (ellipsoid kind; defaults to the WGS84 values).
|
|
329
|
+
|
|
330
|
+
Args:
|
|
331
|
+
settings (dict[str, Any]): The project settings mapping.
|
|
332
|
+
|
|
333
|
+
Returns:
|
|
334
|
+
Planet: The configured planet.
|
|
335
|
+
|
|
336
|
+
Raises:
|
|
337
|
+
ValueError: If the kind is unknown.
|
|
338
|
+
"""
|
|
339
|
+
|
|
340
|
+
kind: str = settings.get("planet.kind", KIND_SPHERE)
|
|
341
|
+
|
|
342
|
+
if kind == KIND_ELLIPSOID:
|
|
343
|
+
return Planet(
|
|
344
|
+
equatorial_radius=settings.get(
|
|
345
|
+
"planet.equatorial_radius", EARTH_EQUATORIAL_RADIUS
|
|
346
|
+
),
|
|
347
|
+
polar_radius=settings.get(
|
|
348
|
+
"planet.polar_radius", EARTH_POLAR_RADIUS
|
|
349
|
+
),
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
if kind == KIND_SPHERE:
|
|
353
|
+
return Planet(
|
|
354
|
+
equatorial_radius=settings.get("planet.radius", EARTH_MEAN_RADIUS)
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
raise ValueError(
|
|
358
|
+
f"Unknown planet kind '{kind}' (expected 'sphere' or 'ellipsoid')"
|
|
359
|
+
)
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Session sea-level surface registry.
|
|
3
|
+
|
|
4
|
+
A registered sea-level layer overrides the plain surface radius used
|
|
5
|
+
by altitude() (and any consumer of sea level): the layer is a sparse
|
|
6
|
+
GeoGrid of sea-surface radii; where it has no data the geometric
|
|
7
|
+
surface radius applies.
|
|
8
|
+
|
|
9
|
+
The registry stores duck-typed adapters only, so it can be imported
|
|
10
|
+
from the geodesy core without circular dependencies. Like the session
|
|
11
|
+
planet, the registry is process-global state.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
# Import Modules
|
|
15
|
+
from typing import Any, Optional
|
|
16
|
+
|
|
17
|
+
from nadata.core.types.home_types.geogrid import bilinear_sample
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class GeoSeaLevelAdapter:
|
|
22
|
+
"""
|
|
23
|
+
Adapter exposing a GeoGrid value as a sea-level surface.
|
|
24
|
+
|
|
25
|
+
Attributes:
|
|
26
|
+
cells (dict[tuple[int, int], Any]): Occupied cells keyed by
|
|
27
|
+
(column, row).
|
|
28
|
+
n_x (int): Longitude column count.
|
|
29
|
+
n_y (int): Latitude row count.
|
|
30
|
+
cell_deg (float): Cell edge in degrees.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, grid: Any) -> None:
|
|
34
|
+
"""
|
|
35
|
+
Initializes the GeoSeaLevelAdapter instance.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
grid (Any): A ValueGeoGrid-like object with cells and a
|
|
39
|
+
TypeGeoGrid-like value_type.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
self.cells: dict[tuple[int, int], Any] = grid.cells
|
|
43
|
+
self.n_x: int = grid.value_type.n_x
|
|
44
|
+
self.n_y: int = grid.value_type.n_y
|
|
45
|
+
self.cell_deg: float = grid.value_type.cell_deg
|
|
46
|
+
|
|
47
|
+
def radius_at(self, lat_deg: float, lon_deg: float) -> Optional[float]:
|
|
48
|
+
"""
|
|
49
|
+
Samples the sea-surface radius at a coordinate.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
lat_deg (float): Latitude in degrees.
|
|
53
|
+
lon_deg (float): Longitude in degrees.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Optional[float]: The interpolated sea-surface radius in
|
|
57
|
+
meters, or None when no surrounding cell has data.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
return bilinear_sample(
|
|
61
|
+
cells=self.cells,
|
|
62
|
+
n_x=self.n_x,
|
|
63
|
+
n_y=self.n_y,
|
|
64
|
+
cell_deg=self.cell_deg,
|
|
65
|
+
lat_deg=lat_deg,
|
|
66
|
+
lon_deg=lon_deg,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
_SEA_LEVEL_SURFACE: Optional[Any] = None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def get_sea_level_surface() -> Optional[Any]:
|
|
76
|
+
"""
|
|
77
|
+
Returns the registered sea-level surface, if any.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Optional[Any]: The surface adapter, or None.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
return _SEA_LEVEL_SURFACE
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def set_sea_level_surface(surface: Optional[Any]) -> None:
|
|
88
|
+
"""
|
|
89
|
+
Replaces the session sea-level surface.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
surface (Optional[Any]): The surface adapter, or None to
|
|
93
|
+
unregister.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
global _SEA_LEVEL_SURFACE
|
|
97
|
+
|
|
98
|
+
_SEA_LEVEL_SURFACE = surface
|
|
File without changes
|