tilupy 2.0.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.
- tilupy/__init__.py +23 -0
- tilupy/analytic_sol.py +2403 -0
- tilupy/benchmark.py +1563 -0
- tilupy/calibration.py +134 -0
- tilupy/cmd.py +177 -0
- tilupy/compare.py +195 -0
- tilupy/download_data.py +68 -0
- tilupy/initdata.py +207 -0
- tilupy/initsimus.py +50 -0
- tilupy/make_mass.py +111 -0
- tilupy/make_topo.py +468 -0
- tilupy/models/__init__.py +0 -0
- tilupy/models/lave2D/__init__.py +0 -0
- tilupy/models/lave2D/initsimus.py +665 -0
- tilupy/models/lave2D/read.py +264 -0
- tilupy/models/ravaflow/__init__.py +0 -0
- tilupy/models/ravaflow/initsimus.py +192 -0
- tilupy/models/ravaflow/read.py +273 -0
- tilupy/models/saval2D/__init__.py +0 -0
- tilupy/models/saval2D/read.py +298 -0
- tilupy/models/shaltop/__init__.py +0 -0
- tilupy/models/shaltop/initsimus.py +375 -0
- tilupy/models/shaltop/read.py +613 -0
- tilupy/notations.py +866 -0
- tilupy/plot.py +234 -0
- tilupy/raster.py +199 -0
- tilupy/read.py +2588 -0
- tilupy/utils.py +656 -0
- tilupy-2.0.0.dist-info/METADATA +876 -0
- tilupy-2.0.0.dist-info/RECORD +34 -0
- tilupy-2.0.0.dist-info/WHEEL +5 -0
- tilupy-2.0.0.dist-info/entry_points.txt +3 -0
- tilupy-2.0.0.dist-info/licenses/LICENSE +516 -0
- tilupy-2.0.0.dist-info/top_level.txt +1 -0
tilupy/notations.py
ADDED
|
@@ -0,0 +1,866 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
import tilupy
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
LABEL_OPTIONS = dict(language="english", label_type="symbol")
|
|
10
|
+
"""Dictionary of configuration options for label generation.
|
|
11
|
+
|
|
12
|
+
This dictionary specifies the settings used for generating or formatting labels.
|
|
13
|
+
It includes the language of the labels and the type of label representation.
|
|
14
|
+
|
|
15
|
+
Keys:
|
|
16
|
+
- language : str
|
|
17
|
+
Language used for the labels (e.g., "english").
|
|
18
|
+
- label_type : str
|
|
19
|
+
Type of label representation (e.g., "symbol" for symbolic labels).
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
class Notation:
|
|
23
|
+
"""Notation system for physical quantities, symbols, or variables.
|
|
24
|
+
|
|
25
|
+
This class allows the definition of a notation with a name, long name, gender, symbol, and unit.
|
|
26
|
+
It provides properties to access and modify these attributes, and a method to retrieve the long name
|
|
27
|
+
in a specific language.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
name : str
|
|
32
|
+
The short name or identifier of the notation.
|
|
33
|
+
long_name : tilupy.notations.LongName or str, optional
|
|
34
|
+
The long name of the notation. If a dictionary is provided, it is converted to a
|
|
35
|
+
:any:`tilupy.notations.LongName` object. By default None.
|
|
36
|
+
gender : tilupy.notations.Gender, optional
|
|
37
|
+
The gender associated with the notation. If a dictionary is provided, it is converted to a
|
|
38
|
+
:obj:`tilupy.notations.Gender` object. By default None.
|
|
39
|
+
symbol : str, optional
|
|
40
|
+
The symbol representing the notation. By default None.
|
|
41
|
+
unit : tilupy.notations.Unit, optional
|
|
42
|
+
The unit associated with the notation. By default None.
|
|
43
|
+
|
|
44
|
+
Attributes
|
|
45
|
+
----------
|
|
46
|
+
_name : str
|
|
47
|
+
The short name or identifier of the notation.
|
|
48
|
+
_long_name : tilupy.notations.LongName or str
|
|
49
|
+
The long name of the notation, which can be language-specific or gender-specific.
|
|
50
|
+
_gender : tilupy.notations.Gender
|
|
51
|
+
The gender associated with the notation, if applicable.
|
|
52
|
+
_symbol : str
|
|
53
|
+
The symbol representing the notation (e.g., mathematical symbol).
|
|
54
|
+
_unit : tilupy.notations.Unit
|
|
55
|
+
The unit associated with the notation (e.g., physical unit).
|
|
56
|
+
"""
|
|
57
|
+
def __init__(self,
|
|
58
|
+
name: str,
|
|
59
|
+
long_name: tilupy.notations.LongName | str = None,
|
|
60
|
+
gender: tilupy.notations.Gender | str = None,
|
|
61
|
+
symbol: str = None,
|
|
62
|
+
unit: tilupy.notations.Unit = None):
|
|
63
|
+
self._name = name
|
|
64
|
+
self._long_name = long_name
|
|
65
|
+
self._gender = gender
|
|
66
|
+
self._symbol = symbol
|
|
67
|
+
self._unit = unit
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def name(self):
|
|
72
|
+
"""Get name.
|
|
73
|
+
|
|
74
|
+
Returns
|
|
75
|
+
-------
|
|
76
|
+
str
|
|
77
|
+
Attribute :attr:`_name`
|
|
78
|
+
"""
|
|
79
|
+
return self._name
|
|
80
|
+
|
|
81
|
+
@name.setter
|
|
82
|
+
def name(self, value: str):
|
|
83
|
+
"""Set name.
|
|
84
|
+
|
|
85
|
+
Parameters
|
|
86
|
+
----------
|
|
87
|
+
value : str
|
|
88
|
+
Name value
|
|
89
|
+
"""
|
|
90
|
+
if value is None:
|
|
91
|
+
self._name = None
|
|
92
|
+
else:
|
|
93
|
+
self._name = value
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def unit(self):
|
|
97
|
+
"""Get unit.
|
|
98
|
+
|
|
99
|
+
Returns
|
|
100
|
+
-------
|
|
101
|
+
tilupy.notations.Unit
|
|
102
|
+
Attribute :attr:`_unit`
|
|
103
|
+
"""
|
|
104
|
+
return self._unit
|
|
105
|
+
|
|
106
|
+
@unit.setter
|
|
107
|
+
def unit(self, value: str):
|
|
108
|
+
"""Set unit.
|
|
109
|
+
|
|
110
|
+
Parameters
|
|
111
|
+
----------
|
|
112
|
+
value : tilupy.notations.Unit
|
|
113
|
+
Unit value
|
|
114
|
+
"""
|
|
115
|
+
if value is None:
|
|
116
|
+
self._unit = None
|
|
117
|
+
else:
|
|
118
|
+
self._unit = value
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def gender(self):
|
|
122
|
+
"""Get gender.
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
tilupy.notations.Gender
|
|
127
|
+
Attribute :attr:`_gender`
|
|
128
|
+
"""
|
|
129
|
+
return self._gender
|
|
130
|
+
|
|
131
|
+
@gender.setter
|
|
132
|
+
def gender(self, value):
|
|
133
|
+
"""Set unit.
|
|
134
|
+
|
|
135
|
+
Parameters
|
|
136
|
+
----------
|
|
137
|
+
value : tilupy.notations.Gender
|
|
138
|
+
Gender value
|
|
139
|
+
"""
|
|
140
|
+
if value is None:
|
|
141
|
+
self._gender = Gender()
|
|
142
|
+
elif isinstance(value, dict):
|
|
143
|
+
self._gender = Gender(**value)
|
|
144
|
+
else:
|
|
145
|
+
self._gender = value
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def symbol(self):
|
|
149
|
+
"""Get symbol.
|
|
150
|
+
|
|
151
|
+
Returns
|
|
152
|
+
-------
|
|
153
|
+
str
|
|
154
|
+
Attribute :attr:`_symbol`
|
|
155
|
+
"""
|
|
156
|
+
return self._symbol
|
|
157
|
+
|
|
158
|
+
@symbol.setter
|
|
159
|
+
def symbol(self, value: str):
|
|
160
|
+
"""Set symbol.
|
|
161
|
+
|
|
162
|
+
Parameters
|
|
163
|
+
----------
|
|
164
|
+
value : str
|
|
165
|
+
Symbol value
|
|
166
|
+
"""
|
|
167
|
+
if value is None:
|
|
168
|
+
self._symbol = None
|
|
169
|
+
else:
|
|
170
|
+
self._symbol = value
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def long_name(self):
|
|
174
|
+
"""Get long name.
|
|
175
|
+
|
|
176
|
+
Returns
|
|
177
|
+
-------
|
|
178
|
+
tilupy.notations.LongName
|
|
179
|
+
Attribute :attr:`_long_name`
|
|
180
|
+
"""
|
|
181
|
+
return self._long_name
|
|
182
|
+
|
|
183
|
+
@long_name.setter
|
|
184
|
+
def long_name(self, value):
|
|
185
|
+
"""Set long name.
|
|
186
|
+
|
|
187
|
+
Parameters
|
|
188
|
+
----------
|
|
189
|
+
value : tilupy.notations.LongName
|
|
190
|
+
Long name value
|
|
191
|
+
"""
|
|
192
|
+
if value is None:
|
|
193
|
+
self._long_name = LongName()
|
|
194
|
+
elif isinstance(value, dict):
|
|
195
|
+
self._long_name = LongName(**value)
|
|
196
|
+
else:
|
|
197
|
+
self._long_name = value
|
|
198
|
+
|
|
199
|
+
def get_long_name(self,
|
|
200
|
+
language: str = None,
|
|
201
|
+
gender: str = None
|
|
202
|
+
) -> str:
|
|
203
|
+
"""Retrieve the long name of the notation in the specified language and gender form.
|
|
204
|
+
|
|
205
|
+
The method retrieves the long name in the specified language (defaulting to the language
|
|
206
|
+
in :data:`tilupy.notations.LABEL_OPTIONS`). If a gender is provided, the method returns
|
|
207
|
+
the gender-specific form of the long name.
|
|
208
|
+
|
|
209
|
+
Parameters
|
|
210
|
+
----------
|
|
211
|
+
language : str, optional
|
|
212
|
+
The language in which to retrieve the long name. If not provided, the language from
|
|
213
|
+
:data:`tilupy.notations.LABEL_OPTIONS` is used.
|
|
214
|
+
gender : str, optional
|
|
215
|
+
The gender form of the long name to retrieve. If not provided, the default form is returned.
|
|
216
|
+
|
|
217
|
+
Returns
|
|
218
|
+
-------
|
|
219
|
+
str
|
|
220
|
+
The long name in the specified language and gender form. If the long name is a string, it is returned as-is.
|
|
221
|
+
"""
|
|
222
|
+
if isinstance(self._long_name, str):
|
|
223
|
+
return self._long_name
|
|
224
|
+
|
|
225
|
+
if language is None:
|
|
226
|
+
language = LABEL_OPTIONS["language"]
|
|
227
|
+
|
|
228
|
+
if isinstance(self._long_name, dict):
|
|
229
|
+
return self._long_name[language]
|
|
230
|
+
|
|
231
|
+
res = getattr(self._long_name, language)
|
|
232
|
+
if gender is not None:
|
|
233
|
+
res = res[gender]
|
|
234
|
+
|
|
235
|
+
return res
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
class Unit(pd.Series):
|
|
239
|
+
"""Subclass of pandas.Series to represent physical units and their exponents.
|
|
240
|
+
|
|
241
|
+
This class allows the creation of unit objects as combinations of base units (e.g., "Pa", "N", "kg")
|
|
242
|
+
with their respective exponents. It supports basic operations like multiplication and provides
|
|
243
|
+
a method to generate a LaTeX-formatted label for the unit combination.
|
|
244
|
+
|
|
245
|
+
Parameters
|
|
246
|
+
----------
|
|
247
|
+
series : pandas.Series, optional
|
|
248
|
+
An existing Series to initialize the Unit object.
|
|
249
|
+
**kwargs : dict
|
|
250
|
+
Key-value pairs where keys are unit names (from `Unit.UNITS`)
|
|
251
|
+
and values are their exponents (as integers or floats).
|
|
252
|
+
If provided, only units in `Unit.UNITS` are allowed.
|
|
253
|
+
|
|
254
|
+
Raises
|
|
255
|
+
------
|
|
256
|
+
ValueError
|
|
257
|
+
If a key in `kwargs` is not in `Unit.UNITS`.
|
|
258
|
+
"""
|
|
259
|
+
|
|
260
|
+
UNITS = ["Pa", "N", "kg", "m", "s", "J"]
|
|
261
|
+
"""List of available units."""
|
|
262
|
+
|
|
263
|
+
def __init__(self,
|
|
264
|
+
series: pd.Series = None,
|
|
265
|
+
**kwargs):
|
|
266
|
+
if series is not None:
|
|
267
|
+
super().__init__(series)
|
|
268
|
+
else:
|
|
269
|
+
super().__init__(dtype="object")
|
|
270
|
+
for key in kwargs:
|
|
271
|
+
if key not in Unit.UNITS:
|
|
272
|
+
raise ValueError("unrecognized unit")
|
|
273
|
+
self[key] = kwargs[key]
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def __mul__(self, other):
|
|
277
|
+
"""Multiply two Unit objects.
|
|
278
|
+
|
|
279
|
+
The multiplication combines the exponents of matching units.
|
|
280
|
+
Units with zero exponents are dropped from the result.
|
|
281
|
+
|
|
282
|
+
Parameters
|
|
283
|
+
----------
|
|
284
|
+
other : tilupy.notations.Unit
|
|
285
|
+
Another :class:`tilupy.notations.Unit` object to multiply with.
|
|
286
|
+
|
|
287
|
+
Returns
|
|
288
|
+
-------
|
|
289
|
+
tilupy.notations.Unit
|
|
290
|
+
A new Unit object representing the product of the two units.
|
|
291
|
+
"""
|
|
292
|
+
tmp = self.add(other, fill_value=0)
|
|
293
|
+
return Unit(tmp[tmp != 0])
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def get_label(self):
|
|
297
|
+
"""Generate a LaTeX-formatted string representation of the unit.
|
|
298
|
+
|
|
299
|
+
The label combines positive and negative exponents, omitting exponents of 1.
|
|
300
|
+
Positive exponents are written as superscripts, while negative exponents
|
|
301
|
+
are enclosed in curly braces (for LaTeX compatibility).
|
|
302
|
+
|
|
303
|
+
Returns
|
|
304
|
+
-------
|
|
305
|
+
str
|
|
306
|
+
A LaTeX-formatted string representing the unit (e.g., "kg m s$^{-2}$").
|
|
307
|
+
Returns an empty string if the Unit object is empty.
|
|
308
|
+
"""
|
|
309
|
+
if self.empty:
|
|
310
|
+
return ""
|
|
311
|
+
|
|
312
|
+
positives = self[self >= 1].reindex(Unit.UNITS).dropna()
|
|
313
|
+
negatives = self[self < 0].reindex(Unit.UNITS).dropna()
|
|
314
|
+
text_label = [
|
|
315
|
+
index + "$^{:.0f}$".format(positives[index])
|
|
316
|
+
for index in positives.index
|
|
317
|
+
]
|
|
318
|
+
text_label += [
|
|
319
|
+
index + "$^{{{:.0f}}}$".format(negatives[index])
|
|
320
|
+
for index in negatives.index
|
|
321
|
+
]
|
|
322
|
+
text_label = " ".join(text_label)
|
|
323
|
+
text_label = text_label.replace("$^1$", "")
|
|
324
|
+
|
|
325
|
+
return text_label
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
class LongName(object):
|
|
329
|
+
"""Generic container class to dynamically store LongName attributes as key-value pairs.
|
|
330
|
+
|
|
331
|
+
This class allows the creation of objects with arbitrary attributes,
|
|
332
|
+
which are passed as keyword arguments during initialization.
|
|
333
|
+
|
|
334
|
+
Parameters
|
|
335
|
+
----------
|
|
336
|
+
**kwargs : dict
|
|
337
|
+
Arbitrary keyword arguments. Each key-value pair is added as an attribute to
|
|
338
|
+
the object.
|
|
339
|
+
"""
|
|
340
|
+
def __init__(self, **kwargs):
|
|
341
|
+
self.__dict__.update(kwargs)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
class Gender(object):
|
|
345
|
+
"""Generic container class to dynamically store Gender attributes as key-value pairs.
|
|
346
|
+
|
|
347
|
+
This class allows the creation of objects with arbitrary attributes,
|
|
348
|
+
which are passed as keyword arguments during initialization.
|
|
349
|
+
|
|
350
|
+
Parameters
|
|
351
|
+
----------
|
|
352
|
+
**kwargs : dict
|
|
353
|
+
Arbitrary keyword arguments. Each key-value pair is added as an attribute to
|
|
354
|
+
the object.
|
|
355
|
+
"""
|
|
356
|
+
def __init__(self, **kwargs):
|
|
357
|
+
self.__dict__.update(kwargs)
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
NOTATIONS = dict()
|
|
361
|
+
"""Dictionary containing predefined notations.
|
|
362
|
+
|
|
363
|
+
Pre-made notations:
|
|
364
|
+
|
|
365
|
+
- x [m]
|
|
366
|
+
- y [m]
|
|
367
|
+
- d [m]
|
|
368
|
+
- z [m]
|
|
369
|
+
- t [s]
|
|
370
|
+
- xy [m2]
|
|
371
|
+
- h [m]
|
|
372
|
+
- hvert [m]
|
|
373
|
+
- u [m1.s-1]
|
|
374
|
+
- hu [m2.s-1]
|
|
375
|
+
- ek [J]
|
|
376
|
+
|
|
377
|
+
Also some operators:
|
|
378
|
+
|
|
379
|
+
- max
|
|
380
|
+
- int
|
|
381
|
+
"""
|
|
382
|
+
|
|
383
|
+
NOTATIONS["x"] = Notation("x",
|
|
384
|
+
symbol="X",
|
|
385
|
+
unit=Unit(m=1),
|
|
386
|
+
long_name=LongName(english="X",
|
|
387
|
+
french="X"),
|
|
388
|
+
gender=Gender(english=None,
|
|
389
|
+
french="f"),
|
|
390
|
+
)
|
|
391
|
+
NOTATIONS["y"] = Notation("y",
|
|
392
|
+
symbol="Y",
|
|
393
|
+
unit=Unit(m=1),
|
|
394
|
+
long_name=LongName(english="Y",
|
|
395
|
+
french="Y"),
|
|
396
|
+
gender=Gender(english=None,
|
|
397
|
+
french="f"),
|
|
398
|
+
)
|
|
399
|
+
NOTATIONS["d"] = Notation("d",
|
|
400
|
+
symbol="D",
|
|
401
|
+
unit=Unit(m=1),
|
|
402
|
+
long_name=LongName(english="Distance",
|
|
403
|
+
french="Distance"),
|
|
404
|
+
gender=Gender(english=None,
|
|
405
|
+
french="f"),
|
|
406
|
+
)
|
|
407
|
+
NOTATIONS["z"] = Notation("z",
|
|
408
|
+
symbol="z",
|
|
409
|
+
unit=Unit(m=1),
|
|
410
|
+
long_name=LongName(english="Altitude",
|
|
411
|
+
french="Altitude"),
|
|
412
|
+
gender=Gender(english=None,
|
|
413
|
+
french="f"),
|
|
414
|
+
)
|
|
415
|
+
NOTATIONS["t"] = Notation("t",
|
|
416
|
+
symbol="t",
|
|
417
|
+
unit=Unit(s=1),
|
|
418
|
+
long_name=LongName(english="Time",
|
|
419
|
+
french="Temps"),
|
|
420
|
+
gender=Gender(english=None,
|
|
421
|
+
french="m"),
|
|
422
|
+
)
|
|
423
|
+
NOTATIONS["xy"] = Notation("xy",
|
|
424
|
+
symbol="XY",
|
|
425
|
+
unit=Unit(m=2),
|
|
426
|
+
long_name=LongName(english="Surface",
|
|
427
|
+
french="Surface"),
|
|
428
|
+
gender=Gender(english=None,
|
|
429
|
+
french="f"),
|
|
430
|
+
)
|
|
431
|
+
NOTATIONS["h"] = Notation("h",
|
|
432
|
+
symbol="h",
|
|
433
|
+
unit=Unit(m=1),
|
|
434
|
+
long_name=LongName(english="Thickness",
|
|
435
|
+
french="Epaisseur"),
|
|
436
|
+
gender=Gender(english=None,
|
|
437
|
+
french="f"),
|
|
438
|
+
)
|
|
439
|
+
NOTATIONS["hvert"] = Notation("hvert",
|
|
440
|
+
symbol="h^v",
|
|
441
|
+
unit=Unit(m=1),
|
|
442
|
+
long_name=LongName(english="Vertical thickness",
|
|
443
|
+
french="Epaisseur verticale"),
|
|
444
|
+
gender=Gender(english=None,
|
|
445
|
+
french="f"),
|
|
446
|
+
)
|
|
447
|
+
NOTATIONS["u"] = Notation("u",
|
|
448
|
+
symbol="u",
|
|
449
|
+
unit=Unit(m=1, s=-1),
|
|
450
|
+
long_name=LongName(english="Velocity",
|
|
451
|
+
french="Vitesse"),
|
|
452
|
+
gender=Gender(english=None,
|
|
453
|
+
french="f"),
|
|
454
|
+
)
|
|
455
|
+
NOTATIONS["hu"] = Notation("hu",
|
|
456
|
+
symbol="hu",
|
|
457
|
+
unit=Unit(m=2, s=-1),
|
|
458
|
+
long_name=LongName(english="Momentum",
|
|
459
|
+
french="Moment"),
|
|
460
|
+
gender=Gender(english=None,
|
|
461
|
+
french="m"),
|
|
462
|
+
)
|
|
463
|
+
NOTATIONS["hu2"] = Notation("hu2",
|
|
464
|
+
symbol="hu2",
|
|
465
|
+
unit=Unit(m=3, s=-2),
|
|
466
|
+
long_name=None,
|
|
467
|
+
gender=None,
|
|
468
|
+
)
|
|
469
|
+
NOTATIONS["ek"] = Notation("ek",
|
|
470
|
+
symbol="ek",
|
|
471
|
+
unit=Unit(J=1),
|
|
472
|
+
long_name=LongName(english="Kinetic energy",
|
|
473
|
+
french="Energie cinétique"),
|
|
474
|
+
gender=Gender(english=None,
|
|
475
|
+
french="f"),
|
|
476
|
+
)
|
|
477
|
+
|
|
478
|
+
NOTATIONS["max"] = Notation("max",
|
|
479
|
+
symbol="max",
|
|
480
|
+
unit=None,
|
|
481
|
+
long_name=LongName(english="Maximum",
|
|
482
|
+
french=dict(m="Maximum", f="Maximale")),
|
|
483
|
+
gender=None,
|
|
484
|
+
)
|
|
485
|
+
NOTATIONS["int"] = Notation("int",
|
|
486
|
+
symbol="int",
|
|
487
|
+
unit=None,
|
|
488
|
+
long_name=LongName(english="Integrate",
|
|
489
|
+
french=dict(m="Intégré", f="Intégrée")),
|
|
490
|
+
gender=None,
|
|
491
|
+
)
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def get_notation(name: str,
|
|
495
|
+
language: str = None
|
|
496
|
+
) -> tilupy.notations.Notation:
|
|
497
|
+
"""Retrieve or construct a Notation object for a given name.
|
|
498
|
+
|
|
499
|
+
This function attempts to fetch a predefined notation from the global :data:`tilupy.notations.NOTATIONS`
|
|
500
|
+
dictionary. If the notation is not found, it constructs a new :class:`tilupy.notations.Notation` object
|
|
501
|
+
based on the provided name. For composite names (e.g., "state_operator"), it recursively resolves the
|
|
502
|
+
state and operator, then combines them using :func:`tilupy.notations.add_operator`.
|
|
503
|
+
|
|
504
|
+
Parameters
|
|
505
|
+
----------
|
|
506
|
+
name : str
|
|
507
|
+
The name of the notation to retrieve or construct.
|
|
508
|
+
Can be a simple name (e.g., "velocity") or a composite name (e.g., "velocity_int_t").
|
|
509
|
+
language : str, optional
|
|
510
|
+
The language to use for the long name of the notation. If not provided, the default language from `LABEL_OPTIONS` is used.
|
|
511
|
+
|
|
512
|
+
Returns
|
|
513
|
+
-------
|
|
514
|
+
tilupy.notations.Notation
|
|
515
|
+
The retrieved or constructed :class:`tilupy.notations.Notation` object.
|
|
516
|
+
"""
|
|
517
|
+
try:
|
|
518
|
+
notation = NOTATIONS[name]
|
|
519
|
+
except KeyError:
|
|
520
|
+
strings = name.split("_")
|
|
521
|
+
if len(strings) == 1:
|
|
522
|
+
notation = Notation(name,
|
|
523
|
+
symbol=name,
|
|
524
|
+
unit=None,
|
|
525
|
+
long_name=name,
|
|
526
|
+
gender=None)
|
|
527
|
+
else:
|
|
528
|
+
state = get_notation(strings[0])
|
|
529
|
+
operator = get_notation(strings[1])
|
|
530
|
+
if len(strings) == 3:
|
|
531
|
+
axis = strings[2]
|
|
532
|
+
else:
|
|
533
|
+
axis = None
|
|
534
|
+
notation = add_operator(state,
|
|
535
|
+
operator,
|
|
536
|
+
axis=axis,
|
|
537
|
+
language=language)
|
|
538
|
+
|
|
539
|
+
return notation
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
def get_operator_unit(name: str,
|
|
543
|
+
axis: str
|
|
544
|
+
) -> tilupy.notations.Unit:
|
|
545
|
+
"""Determine the unit associated with an operator based on its name and axis.
|
|
546
|
+
|
|
547
|
+
This function returns a :class:`tilupy.notations.Unit` object corresponding to the operator's
|
|
548
|
+
name and the axis it operates on. For example, an integral operator ("int") has different units
|
|
549
|
+
depending on whether it integrates over time ("t") or space ("x", "y", "xy").
|
|
550
|
+
|
|
551
|
+
Parameters
|
|
552
|
+
----------
|
|
553
|
+
name : str
|
|
554
|
+
The name of the operator (e.g., "int").
|
|
555
|
+
axis : str or None
|
|
556
|
+
The axis over which the operator acts (e.g., "t", "x", "y", "xy").
|
|
557
|
+
If None, the default axis is used (e.g., "t" for "int").
|
|
558
|
+
|
|
559
|
+
Returns
|
|
560
|
+
-------
|
|
561
|
+
tilupy.notations.Unit
|
|
562
|
+
The unit associated with the operator and axis.
|
|
563
|
+
"""
|
|
564
|
+
if name == "int":
|
|
565
|
+
if axis == "t" or axis is None:
|
|
566
|
+
unit = Unit(s=1)
|
|
567
|
+
if axis in ["x", "y"]:
|
|
568
|
+
unit = Unit(m=1)
|
|
569
|
+
if axis == "xy":
|
|
570
|
+
unit = Unit(m=2)
|
|
571
|
+
else:
|
|
572
|
+
unit = Unit(pd.Series(dtype="object"))
|
|
573
|
+
return unit
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
def make_long_name(notation: tilupy.notations.Notation,
|
|
577
|
+
operator: tilupy.notations.Notation,
|
|
578
|
+
language: str = None
|
|
579
|
+
) -> str:
|
|
580
|
+
"""Construct a long name for a notation combined with an operator.
|
|
581
|
+
|
|
582
|
+
This function generates a readable long name by combining the long names of a notation and an operator.
|
|
583
|
+
It can be written in French or English.
|
|
584
|
+
|
|
585
|
+
Parameters
|
|
586
|
+
----------
|
|
587
|
+
notation : tilupy.notations.Notation
|
|
588
|
+
The base notation object.
|
|
589
|
+
operator : tilupy.notations.Notation
|
|
590
|
+
The operator notation object.
|
|
591
|
+
language : str, optional
|
|
592
|
+
The language to use for the long name. If not provided, the default language from
|
|
593
|
+
:data:`tilupy.notations.LABEL_OPTIONS` is used. By default None.
|
|
594
|
+
|
|
595
|
+
Returns
|
|
596
|
+
-------
|
|
597
|
+
str
|
|
598
|
+
The combined long name in the specified language.
|
|
599
|
+
"""
|
|
600
|
+
if language is None:
|
|
601
|
+
language = LABEL_OPTIONS["language"]
|
|
602
|
+
|
|
603
|
+
str_notation = notation.get_long_name(language=language)
|
|
604
|
+
try:
|
|
605
|
+
gender = gender = getattr(notation.gender, language)
|
|
606
|
+
except AttributeError:
|
|
607
|
+
gender = None
|
|
608
|
+
str_operator = operator.get_long_name(language=language, gender=gender)
|
|
609
|
+
|
|
610
|
+
if language == "english":
|
|
611
|
+
res = str_operator + " " + str_notation
|
|
612
|
+
elif language == "french":
|
|
613
|
+
res = str_notation + " " + str_operator
|
|
614
|
+
|
|
615
|
+
return res
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
def add_operator(notation: tilupy.notations.Notation | str,
|
|
619
|
+
operator: tilupy.notations.Notation | str,
|
|
620
|
+
axis: str = None,
|
|
621
|
+
language: str = None
|
|
622
|
+
) -> tilupy.notations.Notation:
|
|
623
|
+
"""Combine a notation with an operator to create a new notation.
|
|
624
|
+
|
|
625
|
+
This function constructs a new :class:`tilupy.notations.Notation` object by combining
|
|
626
|
+
a base notation with an operator. It handles the symbol, unit, and long name of the
|
|
627
|
+
resulting notation, taking into account the operator's axis (if any).
|
|
628
|
+
|
|
629
|
+
Parameters
|
|
630
|
+
----------
|
|
631
|
+
notation : tilupy.notations.Notation or str
|
|
632
|
+
The base notation object or its name.
|
|
633
|
+
operator : tilupy.notations.Notation or str
|
|
634
|
+
The operator notation object or its name.
|
|
635
|
+
axis : str, optional
|
|
636
|
+
The axis over which the operator acts (e.g., "t", "x", "y"). By default None.
|
|
637
|
+
language : str, optional
|
|
638
|
+
The language to use for the long name. If not provided, the default language from
|
|
639
|
+
:data:`tilupy.notations.LABEL_OPTIONS` is used. By default None.
|
|
640
|
+
|
|
641
|
+
Returns
|
|
642
|
+
-------
|
|
643
|
+
tilupy.notations.Notation
|
|
644
|
+
The new Notation object resulting from the combination of the base notation and the operator.
|
|
645
|
+
"""
|
|
646
|
+
if isinstance(operator, str):
|
|
647
|
+
operator = get_notation(operator)
|
|
648
|
+
|
|
649
|
+
if isinstance(notation, str):
|
|
650
|
+
notation = get_notation(notation)
|
|
651
|
+
|
|
652
|
+
operator_symbol = operator.symbol
|
|
653
|
+
if axis is not None:
|
|
654
|
+
operator_symbol += "({})".format(axis)
|
|
655
|
+
|
|
656
|
+
unit_operator = get_operator_unit(operator.name, axis)
|
|
657
|
+
|
|
658
|
+
if operator.name == "int":
|
|
659
|
+
if axis is None:
|
|
660
|
+
ll = "t" # If axis is not specified by default integration is over time
|
|
661
|
+
else:
|
|
662
|
+
ll = axis
|
|
663
|
+
symbol = "\\int_{{{}}} {}".format(ll, notation.symbol)
|
|
664
|
+
else:
|
|
665
|
+
operator_symbol = operator.symbol
|
|
666
|
+
if axis is not None:
|
|
667
|
+
operator_symbol += "({})".format(axis)
|
|
668
|
+
symbol = notation.symbol + "_{{{}}}".format(operator_symbol)
|
|
669
|
+
|
|
670
|
+
if notation.unit is None:
|
|
671
|
+
unit = None
|
|
672
|
+
else:
|
|
673
|
+
unit = notation.unit * unit_operator
|
|
674
|
+
|
|
675
|
+
res = Notation(name=notation.name + "_" + operator.name,
|
|
676
|
+
symbol=symbol,
|
|
677
|
+
unit=unit,
|
|
678
|
+
long_name=make_long_name(notation, operator, language=language),
|
|
679
|
+
)
|
|
680
|
+
return res
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
def get_label(notation: tilupy.notations.Notation,
|
|
684
|
+
with_unit: bool = True,
|
|
685
|
+
label_type: str = None,
|
|
686
|
+
language: str = None
|
|
687
|
+
) -> str:
|
|
688
|
+
"""Generate a formatted label for a notation.
|
|
689
|
+
|
|
690
|
+
This function creates a label for a notation, either in literal form (long name)
|
|
691
|
+
or symbolic form (symbol). It can optionally include the unit in the label.
|
|
692
|
+
|
|
693
|
+
Parameters
|
|
694
|
+
----------
|
|
695
|
+
notation : tilupy.notations.Notation or str
|
|
696
|
+
The notation object or its name.
|
|
697
|
+
with_unit : bool, optional
|
|
698
|
+
If True, the unit is included in the label. By default True.
|
|
699
|
+
label_type : str, optional
|
|
700
|
+
The type of label to generate: "litteral" (long name) or "symbol" (symbol).
|
|
701
|
+
If not provided, the default label type from :data:`tilupy.notations.LABEL_OPTIONS`
|
|
702
|
+
is used. By default None.
|
|
703
|
+
language : str, optional
|
|
704
|
+
The language to use for the label. If not provided, the default language from
|
|
705
|
+
:data:`tilupy.notations.LABEL_OPTIONS` is used.
|
|
706
|
+
By default None.
|
|
707
|
+
|
|
708
|
+
Returns
|
|
709
|
+
-------
|
|
710
|
+
str
|
|
711
|
+
The formatted label for the notation, optionally including the unit.
|
|
712
|
+
"""
|
|
713
|
+
if isinstance(notation, str):
|
|
714
|
+
notation = get_notation(notation)
|
|
715
|
+
|
|
716
|
+
if label_type is None:
|
|
717
|
+
label_type = LABEL_OPTIONS["label_type"]
|
|
718
|
+
if language is None:
|
|
719
|
+
language = LABEL_OPTIONS["language"]
|
|
720
|
+
|
|
721
|
+
if label_type == "litteral":
|
|
722
|
+
label = notation.get_long_name(language=language, gender=None)
|
|
723
|
+
elif label_type == "symbol":
|
|
724
|
+
label = "$" + notation.symbol + "$"
|
|
725
|
+
|
|
726
|
+
if with_unit and notation.unit is not None:
|
|
727
|
+
unit_string = notation.unit.get_label()
|
|
728
|
+
# Add unit only if string is not empty
|
|
729
|
+
if unit_string:
|
|
730
|
+
label = label + " ({})".format(unit_string)
|
|
731
|
+
|
|
732
|
+
return label
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
def set_label_options(**kwargs):
|
|
736
|
+
"""Update the global label options.
|
|
737
|
+
|
|
738
|
+
This function updates the global :data:`tilupy.notations.LABEL_OPTIONS` dictionary
|
|
739
|
+
with the provided keyword arguments. It allows dynamic configuration of label
|
|
740
|
+
generation settings, such as language and label type.
|
|
741
|
+
|
|
742
|
+
Parameters
|
|
743
|
+
----------
|
|
744
|
+
**kwargs : dict
|
|
745
|
+
Key-value pairs to update in :data:`tilupy.notations.LABEL_OPTIONS`.
|
|
746
|
+
Valid keys include "language" and "label_type".
|
|
747
|
+
"""
|
|
748
|
+
global LABEL_OPTIONS
|
|
749
|
+
LABEL_OPTIONS.update(**kwargs)
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
def readme_to_params(file: str,
|
|
753
|
+
readme_param_match: dict = None
|
|
754
|
+
) -> dict:
|
|
755
|
+
"""Convert a README file into a dictionary of parameters.
|
|
756
|
+
|
|
757
|
+
This function reads a README file and extracts key-value pairs, optionally using a mapping dictionary
|
|
758
|
+
to rename the keys. Each line in the file is expected to contain a key and a value separated by whitespace.
|
|
759
|
+
|
|
760
|
+
Parameters
|
|
761
|
+
----------
|
|
762
|
+
file : str
|
|
763
|
+
Path to the README file to read.
|
|
764
|
+
readme_param_match : dict, optional
|
|
765
|
+
A dictionary mapping keys in the README file to new keys in the output dictionary.
|
|
766
|
+
If not provided, the keys are used as-is. By default None.
|
|
767
|
+
|
|
768
|
+
Returns
|
|
769
|
+
-------
|
|
770
|
+
dict
|
|
771
|
+
A dictionary of parameters extracted from the README file.
|
|
772
|
+
"""
|
|
773
|
+
params = dict()
|
|
774
|
+
with open(file, "r") as f:
|
|
775
|
+
if readme_param_match is not None:
|
|
776
|
+
for line in f:
|
|
777
|
+
(key, val) = line.split()
|
|
778
|
+
if key in readme_param_match:
|
|
779
|
+
params[readme_param_match[key]] = val
|
|
780
|
+
else:
|
|
781
|
+
for line in f:
|
|
782
|
+
(key, val) = line.split()
|
|
783
|
+
params[key] = val
|
|
784
|
+
|
|
785
|
+
return params
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
def make_rheol_string_fmt(rheoldict: dict) -> str:
|
|
789
|
+
"""Generate a formatted string template for rheological parameters.
|
|
790
|
+
|
|
791
|
+
This function constructs a string template for rheological parameters based on the provided dictionary and rheological law.
|
|
792
|
+
The template includes placeholders for parameter values, which can later be formatted with specific values.
|
|
793
|
+
|
|
794
|
+
Parameters
|
|
795
|
+
----------
|
|
796
|
+
rheoldict : dict
|
|
797
|
+
A dictionary of rheological parameters (e.g., "delta1", "ksi").
|
|
798
|
+
|
|
799
|
+
Returns
|
|
800
|
+
-------
|
|
801
|
+
str
|
|
802
|
+
A formatted string template for the rheological parameters.
|
|
803
|
+
"""
|
|
804
|
+
text = ""
|
|
805
|
+
for name in ["delta1", "delta2", "delta3", "delta4"]:
|
|
806
|
+
if name in rheoldict:
|
|
807
|
+
new_txt = name + "_{:05.2f}_"
|
|
808
|
+
text += new_txt
|
|
809
|
+
if "ksi" in rheoldict:
|
|
810
|
+
new_txt = name + "ksi_{:06.1f}_"
|
|
811
|
+
text += new_txt
|
|
812
|
+
text = text[:-1]
|
|
813
|
+
|
|
814
|
+
return text
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
def make_rheol_string(rheoldict: dict,
|
|
818
|
+
law: str
|
|
819
|
+
) -> str | list[str]:
|
|
820
|
+
"""Generate formatted strings for rheological parameters.
|
|
821
|
+
|
|
822
|
+
This function creates formatted strings for rheological parameters based on the provided dictionary and rheological law.
|
|
823
|
+
It handles multiple parameter sets (e.g., for different time steps or conditions) and formats each set according to the specified law.
|
|
824
|
+
|
|
825
|
+
Parameters
|
|
826
|
+
----------
|
|
827
|
+
rheoldict : dict
|
|
828
|
+
A dictionary of rheological parameters. Values can be lists of parameters for multiple sets.
|
|
829
|
+
law : str
|
|
830
|
+
The rheological law to use. Can be "coulomb", "voellmy" or "pouliquen_2002".
|
|
831
|
+
|
|
832
|
+
Returns
|
|
833
|
+
-------
|
|
834
|
+
str or list[str]
|
|
835
|
+
The formatted string(s) for the rheological parameters.
|
|
836
|
+
If there is only one parameter set, a single string is returned. Otherwise, a list of strings is returned.
|
|
837
|
+
"""
|
|
838
|
+
keys = [key for key in rheoldict]
|
|
839
|
+
for key in keys:
|
|
840
|
+
if not isinstance(rheoldict[key], list):
|
|
841
|
+
rheoldict[key] = [rheoldict[key]]
|
|
842
|
+
|
|
843
|
+
nparams = len(rheoldict[keys[0]])
|
|
844
|
+
txt_fmt = make_rheol_string_fmt(rheoldict)
|
|
845
|
+
texts = []
|
|
846
|
+
|
|
847
|
+
for i in range(nparams):
|
|
848
|
+
if law == "coulomb":
|
|
849
|
+
txt_fmt = "delta1_{:05.2f}"
|
|
850
|
+
text = txt_fmt.format(rheoldict["delta1"][i]).replace(".", "p")
|
|
851
|
+
if law == "voellmy":
|
|
852
|
+
txt_fmt = "delta1_{:05.2f}_ksi_{:06.1f}"
|
|
853
|
+
text = txt_fmt.format(
|
|
854
|
+
rheoldict["delta1"][i], rheoldict["ksi"][i]
|
|
855
|
+
).replace(".", "p")
|
|
856
|
+
if law == "pouliquen_2002":
|
|
857
|
+
txt_fmt = "delta1_{:05.2f}_L_{:05.2f}"
|
|
858
|
+
text = txt_fmt.format(
|
|
859
|
+
rheoldict["delta1"][i], rheoldict["wlong"][i]
|
|
860
|
+
).replace(".", "p")
|
|
861
|
+
texts.append(text)
|
|
862
|
+
|
|
863
|
+
if nparams == 1:
|
|
864
|
+
texts = texts[0]
|
|
865
|
+
|
|
866
|
+
return texts
|