floodmodeller-api 0.5.0.post1__py3-none-any.whl → 0.5.2__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 (119) hide show
  1. floodmodeller_api/__init__.py +11 -1
  2. floodmodeller_api/_base.py +55 -36
  3. floodmodeller_api/backup.py +15 -12
  4. floodmodeller_api/dat.py +191 -121
  5. floodmodeller_api/diff.py +4 -4
  6. floodmodeller_api/hydrology_plus/hydrology_plus_export.py +15 -14
  7. floodmodeller_api/ied.py +8 -10
  8. floodmodeller_api/ief.py +56 -42
  9. floodmodeller_api/ief_flags.py +1 -1
  10. floodmodeller_api/inp.py +7 -10
  11. floodmodeller_api/logs/lf.py +25 -26
  12. floodmodeller_api/logs/lf_helpers.py +20 -20
  13. floodmodeller_api/logs/lf_params.py +1 -5
  14. floodmodeller_api/mapping.py +11 -2
  15. floodmodeller_api/test/__init__.py +2 -2
  16. floodmodeller_api/test/conftest.py +2 -3
  17. floodmodeller_api/test/test_backup.py +2 -2
  18. floodmodeller_api/test/test_conveyance.py +13 -7
  19. floodmodeller_api/test/test_dat.py +168 -20
  20. floodmodeller_api/test/test_data/EX18_DAT_expected.json +164 -144
  21. floodmodeller_api/test/test_data/EX3_DAT_expected.json +6 -2
  22. floodmodeller_api/test/test_data/EX6_DAT_expected.json +12 -46
  23. floodmodeller_api/test/test_data/encoding_test_cp1252.dat +1081 -0
  24. floodmodeller_api/test/test_data/encoding_test_utf8.dat +1081 -0
  25. floodmodeller_api/test/test_data/integrated_bridge/AR_NoSP_NoBl_2O_NO_OneFRC.ied +33 -0
  26. floodmodeller_api/test/test_data/integrated_bridge/AR_vSP_25pc_1O.ied +32 -0
  27. floodmodeller_api/test/test_data/integrated_bridge/PL_vSP_25pc_1O.ied +34 -0
  28. floodmodeller_api/test/test_data/integrated_bridge/SBTwoFRCsStaggered.IED +32 -0
  29. floodmodeller_api/test/test_data/integrated_bridge/US_NoSP_NoBl_OR_RN.ied +28 -0
  30. floodmodeller_api/test/test_data/integrated_bridge/US_SP_NoBl_OR_frc_PT2-5_RN.ied +34 -0
  31. floodmodeller_api/test/test_data/integrated_bridge/US_fSP_NoBl_1O.ied +30 -0
  32. floodmodeller_api/test/test_data/integrated_bridge/US_nSP_NoBl_1O.ied +49 -0
  33. floodmodeller_api/test/test_data/integrated_bridge/US_vSP_NoBl_2O_Para.ied +35 -0
  34. floodmodeller_api/test/test_data/integrated_bridge.dat +40 -0
  35. floodmodeller_api/test/test_data/network.ied +2 -2
  36. floodmodeller_api/test/test_data/network_dat_expected.json +141 -243
  37. floodmodeller_api/test/test_data/network_ied_expected.json +2 -2
  38. floodmodeller_api/test/test_data/network_with_comments.ied +2 -2
  39. floodmodeller_api/test/test_data/structure_logs/EX17_expected.csv +4 -0
  40. floodmodeller_api/test/test_data/structure_logs/EX17_expected.json +69 -0
  41. floodmodeller_api/test/test_data/structure_logs/EX18_expected.csv +20 -0
  42. floodmodeller_api/test/test_data/structure_logs/EX18_expected.json +292 -0
  43. floodmodeller_api/test/test_data/structure_logs/EX6_expected.csv +4 -0
  44. floodmodeller_api/test/test_data/structure_logs/EX6_expected.json +35 -0
  45. floodmodeller_api/test/test_data/tabular_csv_outputs/network_zzn_flow.csv +182 -0
  46. floodmodeller_api/test/test_data/tabular_csv_outputs/network_zzn_fr.csv +182 -0
  47. floodmodeller_api/test/test_data/tabular_csv_outputs/network_zzn_mode.csv +182 -0
  48. floodmodeller_api/test/test_data/tabular_csv_outputs/network_zzn_stage.csv +182 -0
  49. floodmodeller_api/test/test_data/tabular_csv_outputs/network_zzn_state.csv +182 -0
  50. floodmodeller_api/test/test_data/tabular_csv_outputs/network_zzn_velocity.csv +182 -0
  51. floodmodeller_api/test/test_data/tabular_csv_outputs/network_zzx_left_fp_h.csv +182 -0
  52. floodmodeller_api/test/test_data/tabular_csv_outputs/network_zzx_left_fp_mode.csv +182 -0
  53. floodmodeller_api/test/test_data/tabular_csv_outputs/network_zzx_link_inflow.csv +182 -0
  54. floodmodeller_api/test/test_data/tabular_csv_outputs/network_zzx_max.csv +87 -0
  55. floodmodeller_api/test/test_data/tabular_csv_outputs/network_zzx_right_fp_h.csv +182 -0
  56. floodmodeller_api/test/test_data/tabular_csv_outputs/network_zzx_right_fp_mode.csv +182 -0
  57. floodmodeller_api/test/test_flowtimeprofile.py +2 -2
  58. floodmodeller_api/test/test_hydrology_plus_export.py +4 -2
  59. floodmodeller_api/test/test_ied.py +3 -3
  60. floodmodeller_api/test/test_ief.py +12 -4
  61. floodmodeller_api/test/test_inp.py +2 -2
  62. floodmodeller_api/test/test_integrated_bridge.py +159 -0
  63. floodmodeller_api/test/test_json.py +14 -13
  64. floodmodeller_api/test/test_logs_lf.py +50 -29
  65. floodmodeller_api/test/test_read_file.py +1 -0
  66. floodmodeller_api/test/test_river.py +12 -12
  67. floodmodeller_api/test/test_tool.py +8 -5
  68. floodmodeller_api/test/test_toolbox_structure_log.py +148 -158
  69. floodmodeller_api/test/test_xml2d.py +14 -16
  70. floodmodeller_api/test/test_zz.py +143 -0
  71. floodmodeller_api/to_from_json.py +9 -9
  72. floodmodeller_api/tool.py +15 -11
  73. floodmodeller_api/toolbox/example_tool.py +5 -1
  74. floodmodeller_api/toolbox/model_build/add_siltation_definition.py +13 -9
  75. floodmodeller_api/toolbox/model_build/structure_log/structure_log.py +500 -194
  76. floodmodeller_api/toolbox/model_build/structure_log_definition.py +5 -1
  77. floodmodeller_api/units/__init__.py +15 -0
  78. floodmodeller_api/units/_base.py +87 -20
  79. floodmodeller_api/units/_helpers.py +343 -0
  80. floodmodeller_api/units/boundaries.py +59 -71
  81. floodmodeller_api/units/comment.py +1 -1
  82. floodmodeller_api/units/conduits.py +57 -54
  83. floodmodeller_api/units/connectors.py +112 -0
  84. floodmodeller_api/units/controls.py +107 -0
  85. floodmodeller_api/units/conveyance.py +1 -1
  86. floodmodeller_api/units/iic.py +2 -9
  87. floodmodeller_api/units/losses.py +44 -45
  88. floodmodeller_api/units/sections.py +52 -51
  89. floodmodeller_api/units/structures.py +361 -531
  90. floodmodeller_api/units/units.py +27 -26
  91. floodmodeller_api/units/unsupported.py +5 -7
  92. floodmodeller_api/units/variables.py +2 -2
  93. floodmodeller_api/urban1d/_base.py +13 -17
  94. floodmodeller_api/urban1d/conduits.py +11 -21
  95. floodmodeller_api/urban1d/general_parameters.py +1 -1
  96. floodmodeller_api/urban1d/junctions.py +7 -11
  97. floodmodeller_api/urban1d/losses.py +13 -17
  98. floodmodeller_api/urban1d/outfalls.py +18 -22
  99. floodmodeller_api/urban1d/raingauges.py +5 -10
  100. floodmodeller_api/urban1d/subsections.py +5 -4
  101. floodmodeller_api/urban1d/xsections.py +14 -17
  102. floodmodeller_api/util.py +23 -6
  103. floodmodeller_api/validation/parameters.py +7 -3
  104. floodmodeller_api/validation/urban_parameters.py +1 -4
  105. floodmodeller_api/validation/validation.py +11 -5
  106. floodmodeller_api/version.py +1 -1
  107. floodmodeller_api/xml2d.py +27 -31
  108. floodmodeller_api/xml2d_template.py +1 -1
  109. floodmodeller_api/zz.py +539 -0
  110. {floodmodeller_api-0.5.0.post1.dist-info → floodmodeller_api-0.5.2.dist-info}/LICENSE.txt +1 -1
  111. {floodmodeller_api-0.5.0.post1.dist-info → floodmodeller_api-0.5.2.dist-info}/METADATA +30 -16
  112. {floodmodeller_api-0.5.0.post1.dist-info → floodmodeller_api-0.5.2.dist-info}/RECORD +116 -83
  113. {floodmodeller_api-0.5.0.post1.dist-info → floodmodeller_api-0.5.2.dist-info}/WHEEL +1 -1
  114. floodmodeller_api/test/test_zzn.py +0 -36
  115. floodmodeller_api/units/helpers.py +0 -123
  116. floodmodeller_api/zzn.py +0 -414
  117. /floodmodeller_api/test/test_data/{network_from_tabularCSV.csv → tabular_csv_outputs/network_zzn_max.csv} +0 -0
  118. {floodmodeller_api-0.5.0.post1.dist-info → floodmodeller_api-0.5.2.dist-info}/entry_points.txt +0 -0
  119. {floodmodeller_api-0.5.0.post1.dist-info → floodmodeller_api-0.5.2.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  """
2
2
  Flood Modeller Python API
3
- Copyright (C) 2024 Jacobs U.K. Limited
3
+ Copyright (C) 2025 Jacobs U.K. Limited
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
6
6
  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -14,16 +14,23 @@ If you have any query about this program or this License, please contact us at s
14
14
  address: Jacobs UK Limited, Flood Modeller, Cottons Centre, Cottons Lane, London, SE1 2QG, United Kingdom.
15
15
  """
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  from typing import TypedDict
18
20
 
19
21
 
20
- class UnitTypes(TypedDict):
22
+ class SupportedUnitTypes(TypedDict):
21
23
  group: str
22
24
  has_subtype: bool
23
25
 
24
26
 
27
+ class UnsupportedUnitTypes(TypedDict):
28
+ group: str | None
29
+ has_subtype: bool
30
+
31
+
25
32
  # Unit types and support
26
- SUPPORTED_UNIT_TYPES: dict[str, UnitTypes] = {
33
+ SUPPORTED_UNIT_TYPES: dict[str, SupportedUnitTypes] = {
27
34
  "QTBDY": {"group": "boundaries", "has_subtype": False},
28
35
  "HTBDY": {"group": "boundaries", "has_subtype": False},
29
36
  "QHBDY": {"group": "boundaries", "has_subtype": False},
@@ -46,45 +53,39 @@ SUPPORTED_UNIT_TYPES: dict[str, UnitTypes] = {
46
53
  "REPLICATE": {"group": "sections", "has_subtype": False},
47
54
  "OUTFALL": {"group": "structures", "has_subtype": True},
48
55
  "COMMENT": {"group": "comments", "has_subtype": False},
56
+ "JUNCTION": {"group": "connectors", "has_subtype": True},
57
+ "LATERAL": {"group": "connectors", "has_subtype": False},
58
+ "RESERVOIR": {"group": "controls", "has_subtype": False},
49
59
  }
50
60
 
51
- UNSUPPORTED_UNIT_TYPES = {
52
- "ABSTRACTION": {"has_subtype": False},
53
- "BERNOULLI": {"has_subtype": False},
54
- "BREACH": {"has_subtype": False}, # breach
61
+ UNSUPPORTED_UNIT_TYPES: dict[str, UnsupportedUnitTypes] = {
62
+ "ABSTRACTION": {"group": None, "has_subtype": False},
63
+ "BERNOULLI": {"group": None, "has_subtype": False},
64
+ "BREACH": {"group": None, "has_subtype": False}, # breach
55
65
  "FEHBDY": {"group": "boundaries", "has_subtype": False}, # RAINFALL RUNOFF METHOD boundary
56
- "FLOOD RELIEF": {"has_subtype": True}, # found in dat file
66
+ "FLOOD RELIEF": {"group": None, "has_subtype": True}, # found in dat file
57
67
  "FLOOD RELIEF ARCH": {"group": "structures", "has_subtype": True}, # found in FM help
58
- "FLOODPLAIN": {"has_subtype": True}, # floodplain section culvert
68
+ "FLOODPLAIN": {"group": None, "has_subtype": True}, # floodplain section culvert
59
69
  "FRQSIM": {"group": "boundaries", "has_subtype": False}, # flood FReQuency SIMulation
60
- "FSRBDY": {
61
- "group": "boundaries",
62
- "has_subtype": False,
63
- }, # FEH Method (FEH Rainfall Runoff Method)
70
+ "FSRBDY": {"group": "boundaries", "has_subtype": False}, # FEH Rainfall Runoff Method
64
71
  "FSSR16BDY": {"group": "boundaries", "has_subtype": False}, # FSSR16 Method
65
72
  "GATED WEIR": {"group": "structures", "has_subtype": False}, # gated weir
66
- "GAUGE": {"has_subtype": False}, # Gauge
73
+ "GAUGE": {"group": None, "has_subtype": False}, # Gauge
67
74
  "GERRBDY": {"group": "boundaries", "has_subtype": False}, # gen rainfall runoff
68
75
  "INVERTED SYPHON": {"group": "structures", "has_subtype": True}, # invert syphon
69
- "JUNCTION": {"has_subtype": True}, # [connector]
70
76
  "LABYRINTH WEIR": {"group": "structures", "has_subtype": False}, # labyrinth weir
71
- "LATERAL": {"has_subtype": False}, # [connector]
72
- "LOSS": {"has_subtype": False}, # found in .dat
73
- "LOSSID": {"has_subtype": False}, # found in .dat
74
- "MANHOLE": {"has_subtype": False}, # Manhole [connector]
77
+ "LOSS": {"group": None, "has_subtype": False}, # found in .dat
78
+ "LOSSID": {"group": None, "has_subtype": False}, # found in .dat
79
+ "MANHOLE": {"group": None, "has_subtype": False}, # Manhole [connector]
75
80
  "NCDBDY": {"group": "boundaries", "has_subtype": False}, # Normal/Critical Depth Boundary
76
81
  "NOTWEIR": {"group": "structures", "has_subtype": False}, # Notional Weir
77
- "OCPUMP": {"has_subtype": False}, # pump [junctions]
78
- "POND": {"has_subtype": True}, # Pond units, online pond etc [connector]
82
+ "OCPUMP": {"group": None, "has_subtype": False}, # pump [junctions]
83
+ "POND": {"group": None, "has_subtype": True}, # Pond units, online pond etc [connector]
79
84
  "QH CONTROL": {"group": "structures", "has_subtype": False}, # Flow-head control weir
80
85
  "QRATING": {"group": "boundaries", "has_subtype": False}, # Rating Curves
81
86
  "REBDY": {"group": "boundaries", "has_subtype": False}, # Rainfall/Evaporation Boundary
82
87
  "REFH2BDY": {"group": "boundaries", "has_subtype": False}, # ReFH2 Method
83
- "RESERVOIR": {"has_subtype": False}, # reservoir unit [connector]
84
- "SCSBDY": {
85
- "group": "boundaries",
86
- "has_subtype": False,
87
- }, # US SCS Method now SS for rainfall/runoff
88
+ "SCSBDY": {"group": "boundaries", "has_subtype": False}, # US SCS now SS for rainfall/runoff
88
89
  "SCWEIR": {"group": "structures", "has_subtype": False}, # sharp crested weir
89
90
  "SYPHON": {"group": "structures", "has_subtype": False}, # syphon unit
90
91
  "TIDBDY": {"group": "boundaries", "has_subtype": False}, # tidal
@@ -1,6 +1,6 @@
1
1
  """
2
2
  Flood Modeller Python API
3
- Copyright (C) 2024 Jacobs U.K. Limited
3
+ Copyright (C) 2025 Jacobs U.K. Limited
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
6
6
  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -15,7 +15,7 @@ address: Jacobs UK Limited, Flood Modeller, Cottons Centre, Cottons Lane, London
15
15
  """
16
16
 
17
17
  from ._base import Unit
18
- from .helpers import split_n_char
18
+ from ._helpers import split_n_char
19
19
 
20
20
 
21
21
  class UNSUPPORTED(Unit):
@@ -26,18 +26,16 @@ class UNSUPPORTED(Unit):
26
26
  self._unit = unit_type
27
27
  self._subtype = subtype
28
28
  self._raw_block = block
29
- self.comment = block[0].replace(self._unit, "").strip()
29
+ self.comment = self._remove_unit_name(block[0])
30
30
 
31
31
  if self._subtype is False:
32
32
  self.labels = split_n_char(f"{block[1]:<{2*self._label_len}}", self._label_len)
33
33
 
34
34
  else:
35
- self._subtype = block[1].split(" ")[0].strip()
36
- if self._unit == "JUNCTION":
37
- self.labels = split_n_char(block[2], self._label_len)
35
+ self._subtype = self._get_first_word(block[1])
38
36
  self.labels = split_n_char(f"{block[2]:<{2*self._label_len}}", self._label_len)
39
37
 
40
- if self.labels[1] != "" and self._unit != "JUNCTION":
38
+ if self.labels[1] != "":
41
39
  self.ds_label = self.labels[1]
42
40
 
43
41
  def _write(self):
@@ -1,6 +1,6 @@
1
1
  """
2
2
  Flood Modeller Python API
3
- Copyright (C) 2024 Jacobs U.K. Limited
3
+ Copyright (C) 2025 Jacobs U.K. Limited
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
6
6
  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -18,7 +18,7 @@ import pandas as pd
18
18
 
19
19
  from ..diff import check_item_with_dataframe_equal
20
20
  from ..to_from_json import Jsonable
21
- from .helpers import join_10_char
21
+ from ._helpers import join_10_char
22
22
 
23
23
 
24
24
  class Variables(Jsonable):
@@ -1,6 +1,6 @@
1
1
  """
2
2
  Flood Modeller Python API
3
- Copyright (C) 2024 Jacobs U.K. Limited
3
+ Copyright (C) 2025 Jacobs U.K. Limited
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
6
6
  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -18,6 +18,8 @@ from __future__ import annotations
18
18
 
19
19
  """ Holds the base unit class for all FM 1D units Units """
20
20
 
21
+ import logging
22
+
21
23
  from ..diff import check_item_with_dataframe_equal
22
24
  from ..to_from_json import Jsonable
23
25
 
@@ -32,7 +34,6 @@ class UrbanUnit(Jsonable):
32
34
  return
33
35
  if unit_block is not None:
34
36
  self._read(unit_block)
35
- # TODO: add functionality to read description
36
37
  else:
37
38
  self._create_from_blank(**kwargs)
38
39
 
@@ -51,9 +52,8 @@ class UrbanUnit(Jsonable):
51
52
  return None
52
53
 
53
54
  def _create_from_blank(self):
54
- raise NotImplementedError(
55
- f"Creating new {self._unit} units is not yet supported by floodmodeller_api, only existing units can be read",
56
- )
55
+ msg = f"Creating new {self._unit} units is not yet supported by floodmodeller_api, only existing units can be read"
56
+ raise NotImplementedError(msg)
57
57
 
58
58
  def __str__(self):
59
59
  return self._write()
@@ -67,9 +67,9 @@ class UrbanUnit(Jsonable):
67
67
  def _diff(self, other):
68
68
  diff = self._get_diff(other)
69
69
  if diff[0]:
70
- print("No difference, units are equivalent")
70
+ logging.info("No difference, units are equivalent")
71
71
  else:
72
- print("\n".join([f"{name}: {reason}" for name, reason in diff[1]]))
72
+ logging.info("\n".join([f"{name}: {reason}" for name, reason in diff[1]]))
73
73
 
74
74
  def _get_diff(self, other):
75
75
  return self.__eq__(other, return_diff=True) # pylint: disable=unnecessary-dunder-call
@@ -110,9 +110,8 @@ class UrbanSubsection(Jsonable):
110
110
  return f"<floodmodeller_api UrbanSubsection Class: {self._attribute}>"
111
111
 
112
112
  def _create_from_blank(self):
113
- raise NotImplementedError(
114
- f"Creating new {self._name} subsections is not yet supported by floodmodeller_api, only existing subsections can be read",
115
- )
113
+ msg = f"Creating new {self._name} subsections is not yet supported by floodmodeller_api, only existing subsections can be read"
114
+ raise NotImplementedError(msg)
116
115
 
117
116
  def __str__(self):
118
117
  return "\n".join(self._write())
@@ -155,23 +154,20 @@ class UrbanSubsection(Jsonable):
155
154
  # Miss-match found
156
155
  # check that it is not an existing label in units
157
156
  if unit.name in units:
158
- raise Exception(
159
- f'Error: Cannot update label "{name}" to "{unit.name}" beacuase "{unit.name}" already exists in the {self._attribute} subsection',
160
- )
157
+ msg = f'Error: Cannot update label "{name}" to "{unit.name}" beacuase "{unit.name}" already exists in the {self._attribute} subsection'
158
+ raise Exception(msg)
161
159
 
162
160
  units[unit.name] = unit
163
161
  del units[name]
164
162
 
165
- # TODO: update label in any other units where required.
166
-
167
163
  return block
168
164
 
169
165
  def _diff(self, other):
170
166
  diff = self._get_diff(other)
171
167
  if diff[0]:
172
- print("No difference, units are equivalent")
168
+ logging.info("No difference, units are equivalent")
173
169
  else:
174
- print("\n".join([f"{name}: {reason}" for name, reason in diff[1]]))
170
+ logging.info("\n".join([f"{name}: {reason}" for name, reason in diff[1]]))
175
171
 
176
172
  def _get_diff(self, other):
177
173
  return self.__eq__(other, return_diff=True) # pylint: disable=unnecessary-dunder-call
@@ -1,6 +1,6 @@
1
1
  """
2
2
  Flood Modeller Python API
3
- Copyright (C) 2024 Jacobs U.K. Limited
3
+ Copyright (C) 2025 Jacobs U.K. Limited
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
6
6
  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -14,7 +14,7 @@ If you have any query about this program or this License, please contact us at s
14
14
  address: Jacobs UK Limited, Flood Modeller, Cottons Centre, Cottons Lane, London, SE1 2QG, United Kingdom.
15
15
  """
16
16
 
17
- from floodmodeller_api.units.helpers import _to_float, _to_str, join_n_char_ljust
17
+ from floodmodeller_api.units._helpers import join_n_char_ljust, to_float, to_str
18
18
  from floodmodeller_api.validation import _validate_unit
19
19
 
20
20
  from ._base import UrbanSubsection, UrbanUnit
@@ -44,37 +44,27 @@ class CONDUIT(UrbanUnit):
44
44
  def _read(self, line):
45
45
  """Function to read a given CONDUIT line and store data as class attributes"""
46
46
 
47
- # TODO: add functionality to read comments
48
- # TODO: considering raising an exception if any of the required parameters are missing
49
-
50
47
  unit_data = line.split() # Get unit parameters
51
48
 
52
49
  # Extend length of unit_data if options variables not provided.
53
50
  while len(unit_data) < self.MIN_LENGTH:
54
51
  unit_data.append("")
55
52
 
56
- # TODO: Update defaults. Presently atrbitary defaults added to allow API to work.
57
- # TODO: Consider re-naming variables to more intuitive names. Currently as as per SWMM manual
58
-
59
- self.name = _to_str(unit_data[0], "")
60
- self.node1 = _to_str(unit_data[1], "")
61
- self.node2 = _to_str(unit_data[2], "")
62
- self.length = _to_float(unit_data[3], 0.0)
63
- self.n = _to_float(unit_data[4], 0.0)
64
- self.z1 = _to_float(unit_data[5], 0.0)
65
- self.z2 = _to_float(unit_data[6], 0.0)
66
- self.q0 = _to_float(unit_data[7], 0.0) # Default as per FM
67
- self.qmax = _to_float(unit_data[8], 999999) # No limit
68
-
69
- # TODO: Consider linkage with other associated subsections i.e. [XSECTIONS] and [LOSSES]
53
+ self.name = to_str(unit_data[0], "")
54
+ self.node1 = to_str(unit_data[1], "")
55
+ self.node2 = to_str(unit_data[2], "")
56
+ self.length = to_float(unit_data[3], 0.0)
57
+ self.n = to_float(unit_data[4], 0.0)
58
+ self.z1 = to_float(unit_data[5], 0.0)
59
+ self.z2 = to_float(unit_data[6], 0.0)
60
+ self.q0 = to_float(unit_data[7], 0.0) # Default as per FM
61
+ self.qmax = to_float(unit_data[8], 999999) # No limit
70
62
 
71
63
  def _write(self):
72
64
  """Function to write a valid CONDUIT line"""
73
65
 
74
66
  _validate_unit(self, urban=True)
75
67
 
76
- # TODO:Improve indentation format when writing and include header for completeness
77
-
78
68
  return join_n_char_ljust(17, self.name, self.node1, self.node2) + join_n_char_ljust(
79
69
  15,
80
70
  self.length,
@@ -1,6 +1,6 @@
1
1
  """
2
2
  Flood Modeller Python API
3
- Copyright (C) 2024 Jacobs U.K. Limited
3
+ Copyright (C) 2025 Jacobs U.K. Limited
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
6
6
  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -1,6 +1,6 @@
1
1
  """
2
2
  Flood Modeller Python API
3
- Copyright (C) 2024 Jacobs U.K. Limited
3
+ Copyright (C) 2025 Jacobs U.K. Limited
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
6
6
  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -14,7 +14,7 @@ If you have any query about this program or this License, please contact us at s
14
14
  address: Jacobs UK Limited, Flood Modeller, Cottons Centre, Cottons Lane, London, SE1 2QG, United Kingdom.
15
15
  """
16
16
 
17
- from floodmodeller_api.units.helpers import _to_float, join_n_char_ljust
17
+ from floodmodeller_api.units._helpers import join_n_char_ljust, to_float
18
18
  from floodmodeller_api.validation import _validate_unit
19
19
 
20
20
  from ._base import UrbanSubsection, UrbanUnit
@@ -41,8 +41,6 @@ class JUNCTION(UrbanUnit):
41
41
  def _read(self, line):
42
42
  """Function to read a given JUNCTION line and store data as class attributes"""
43
43
 
44
- # TODO: add functionality to read comments
45
-
46
44
  unit_data = line.split() # Get unit parameters
47
45
 
48
46
  # Extend length of unit_data if options variables not provided.
@@ -51,19 +49,17 @@ class JUNCTION(UrbanUnit):
51
49
 
52
50
  self.name = str(unit_data[0])
53
51
 
54
- self.elevation = _to_float(unit_data[1], 0.0)
55
- self.max_depth = _to_float(unit_data[2], 0.0)
56
- self.initial_depth = _to_float(unit_data[3], 0.0)
57
- self.surface_depth = _to_float(unit_data[4], 0.0)
58
- self.area_ponded = _to_float(unit_data[5], 0.0)
52
+ self.elevation = to_float(unit_data[1], 0.0)
53
+ self.max_depth = to_float(unit_data[2], 0.0)
54
+ self.initial_depth = to_float(unit_data[3], 0.0)
55
+ self.surface_depth = to_float(unit_data[4], 0.0)
56
+ self.area_ponded = to_float(unit_data[5], 0.0)
59
57
 
60
58
  def _write(self):
61
59
  """Function to write a valid JUNCTION line"""
62
60
 
63
61
  _validate_unit(self, urban=True)
64
62
 
65
- # TODO:Improve indentation format when writing and include header for completeness
66
-
67
63
  return join_n_char_ljust(17, self.name) + join_n_char_ljust(
68
64
  15,
69
65
  self.elevation,
@@ -1,6 +1,6 @@
1
1
  """
2
2
  Flood Modeller Python API
3
- Copyright (C) 2024 Jacobs U.K. Limited
3
+ Copyright (C) 2025 Jacobs U.K. Limited
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
6
6
  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -14,7 +14,7 @@ If you have any query about this program or this License, please contact us at s
14
14
  address: Jacobs UK Limited, Flood Modeller, Cottons Centre, Cottons Lane, London, SE1 2QG, United Kingdom.
15
15
  """
16
16
 
17
- from floodmodeller_api.units.helpers import _to_float, _to_str, join_n_char_ljust
17
+ from floodmodeller_api.units._helpers import join_n_char_ljust, to_float, to_str
18
18
  from floodmodeller_api.validation import _validate_unit
19
19
 
20
20
  from ._base import UrbanSubsection, UrbanUnit
@@ -25,11 +25,11 @@ class LOSS(UrbanUnit):
25
25
 
26
26
  Args:
27
27
  name (str): Name of conduit. (required)
28
- kentry (float): Entrance minor head loss coefficient. (required) # TODO: FM name - Entry Loss Coeff.
29
- kexit (float): Exit minor head loss coefficient. (required) # TODO: FM name - Exit Loss Coeff.
30
- kavg (float): Average minor head loss coefficient across lenght of culvert. (required) # TODO: FM name - Avg. Loss Coeff.
31
- flap (str): YES/NO. If conduit has a flat valve that prevents back flow. (optional, default NO ) # TODO: FM name - Flap Gate.
32
- seepage (float): Rate of seepage loss into surrounding soil (in/hr or mm/hr). (optional, default is 0) # TODO: FM name - Seepage Loss Rate
28
+ kentry (float): Entrance minor head loss coefficient. (required)
29
+ kexit (float): Exit minor head loss coefficient. (required)
30
+ kavg (float): Average minor head loss coefficient across lenght of culvert. (required)
31
+ flap (str): YES/NO. If conduit has a flat valve that prevents back flow. (optional, default NO )
32
+ seepage (float): Rate of seepage loss into surrounding soil (in/hr or mm/hr). (optional, default is 0)
33
33
 
34
34
 
35
35
  Returns:
@@ -42,28 +42,24 @@ class LOSS(UrbanUnit):
42
42
  def _read(self, line):
43
43
  """Function to read a given LOSS line and store data as class attributes"""
44
44
 
45
- # TODO: add functionality to read comments
46
-
47
45
  unit_data = line.split() # Get unit parameters
48
46
 
49
47
  # Extend length of unit_data if options variables not provided.
50
48
  while len(unit_data) < self.MIN_LENGTH:
51
49
  unit_data.append("")
52
50
 
53
- self.name = _to_str(unit_data[0], "")
54
- self.kentry = _to_float(unit_data[1], 0)
55
- self.kexit = _to_float(unit_data[2], 0)
56
- self.kavg = _to_float(unit_data[3], 0)
57
- self.flap = _to_str(unit_data[4], "NO")
58
- self.seepage = _to_float(unit_data[5], 0)
51
+ self.name = to_str(unit_data[0], "")
52
+ self.kentry = to_float(unit_data[1], 0)
53
+ self.kexit = to_float(unit_data[2], 0)
54
+ self.kavg = to_float(unit_data[3], 0)
55
+ self.flap = to_str(unit_data[4], "NO")
56
+ self.seepage = to_float(unit_data[5], 0)
59
57
 
60
58
  def _write(self):
61
59
  """Function to write a valid LOSS line"""
62
60
 
63
61
  _validate_unit(self, urban=True)
64
62
 
65
- # TODO:Improve indentation format when writing and include header for completeness
66
-
67
63
  return join_n_char_ljust(17, self.name) + join_n_char_ljust(
68
64
  15,
69
65
  self.kentry,
@@ -1,6 +1,6 @@
1
1
  """
2
2
  Flood Modeller Python API
3
- Copyright (C) 2024 Jacobs U.K. Limited
3
+ Copyright (C) 2025 Jacobs U.K. Limited
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
6
6
  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -14,7 +14,7 @@ If you have any query about this program or this License, please contact us at s
14
14
  address: Jacobs UK Limited, Flood Modeller, Cottons Centre, Cottons Lane, London, SE1 2QG, United Kingdom.
15
15
  """
16
16
 
17
- from floodmodeller_api.units.helpers import _to_float, _to_str, join_n_char_ljust
17
+ from floodmodeller_api.units._helpers import join_n_char_ljust, to_float, to_str
18
18
  from floodmodeller_api.validation import _validate_unit
19
19
 
20
20
  from ._base import UrbanSubsection, UrbanUnit
@@ -30,25 +30,22 @@ class OUTFALL(UrbanUnit):
30
30
  stage (float): elevation of fixed stage for outfall (ft or m) (required when "FIXED" type)
31
31
  tcurve (string): name of curve in [CURVES] section containing tidal height (required when "TIDAL" type)
32
32
  tseries (string): name of timeseries in [TIMESERIES] section that describes how outfall stage varies with time (required when "TIMESERIES" type)
33
- gated (sring): "YES" or "NO" depending on whether flat gate is present that prevents reverse flow. (optional for all types, default is "NO") TODO: is this required, or can it be missing
33
+ gated (sring): "YES" or "NO" depending on whether flat gate is present that prevents reverse flow. (optional for all types, default is "NO")
34
34
  routeto (string): Optional name of a subcatchment that recieves the outfall's discharge. (default is not be "", and to no route outfall's discharge)
35
35
 
36
36
  Returns:
37
- OUTFALL: Flood Modeller OUTFALL Unit class object TODO: add urban 1d in to all instances within urban 1d API
37
+ OUTFALL: Flood Modeller OUTFALL Unit class object
38
38
  """
39
39
 
40
40
  _unit = "OUTFALL"
41
41
  MIN_LENGTH_FREE_NORMAL = 5
42
- MIN_LENGTH_FIXED_NORMAL_TIMESERIES = 6
42
+ MIN_LENGTH_FIXED_TIDAL_TIMESERIES = 6
43
43
 
44
44
  def _read(self, line):
45
45
  unit_data = line.split()
46
46
 
47
- # TODO: add functionality to read comments
48
- # TODO: considering raising an exception if any of the required parameters are missing
49
-
50
47
  self.name = str(unit_data[0])
51
- self.elevation = _to_float(unit_data[1], 0.0)
48
+ self.elevation = to_float(unit_data[1], 0.0)
52
49
  self.type = str(unit_data[2])
53
50
 
54
51
  if self.type in ("FREE", "NORMAL"):
@@ -56,33 +53,31 @@ class OUTFALL(UrbanUnit):
56
53
  while len(unit_data) < self.MIN_LENGTH_FREE_NORMAL:
57
54
  unit_data.append("")
58
55
 
59
- self.gated = _to_str(unit_data[3], "NO")
60
- self.routeto = _to_str(unit_data[4], "")
56
+ self.gated = to_str(unit_data[3], "NO")
57
+ self.routeto = to_str(unit_data[4], "")
61
58
 
62
- elif self.type in ("FIXED", "NORMAL", "TIMESERIES"):
59
+ elif self.type in ("FIXED", "TIDAL", "TIMESERIES"):
63
60
  # Extend length of unit_data to account for missing optional arguments.
64
- while len(unit_data) < self.MIN_LENGTH_FIXED_NORMAL_TIMESERIES:
61
+ while len(unit_data) < self.MIN_LENGTH_FIXED_TIDAL_TIMESERIES:
65
62
  unit_data.append("")
66
63
 
67
64
  if self.type == "FIXED":
68
- self.stage = _to_float(unit_data[3], 0.0)
65
+ self.stage = to_float(unit_data[3], 0.0)
69
66
 
70
- elif self.type == "NORMAL":
71
- self.tcurve = _to_str(unit_data[3], "")
67
+ elif self.type == "TIDAL":
68
+ self.tcurve = to_str(unit_data[3], "")
72
69
 
73
70
  elif self.type == "TIMESERIES":
74
- self.tseries = _to_str(unit_data[3], "")
71
+ self.tseries = to_str(unit_data[3], "")
75
72
 
76
- self.gated = _to_str(unit_data[4], "NO")
77
- self.routeto = _to_str(unit_data[5], "")
73
+ self.gated = to_str(unit_data[4], "NO")
74
+ self.routeto = to_str(unit_data[5], "")
78
75
 
79
76
  def _write(self):
80
77
  """Function to write a valid OUTFALL line"""
81
78
 
82
79
  _validate_unit(self, urban=True)
83
80
 
84
- # TODO:Improve indentation format when writing and include header for completeness
85
-
86
81
  params1 = join_n_char_ljust(17, self.name) + join_n_char_ljust(
87
82
  15,
88
83
  self.elevation,
@@ -102,7 +97,8 @@ class OUTFALL(UrbanUnit):
102
97
  params2 = join_n_char_ljust(15, self.tseries, self.gated, self.routeto)
103
98
 
104
99
  else:
105
- raise RuntimeError(f"{self.type} not supported")
100
+ msg = f"{self.type} not supported"
101
+ raise RuntimeError(msg)
106
102
 
107
103
  return params1 + params2
108
104
 
@@ -1,6 +1,6 @@
1
1
  """
2
2
  Flood Modeller Python API
3
- Copyright (C) 2024 Jacobs U.K. Limited
3
+ Copyright (C) 2025 Jacobs U.K. Limited
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
6
6
  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -14,7 +14,7 @@ If you have any query about this program or this License, please contact us at s
14
14
  address: Jacobs UK Limited, Flood Modeller, Cottons Centre, Cottons Lane, London, SE1 2QG, United Kingdom.
15
15
  """
16
16
 
17
- from floodmodeller_api.units.helpers import _to_float, join_n_char_ljust
17
+ from floodmodeller_api.units._helpers import join_n_char_ljust, to_float
18
18
  from floodmodeller_api.validation import _validate_unit
19
19
 
20
20
  from ._base import UrbanSubsection, UrbanUnit
@@ -43,8 +43,6 @@ class RAINGAUGE(UrbanUnit):
43
43
  def _read(self, line):
44
44
  """Function to read a given RAINGAUGE line and store data as class attributes"""
45
45
 
46
- # TODO: add functionality to read comments
47
-
48
46
  unit_data = line.split() # Get unit parameters
49
47
 
50
48
  self.name = str(unit_data[0])
@@ -55,7 +53,7 @@ class RAINGAUGE(UrbanUnit):
55
53
  except ValueError:
56
54
  self.interval = str(unit_data[2]) # HH:MM format
57
55
 
58
- self.snow_catch_factor = _to_float(unit_data[3], 0.0)
56
+ self.snow_catch_factor = to_float(unit_data[3], 0.0)
59
57
  self.data_option = str(unit_data[4])
60
58
 
61
59
  # Check is raingauge data is provided as a TIMESERIES or as a FILE
@@ -79,8 +77,6 @@ class RAINGAUGE(UrbanUnit):
79
77
 
80
78
  _validate_unit(self, urban=True)
81
79
 
82
- # TODO:Improve indentation format when writing and include header for completeness
83
-
84
80
  params1 = join_n_char_ljust(17, self.name) + join_n_char_ljust(
85
81
  15,
86
82
  self.format,
@@ -97,12 +93,11 @@ class RAINGAUGE(UrbanUnit):
97
93
  params2 = join_n_char_ljust(15, self.filename, self.station, self.units)
98
94
 
99
95
  else:
100
- raise RuntimeError(f"{self.data_option} not supported")
96
+ msg = f"{self.data_option} not supported"
97
+ raise RuntimeError(msg)
101
98
 
102
99
  return params1 + params2
103
100
 
104
- # TODO: Implement validation that does not allow spaces to be entered in attribute values
105
-
106
101
 
107
102
  class RAINGAUGES(UrbanSubsection):
108
103
  """Class to read/write the table of raingauges"""
@@ -1,6 +1,6 @@
1
1
  """
2
2
  Flood Modeller Python API
3
- Copyright (C) 2024 Jacobs U.K. Limited
3
+ Copyright (C) 2025 Jacobs U.K. Limited
4
4
 
5
5
  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
6
6
  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -14,7 +14,9 @@ If you have any query about this program or this License, please contact us at s
14
14
  address: Jacobs UK Limited, Flood Modeller, Cottons Centre, Cottons Lane, London, SE1 2QG, United Kingdom.
15
15
  """
16
16
 
17
- from typing import Type, TypedDict
17
+ from __future__ import annotations
18
+
19
+ from typing import TypedDict
18
20
 
19
21
  from ._base import UrbanSubsection
20
22
  from .conduits import CONDUITS
@@ -26,11 +28,10 @@ from .xsections import XSECTIONS
26
28
 
27
29
  SupportedSubsections = TypedDict(
28
30
  "SupportedSubsections",
29
- {"group": str, "attribute": str, "class": Type[UrbanSubsection]},
31
+ {"group": str, "attribute": str, "class": type[UrbanSubsection]},
30
32
  )
31
33
 
32
34
  # Unit types and support
33
- # TODO: Update functionality - SWMM manual indicates only first 4 characters of subsection heading are needed
34
35
  SUPPORTED_SUBSECTIONS: dict[str, SupportedSubsections] = {
35
36
  "[JUNCTIONS]": {"group": "units", "attribute": "_junctions", "class": JUNCTIONS},
36
37
  "[OUTFALLS]": {"group": "units", "attribute": "_outfalls", "class": OUTFALLS},