floodmodeller-api 0.4.4.post1__py3-none-any.whl → 0.5.0.post1__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.
Files changed (67) hide show
  1. floodmodeller_api/__init__.py +1 -0
  2. floodmodeller_api/dat.py +117 -96
  3. floodmodeller_api/hydrology_plus/__init__.py +2 -0
  4. floodmodeller_api/hydrology_plus/helper.py +23 -0
  5. floodmodeller_api/hydrology_plus/hydrology_plus_export.py +333 -0
  6. floodmodeller_api/ied.py +93 -90
  7. floodmodeller_api/ief.py +233 -50
  8. floodmodeller_api/ief_flags.py +1 -0
  9. floodmodeller_api/logs/lf.py +5 -1
  10. floodmodeller_api/mapping.py +2 -0
  11. floodmodeller_api/test/test_conveyance.py +23 -32
  12. floodmodeller_api/test/test_data/7082.ief +28 -0
  13. floodmodeller_api/test/test_data/BaseModel_2D_Q100.ief +28 -0
  14. floodmodeller_api/test/test_data/Baseline_unchecked.csv +77 -0
  15. floodmodeller_api/test/test_data/Constant QT.ief +19 -0
  16. floodmodeller_api/test/test_data/Domain1_Q_xml_expected.json +7 -7
  17. floodmodeller_api/test/test_data/EX18_DAT_expected.json +54 -38
  18. floodmodeller_api/test/test_data/EX3_DAT_expected.json +246 -166
  19. floodmodeller_api/test/test_data/EX3_IEF_expected.json +25 -20
  20. floodmodeller_api/test/test_data/EX6_DAT_expected.json +522 -350
  21. floodmodeller_api/test/test_data/FEH boundary.ief +23 -0
  22. floodmodeller_api/test/test_data/Linked1D2D_xml_expected.json +7 -7
  23. floodmodeller_api/test/test_data/P3Panels_UNsteady.ief +25 -0
  24. floodmodeller_api/test/test_data/QT in dat file.ief +20 -0
  25. floodmodeller_api/test/test_data/T10.ief +25 -0
  26. floodmodeller_api/test/test_data/T2.ief +25 -0
  27. floodmodeller_api/test/test_data/T5.ief +25 -0
  28. floodmodeller_api/test/test_data/df_flows_hplus.csv +56 -0
  29. floodmodeller_api/test/test_data/event_hplus.csv +56 -0
  30. floodmodeller_api/test/test_data/ex4.ief +20 -0
  31. floodmodeller_api/test/test_data/ex6.ief +21 -0
  32. floodmodeller_api/test/test_data/example_h+_export.csv +77 -0
  33. floodmodeller_api/test/test_data/hplus_export_example_1.csv +72 -0
  34. floodmodeller_api/test/test_data/hplus_export_example_10.csv +77 -0
  35. floodmodeller_api/test/test_data/hplus_export_example_2.csv +79 -0
  36. floodmodeller_api/test/test_data/hplus_export_example_3.csv +77 -0
  37. floodmodeller_api/test/test_data/hplus_export_example_4.csv +131 -0
  38. floodmodeller_api/test/test_data/hplus_export_example_5.csv +77 -0
  39. floodmodeller_api/test/test_data/hplus_export_example_6.csv +131 -0
  40. floodmodeller_api/test/test_data/hplus_export_example_7.csv +131 -0
  41. floodmodeller_api/test/test_data/hplus_export_example_8.csv +131 -0
  42. floodmodeller_api/test/test_data/hplus_export_example_9.csv +131 -0
  43. floodmodeller_api/test/test_data/network_dat_expected.json +312 -210
  44. floodmodeller_api/test/test_data/network_ied_expected.json +6 -6
  45. floodmodeller_api/test/test_data/network_with_comments.ied +55 -0
  46. floodmodeller_api/test/test_flowtimeprofile.py +133 -0
  47. floodmodeller_api/test/test_hydrology_plus_export.py +210 -0
  48. floodmodeller_api/test/test_ied.py +12 -0
  49. floodmodeller_api/test/test_ief.py +49 -9
  50. floodmodeller_api/test/test_json.py +6 -1
  51. floodmodeller_api/test/test_read_file.py +27 -0
  52. floodmodeller_api/test/test_river.py +246 -0
  53. floodmodeller_api/to_from_json.py +7 -1
  54. floodmodeller_api/tool.py +6 -10
  55. floodmodeller_api/units/__init__.py +11 -1
  56. floodmodeller_api/units/conveyance.py +103 -212
  57. floodmodeller_api/units/sections.py +120 -39
  58. floodmodeller_api/util.py +2 -0
  59. floodmodeller_api/version.py +1 -1
  60. floodmodeller_api/xml2d.py +20 -13
  61. floodmodeller_api/xsd_backup.xml +738 -0
  62. {floodmodeller_api-0.4.4.post1.dist-info → floodmodeller_api-0.5.0.post1.dist-info}/METADATA +2 -1
  63. {floodmodeller_api-0.4.4.post1.dist-info → floodmodeller_api-0.5.0.post1.dist-info}/RECORD +67 -33
  64. {floodmodeller_api-0.4.4.post1.dist-info → floodmodeller_api-0.5.0.post1.dist-info}/WHEEL +1 -1
  65. {floodmodeller_api-0.4.4.post1.dist-info → floodmodeller_api-0.5.0.post1.dist-info}/LICENSE.txt +0 -0
  66. {floodmodeller_api-0.4.4.post1.dist-info → floodmodeller_api-0.5.0.post1.dist-info}/entry_points.txt +0 -0
  67. {floodmodeller_api-0.4.4.post1.dist-info → floodmodeller_api-0.5.0.post1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,246 @@
1
+ import pandas as pd
2
+ import pytest
3
+
4
+ from floodmodeller_api.units.sections import RIVER
5
+
6
+ river_unit_data_cases = [
7
+ (
8
+ [
9
+ "RIVER normal case",
10
+ "SECTION",
11
+ "SomeUnit",
12
+ " 0.000 0.000100 1000.000",
13
+ " 5",
14
+ " 0.000 10 0.030 0.000 0.0 0.0 ",
15
+ " 1.000 9 0.030 0.000 0.0 0.0 LEFT",
16
+ " 2.000 5 0.030 0.000 0.0 0.0 ",
17
+ " 3.000 6 0.030 0.000 0.0 0.0 RIGHT",
18
+ " 4.000 10 0.030 0.000 0.0 0.0 ",
19
+ ],
20
+ 3,
21
+ ),
22
+ (
23
+ [
24
+ "RIVER close together",
25
+ "SECTION",
26
+ "AnotherUnit",
27
+ " 0.000 0.000100 1000.000",
28
+ " 3",
29
+ " 0.000 15 0.040 0.000 0.0 0.0 ",
30
+ " 1.500 8 0.040 0.000 0.0 0.0 LEFT",
31
+ " 3.000 12 0.040 0.000 0.0 0.0 RIGHT",
32
+ ],
33
+ 2,
34
+ ),
35
+ (
36
+ [
37
+ "RIVER double markers",
38
+ "SECTION",
39
+ "AnotherUnit",
40
+ " 0.000 0.000100 1000.000",
41
+ " 3",
42
+ " 0.000 15 0.040 0.000 0.0 0.0 ",
43
+ " 1.500 8 0.040 0.000 0.0 0.0 LEFT",
44
+ " 3.000 12 0.040 0.000 0.0 0.0 ",
45
+ " 4.000 13 0.040 0.000 0.0 0.0 LEFT",
46
+ " 5.000 2 0.040 0.000 0.0 0.0 ",
47
+ " 6.000 1 0.040 0.000 0.0 0.0 ",
48
+ " 7.000 254 0.040 0.000 0.0 0.0 RIGHT",
49
+ " 8.000 21 0.040 0.000 0.0 0.0 ",
50
+ " 9.000 76 0.040 0.000 0.0 0.0 RIGHT",
51
+ ],
52
+ 4,
53
+ ),
54
+ ]
55
+
56
+
57
+ @pytest.mark.parametrize(("river_unit_data", "_"), river_unit_data_cases)
58
+ def test_read_write(river_unit_data, _):
59
+ river_section_1 = RIVER(river_unit_data)
60
+ river_section_2 = RIVER(river_section_1._write())
61
+ assert river_section_1 == river_section_2
62
+
63
+
64
+ @pytest.mark.parametrize(("river_unit_data", "expected_len"), river_unit_data_cases)
65
+ def test_river_active_data(river_unit_data, expected_len):
66
+ river_section = RIVER(river_unit_data)
67
+ active_data = river_section.active_data
68
+
69
+ assert len(active_data) == expected_len
70
+ assert active_data.iloc[0].Deactivation == "LEFT"
71
+ assert active_data.iloc[-1].Deactivation == "RIGHT"
72
+ assert "LEFT" not in active_data.iloc[1:-1].Deactivation.to_list()
73
+ assert "RIGHT" not in active_data.iloc[1:-1].Deactivation.to_list()
74
+
75
+
76
+ def test_edit_active_data():
77
+ unit = RIVER(
78
+ [
79
+ "RIVER normal case",
80
+ "SECTION",
81
+ "SomeUnit",
82
+ " 0.000 0.000100 1000.000",
83
+ " 5",
84
+ " 0.000 10 0.030 0.000 0.0 0.0 ",
85
+ " 1.000 9 0.030 0.000 0.0 0.0 LEFT",
86
+ " 2.000 5 0.030 0.000 0.0 0.0 ",
87
+ " 3.000 6 0.030 0.000 0.0 0.0 RIGHT",
88
+ " 4.000 10 0.030 0.000 0.0 0.0 ",
89
+ ],
90
+ )
91
+ unit.active_data.iloc[0, 1] = 99
92
+ assert unit.data.iloc[1, 1] == 99
93
+ expected_row = "1.000 99.000 0.030 0.000 0.000 0.000 LEFT"
94
+ assert expected_row in str(unit)
95
+
96
+
97
+ def test_active_data_with_no_markers():
98
+ unit = RIVER(
99
+ [
100
+ "RIVER normal case",
101
+ "SECTION",
102
+ "SomeUnit",
103
+ " 0.000 0.000100 1000.000",
104
+ " 5",
105
+ " 0.000 10 0.030",
106
+ " 1.000 9 0.030",
107
+ " 2.000 5 0.030",
108
+ " 3.000 6 0.030",
109
+ " 4.000 10 0.030",
110
+ ],
111
+ )
112
+ assert len(unit.active_data) == 5
113
+ unit.data.iloc[1, 8] = "LEFT"
114
+ unit.data.iloc[3, 8] = "RIGHT"
115
+ assert len(unit.active_data) == 3
116
+
117
+
118
+ def test_create_from_blank():
119
+ blank_unit = RIVER()
120
+ assert len(blank_unit.data) == 0
121
+ assert len(blank_unit.active_data) == 0
122
+ assert blank_unit._write() == [
123
+ "RIVER ",
124
+ "SECTION",
125
+ "new_section ",
126
+ " 0.000 0.000100 1000.000",
127
+ " 0",
128
+ ]
129
+
130
+
131
+ def test_create_from_blank_with_params():
132
+ unit = RIVER(
133
+ name="for_test",
134
+ comment="testing",
135
+ spill1="t",
136
+ spill2="e",
137
+ lat1="s",
138
+ lat2="t",
139
+ lat3="i",
140
+ lat4="ng",
141
+ dist_to_next=55,
142
+ slope=0.00015,
143
+ density=1010.0,
144
+ data=pd.DataFrame(
145
+ {
146
+ "X": [0.0, 1.0, 2.0],
147
+ "Y": [5.0, 2.0, 5.0],
148
+ "Mannings n": [0.01, 0.01, 0.01],
149
+ "Panel": ["", "", ""],
150
+ "RPL": [0.0, 0.0, 0.0],
151
+ "Marker": ["", "", ""],
152
+ "Easting": [0.0, 0.0, 0.0],
153
+ "Northing": [0.0, 0.0, 0.0],
154
+ "Deactivation": ["", "", ""],
155
+ "SP. Marker": ["", "", ""],
156
+ },
157
+ ),
158
+ )
159
+
160
+ assert unit._write() == [
161
+ "RIVER testing",
162
+ "SECTION",
163
+ "for_test t e s t i ng ",
164
+ " 55.000 0.000150 1010.000",
165
+ " 3",
166
+ " 0.000 5.000 0.010 0.000 0.000 0.000 ",
167
+ " 1.000 2.000 0.010 0.000 0.000 0.000 ",
168
+ " 2.000 5.000 0.010 0.000 0.000 0.000 ",
169
+ ]
170
+
171
+
172
+ def test_set_river_dataframe_correct():
173
+ unit = RIVER(
174
+ [
175
+ "RIVER normal case",
176
+ "SECTION",
177
+ "SomeUnit",
178
+ " 0.000 0.000100 1000.000",
179
+ " 5",
180
+ " 0.000 10 0.030",
181
+ " 1.000 9 0.030",
182
+ " 2.000 5 0.030",
183
+ " 3.000 6 0.030",
184
+ " 4.000 10 0.030",
185
+ ],
186
+ )
187
+
188
+ df = pd.DataFrame(
189
+ {
190
+ "X": [0.0, 1.0, 2.0],
191
+ "Y": [5.0, 2.0, 5.0],
192
+ "Mannings n": [0.01, 0.01, 0.01],
193
+ "Panel": ["", "", ""],
194
+ "RPL": [0.0, 0.0, 0.0],
195
+ "Marker": ["", "", ""],
196
+ "Easting": [0.0, 0.0, 0.0],
197
+ "Northing": [0.0, 0.0, 0.0],
198
+ "Deactivation": ["", "", ""],
199
+ "SP. Marker": ["", "", ""],
200
+ },
201
+ )
202
+
203
+ unit.data = df.copy()
204
+ pd.testing.assert_frame_equal(unit._data, df.copy())
205
+
206
+
207
+ def test_set_river_dataframe_incorrect():
208
+ unit = RIVER()
209
+
210
+ df = pd.DataFrame(
211
+ {
212
+ "X": [0.0, 1.0, 2.0],
213
+ "Y": [5.0, 2.0, 5.0],
214
+ "Mannings n": [0.01, 0.01, 0.01],
215
+ "RPL": [0.0, 0.0, 0.0],
216
+ "Marker": ["", "", ""],
217
+ "Easting": [0.0, 0.0, 0.0],
218
+ "Deactivation": ["", "", ""],
219
+ "SP. Marker": ["", "", ""],
220
+ },
221
+ )
222
+
223
+ with pytest.raises(ValueError):
224
+ unit.data = df.copy()
225
+
226
+
227
+ def test_set_river_dataframe_case_sensitivity():
228
+ unit = RIVER()
229
+
230
+ df = pd.DataFrame(
231
+ {
232
+ "x": [0.0, 1.0, 2.0],
233
+ "Y": [5.0, 2.0, 5.0],
234
+ "mANNINGs n": [0.01, 0.01, 0.01],
235
+ "Panel": ["", "", ""],
236
+ "RPL": [0.0, 0.0, 0.0],
237
+ "Marker": ["", "", ""],
238
+ "Easting": [0.0, 0.0, 0.0],
239
+ "Northing": [0.0, 0.0, 0.0],
240
+ "Deactivation": ["", "", ""],
241
+ "SP. Marker": ["", "", ""],
242
+ },
243
+ )
244
+
245
+ unit.data = df.copy()
246
+ pd.testing.assert_frame_equal(unit._data, df.copy())
@@ -77,6 +77,7 @@ def recursive_to_json(obj: Any, is_top_level: bool = True) -> Any: # noqa: PLR0
77
77
  """
78
78
  from ._base import FMFile
79
79
  from .backup import File
80
+ from .ief import FlowTimeProfile
80
81
  from .units import IIC
81
82
  from .units._base import Unit
82
83
  from .urban1d._base import UrbanSubsection, UrbanUnit
@@ -105,7 +106,10 @@ def recursive_to_json(obj: Any, is_top_level: bool = True) -> Any: # noqa: PLR0
105
106
  return {key: recursive_to_json(value, is_top_level=False) for key, value in obj.items()}
106
107
 
107
108
  # Either a type of FM API Class
108
- if isinstance(obj, (FMFile, Unit, IIC, File, UrbanSubsection, UrbanUnit)): # noqa: RET503
109
+ if isinstance(
110
+ obj,
111
+ (FMFile, Unit, IIC, File, UrbanSubsection, UrbanUnit, FlowTimeProfile),
112
+ ):
109
113
  # Information from the flood modeller object will be included in the JSON output
110
114
  # slicing undertaken to remove quotation marks
111
115
  return_dict: dict[str, Any] = {"API Class": str(obj.__class__)[8:-2]}
@@ -118,6 +122,8 @@ def recursive_to_json(obj: Any, is_top_level: bool = True) -> Any: # noqa: PLR0
118
122
 
119
123
  return return_dict
120
124
 
125
+ return None
126
+
121
127
 
122
128
  def from_json(obj: str | dict) -> dict:
123
129
  """
floodmodeller_api/tool.py CHANGED
@@ -54,9 +54,7 @@ def validate_int(value):
54
54
  """
55
55
  if value.isdigit():
56
56
  return True
57
- if value == "":
58
- return True
59
- return False
57
+ return value == ""
60
58
 
61
59
 
62
60
  def validate_float(value):
@@ -72,9 +70,7 @@ def validate_float(value):
72
70
  float(value)
73
71
  return True
74
72
  except ValueError:
75
- if value == "":
76
- return True
77
- return False
73
+ return value == ""
78
74
 
79
75
 
80
76
  class Gui:
@@ -92,7 +88,7 @@ class Gui:
92
88
 
93
89
  """
94
90
 
95
- def __init__( # noqa: PLR0913
91
+ def __init__(
96
92
  self,
97
93
  master: tk.Tk,
98
94
  title: str,
@@ -145,12 +141,12 @@ class Gui:
145
141
  label.pack()
146
142
  # Conditional stuff to add validation for different data types.
147
143
  # This ensures that you can't enter text if the input should be a number, etc.
148
- if data_type == str:
144
+ if data_type is str:
149
145
  entry = tk.Entry(self.master)
150
- elif data_type == int:
146
+ elif data_type is int:
151
147
  entry = tk.Entry(self.master, validate="key")
152
148
  entry.config(validatecommand=(entry.register(validate_int), "%P"))
153
- elif data_type == float:
149
+ elif data_type is float:
154
150
  entry = tk.Entry(self.master, validate="key")
155
151
  entry.config(validatecommand=(entry.register(validate_float), "%P"))
156
152
  else:
@@ -4,7 +4,17 @@ from .conduits import CONDUIT
4
4
  from .iic import IIC
5
5
  from .losses import BLOCKAGE, CULVERT
6
6
  from .sections import INTERPOLATE, REPLICATE, RIVER
7
- from .structures import BRIDGE, CRUMP, FLAT_V_WEIR, ORIFICE, OUTFALL, RNWEIR, SLUICE, SPILL, WEIR
7
+ from .structures import (
8
+ BRIDGE,
9
+ CRUMP,
10
+ FLAT_V_WEIR,
11
+ ORIFICE,
12
+ OUTFALL,
13
+ RNWEIR,
14
+ SLUICE,
15
+ SPILL,
16
+ WEIR,
17
+ )
8
18
  from .units import ALL_UNIT_TYPES, SUPPORTED_UNIT_TYPES, UNSUPPORTED_UNIT_TYPES
9
19
  from .unsupported import UNSUPPORTED
10
20
  from .variables import Variables