floodmodeller-api 0.5.1__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 (86) hide show
  1. floodmodeller_api/__init__.py +10 -0
  2. floodmodeller_api/_base.py +29 -20
  3. floodmodeller_api/backup.py +12 -10
  4. floodmodeller_api/dat.py +162 -91
  5. floodmodeller_api/diff.py +1 -1
  6. floodmodeller_api/hydrology_plus/hydrology_plus_export.py +1 -1
  7. floodmodeller_api/ied.py +2 -4
  8. floodmodeller_api/ief.py +29 -17
  9. floodmodeller_api/ief_flags.py +1 -1
  10. floodmodeller_api/inp.py +4 -6
  11. floodmodeller_api/logs/lf.py +18 -12
  12. floodmodeller_api/logs/lf_helpers.py +2 -2
  13. floodmodeller_api/logs/lf_params.py +1 -5
  14. floodmodeller_api/mapping.py +9 -2
  15. floodmodeller_api/test/test_conveyance.py +9 -4
  16. floodmodeller_api/test/test_dat.py +166 -18
  17. floodmodeller_api/test/test_data/EX18_DAT_expected.json +164 -144
  18. floodmodeller_api/test/test_data/EX3_DAT_expected.json +6 -2
  19. floodmodeller_api/test/test_data/EX6_DAT_expected.json +12 -46
  20. floodmodeller_api/test/test_data/encoding_test_cp1252.dat +1081 -0
  21. floodmodeller_api/test/test_data/encoding_test_utf8.dat +1081 -0
  22. floodmodeller_api/test/test_data/integrated_bridge/AR_NoSP_NoBl_2O_NO_OneFRC.ied +33 -0
  23. floodmodeller_api/test/test_data/integrated_bridge/AR_vSP_25pc_1O.ied +32 -0
  24. floodmodeller_api/test/test_data/integrated_bridge/PL_vSP_25pc_1O.ied +34 -0
  25. floodmodeller_api/test/test_data/integrated_bridge/SBTwoFRCsStaggered.IED +32 -0
  26. floodmodeller_api/test/test_data/integrated_bridge/US_NoSP_NoBl_OR_RN.ied +28 -0
  27. floodmodeller_api/test/test_data/integrated_bridge/US_SP_NoBl_OR_frc_PT2-5_RN.ied +34 -0
  28. floodmodeller_api/test/test_data/integrated_bridge/US_fSP_NoBl_1O.ied +30 -0
  29. floodmodeller_api/test/test_data/integrated_bridge/US_nSP_NoBl_1O.ied +49 -0
  30. floodmodeller_api/test/test_data/integrated_bridge/US_vSP_NoBl_2O_Para.ied +35 -0
  31. floodmodeller_api/test/test_data/integrated_bridge.dat +40 -0
  32. floodmodeller_api/test/test_data/network.ied +2 -2
  33. floodmodeller_api/test/test_data/network_dat_expected.json +141 -243
  34. floodmodeller_api/test/test_data/network_ied_expected.json +2 -2
  35. floodmodeller_api/test/test_data/network_with_comments.ied +2 -2
  36. floodmodeller_api/test/test_ied.py +1 -1
  37. floodmodeller_api/test/test_ief.py +10 -2
  38. floodmodeller_api/test/test_integrated_bridge.py +159 -0
  39. floodmodeller_api/test/test_json.py +9 -3
  40. floodmodeller_api/test/test_logs_lf.py +45 -24
  41. floodmodeller_api/test/test_river.py +1 -1
  42. floodmodeller_api/test/test_toolbox_structure_log.py +0 -1
  43. floodmodeller_api/test/test_xml2d.py +5 -5
  44. floodmodeller_api/to_from_json.py +1 -1
  45. floodmodeller_api/tool.py +3 -5
  46. floodmodeller_api/toolbox/model_build/add_siltation_definition.py +1 -1
  47. floodmodeller_api/toolbox/model_build/structure_log/structure_log.py +12 -8
  48. floodmodeller_api/units/__init__.py +15 -0
  49. floodmodeller_api/units/_base.py +73 -10
  50. floodmodeller_api/units/_helpers.py +343 -0
  51. floodmodeller_api/units/boundaries.py +59 -71
  52. floodmodeller_api/units/comment.py +1 -1
  53. floodmodeller_api/units/conduits.py +57 -54
  54. floodmodeller_api/units/connectors.py +112 -0
  55. floodmodeller_api/units/controls.py +107 -0
  56. floodmodeller_api/units/iic.py +2 -9
  57. floodmodeller_api/units/losses.py +42 -42
  58. floodmodeller_api/units/sections.py +40 -43
  59. floodmodeller_api/units/structures.py +360 -530
  60. floodmodeller_api/units/units.py +25 -26
  61. floodmodeller_api/units/unsupported.py +5 -7
  62. floodmodeller_api/units/variables.py +2 -2
  63. floodmodeller_api/urban1d/_base.py +7 -8
  64. floodmodeller_api/urban1d/conduits.py +11 -21
  65. floodmodeller_api/urban1d/general_parameters.py +1 -1
  66. floodmodeller_api/urban1d/junctions.py +7 -11
  67. floodmodeller_api/urban1d/losses.py +13 -17
  68. floodmodeller_api/urban1d/outfalls.py +16 -21
  69. floodmodeller_api/urban1d/raingauges.py +3 -9
  70. floodmodeller_api/urban1d/subsections.py +3 -4
  71. floodmodeller_api/urban1d/xsections.py +11 -15
  72. floodmodeller_api/util.py +7 -4
  73. floodmodeller_api/validation/parameters.py +7 -3
  74. floodmodeller_api/validation/urban_parameters.py +1 -4
  75. floodmodeller_api/validation/validation.py +9 -4
  76. floodmodeller_api/version.py +1 -1
  77. floodmodeller_api/xml2d.py +9 -11
  78. floodmodeller_api/xml2d_template.py +1 -1
  79. floodmodeller_api/zz.py +7 -6
  80. {floodmodeller_api-0.5.1.dist-info → floodmodeller_api-0.5.2.dist-info}/LICENSE.txt +1 -1
  81. {floodmodeller_api-0.5.1.dist-info → floodmodeller_api-0.5.2.dist-info}/METADATA +11 -3
  82. {floodmodeller_api-0.5.1.dist-info → floodmodeller_api-0.5.2.dist-info}/RECORD +85 -70
  83. {floodmodeller_api-0.5.1.dist-info → floodmodeller_api-0.5.2.dist-info}/WHEEL +1 -1
  84. floodmodeller_api/units/helpers.py +0 -121
  85. {floodmodeller_api-0.5.1.dist-info → floodmodeller_api-0.5.2.dist-info}/entry_points.txt +0 -0
  86. {floodmodeller_api-0.5.1.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.
@@ -19,13 +19,18 @@ from __future__ import annotations
19
19
  from typing import TypedDict
20
20
 
21
21
 
22
- class UnitTypes(TypedDict):
22
+ class SupportedUnitTypes(TypedDict):
23
23
  group: str
24
24
  has_subtype: bool
25
25
 
26
26
 
27
+ class UnsupportedUnitTypes(TypedDict):
28
+ group: str | None
29
+ has_subtype: bool
30
+
31
+
27
32
  # Unit types and support
28
- SUPPORTED_UNIT_TYPES: dict[str, UnitTypes] = {
33
+ SUPPORTED_UNIT_TYPES: dict[str, SupportedUnitTypes] = {
29
34
  "QTBDY": {"group": "boundaries", "has_subtype": False},
30
35
  "HTBDY": {"group": "boundaries", "has_subtype": False},
31
36
  "QHBDY": {"group": "boundaries", "has_subtype": False},
@@ -48,45 +53,39 @@ SUPPORTED_UNIT_TYPES: dict[str, UnitTypes] = {
48
53
  "REPLICATE": {"group": "sections", "has_subtype": False},
49
54
  "OUTFALL": {"group": "structures", "has_subtype": True},
50
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},
51
59
  }
52
60
 
53
- UNSUPPORTED_UNIT_TYPES = {
54
- "ABSTRACTION": {"has_subtype": False},
55
- "BERNOULLI": {"has_subtype": False},
56
- "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
57
65
  "FEHBDY": {"group": "boundaries", "has_subtype": False}, # RAINFALL RUNOFF METHOD boundary
58
- "FLOOD RELIEF": {"has_subtype": True}, # found in dat file
66
+ "FLOOD RELIEF": {"group": None, "has_subtype": True}, # found in dat file
59
67
  "FLOOD RELIEF ARCH": {"group": "structures", "has_subtype": True}, # found in FM help
60
- "FLOODPLAIN": {"has_subtype": True}, # floodplain section culvert
68
+ "FLOODPLAIN": {"group": None, "has_subtype": True}, # floodplain section culvert
61
69
  "FRQSIM": {"group": "boundaries", "has_subtype": False}, # flood FReQuency SIMulation
62
- "FSRBDY": {
63
- "group": "boundaries",
64
- "has_subtype": False,
65
- }, # FEH Method (FEH Rainfall Runoff Method)
70
+ "FSRBDY": {"group": "boundaries", "has_subtype": False}, # FEH Rainfall Runoff Method
66
71
  "FSSR16BDY": {"group": "boundaries", "has_subtype": False}, # FSSR16 Method
67
72
  "GATED WEIR": {"group": "structures", "has_subtype": False}, # gated weir
68
- "GAUGE": {"has_subtype": False}, # Gauge
73
+ "GAUGE": {"group": None, "has_subtype": False}, # Gauge
69
74
  "GERRBDY": {"group": "boundaries", "has_subtype": False}, # gen rainfall runoff
70
75
  "INVERTED SYPHON": {"group": "structures", "has_subtype": True}, # invert syphon
71
- "JUNCTION": {"has_subtype": True}, # [connector]
72
76
  "LABYRINTH WEIR": {"group": "structures", "has_subtype": False}, # labyrinth weir
73
- "LATERAL": {"has_subtype": False}, # [connector]
74
- "LOSS": {"has_subtype": False}, # found in .dat
75
- "LOSSID": {"has_subtype": False}, # found in .dat
76
- "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]
77
80
  "NCDBDY": {"group": "boundaries", "has_subtype": False}, # Normal/Critical Depth Boundary
78
81
  "NOTWEIR": {"group": "structures", "has_subtype": False}, # Notional Weir
79
- "OCPUMP": {"has_subtype": False}, # pump [junctions]
80
- "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]
81
84
  "QH CONTROL": {"group": "structures", "has_subtype": False}, # Flow-head control weir
82
85
  "QRATING": {"group": "boundaries", "has_subtype": False}, # Rating Curves
83
86
  "REBDY": {"group": "boundaries", "has_subtype": False}, # Rainfall/Evaporation Boundary
84
87
  "REFH2BDY": {"group": "boundaries", "has_subtype": False}, # ReFH2 Method
85
- "RESERVOIR": {"has_subtype": False}, # reservoir unit [connector]
86
- "SCSBDY": {
87
- "group": "boundaries",
88
- "has_subtype": False,
89
- }, # US SCS Method now SS for rainfall/runoff
88
+ "SCSBDY": {"group": "boundaries", "has_subtype": False}, # US SCS now SS for rainfall/runoff
90
89
  "SCWEIR": {"group": "structures", "has_subtype": False}, # sharp crested weir
91
90
  "SYPHON": {"group": "structures", "has_subtype": False}, # syphon unit
92
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
 
@@ -66,9 +67,9 @@ class UrbanUnit(Jsonable):
66
67
  def _diff(self, other):
67
68
  diff = self._get_diff(other)
68
69
  if diff[0]:
69
- print("No difference, units are equivalent")
70
+ logging.info("No difference, units are equivalent")
70
71
  else:
71
- 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]]))
72
73
 
73
74
  def _get_diff(self, other):
74
75
  return self.__eq__(other, return_diff=True) # pylint: disable=unnecessary-dunder-call
@@ -159,16 +160,14 @@ class UrbanSubsection(Jsonable):
159
160
  units[unit.name] = unit
160
161
  del units[name]
161
162
 
162
- # TODO: update label in any other units where required.
163
-
164
163
  return block
165
164
 
166
165
  def _diff(self, other):
167
166
  diff = self._get_diff(other)
168
167
  if diff[0]:
169
- print("No difference, units are equivalent")
168
+ logging.info("No difference, units are equivalent")
170
169
  else:
171
- 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]]))
172
171
 
173
172
  def _get_diff(self, other):
174
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,
@@ -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,
@@ -102,8 +98,6 @@ class RAINGAUGE(UrbanUnit):
102
98
 
103
99
  return params1 + params2
104
100
 
105
- # TODO: Implement validation that does not allow spaces to be entered in attribute values
106
-
107
101
 
108
102
  class RAINGAUGES(UrbanSubsection):
109
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.
@@ -16,7 +16,7 @@ address: Jacobs UK Limited, Flood Modeller, Cottons Centre, Cottons Lane, London
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- from typing import Type, TypedDict
19
+ from typing import TypedDict
20
20
 
21
21
  from ._base import UrbanSubsection
22
22
  from .conduits import CONDUITS
@@ -28,11 +28,10 @@ from .xsections import XSECTIONS
28
28
 
29
29
  SupportedSubsections = TypedDict(
30
30
  "SupportedSubsections",
31
- {"group": str, "attribute": str, "class": Type[UrbanSubsection]},
31
+ {"group": str, "attribute": str, "class": type[UrbanSubsection]},
32
32
  )
33
33
 
34
34
  # Unit types and support
35
- # TODO: Update functionality - SWMM manual indicates only first 4 characters of subsection heading are needed
36
35
  SUPPORTED_SUBSECTIONS: dict[str, SupportedSubsections] = {
37
36
  "[JUNCTIONS]": {"group": "units", "attribute": "_junctions", "class": JUNCTIONS},
38
37
  "[OUTFALLS]": {"group": "units", "attribute": "_outfalls", "class": OUTFALLS},
@@ -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_int, join_n_char_ljust
17
+ from floodmodeller_api.units._helpers import join_n_char_ljust, to_float, to_int
18
18
  from floodmodeller_api.validation import _validate_unit
19
19
 
20
20
  from ._base import UrbanSubsection, UrbanUnit
@@ -37,7 +37,7 @@ class XSECTION(UrbanUnit):
37
37
 
38
38
 
39
39
  Returns:
40
- XSECTION: Flood Modeller XSECTION Unit class object TODO: add urban 1d in to all instances within urban 1d API
40
+ XSECTION: Flood Modeller XSECTION Unit class object
41
41
  """
42
42
 
43
43
  _unit = "XSECTION"
@@ -48,8 +48,6 @@ class XSECTION(UrbanUnit):
48
48
  def _read(self, line):
49
49
  unit_data = line.split()
50
50
 
51
- # TODO: add functionality to read comments
52
- # TODO: consider appropriate defaults
53
51
  self.name = str(unit_data[0])
54
52
 
55
53
  if unit_data[1] in _shape_options:
@@ -59,20 +57,20 @@ class XSECTION(UrbanUnit):
59
57
  unit_data.append("")
60
58
 
61
59
  self.shape = str(unit_data[1])
62
- self.geom1 = _to_float(unit_data[2], 0.0)
63
- self.geom2 = _to_float(unit_data[3], 0.0)
64
- self.geom3 = _to_float(unit_data[4], 0.0)
65
- self.geom4 = _to_float(unit_data[5], 0.0)
66
- self.barrels = _to_int(unit_data[6], 1)
67
- self.culvert = _to_int(unit_data[7], "")
60
+ self.geom1 = to_float(unit_data[2], 0.0)
61
+ self.geom2 = to_float(unit_data[3], 0.0)
62
+ self.geom3 = to_float(unit_data[4], 0.0)
63
+ self.geom4 = to_float(unit_data[5], 0.0)
64
+ self.barrels = to_int(unit_data[6], 1)
65
+ self.culvert = to_int(unit_data[7], "")
68
66
 
69
67
  elif unit_data[1] == "CUSTOM":
70
68
  while len(unit_data) < self.MIN_LENGTH_CUSTOM:
71
69
  unit_data.append("")
72
70
 
73
71
  self.shape = str(unit_data[1])
74
- self.geom1 = _to_float(unit_data[2], "")
75
- self.barrels = _to_int(unit_data[6], 1)
72
+ self.geom1 = to_float(unit_data[2], "")
73
+ self.barrels = to_int(unit_data[6], 1)
76
74
 
77
75
  elif unit_data[1] == "IRREGULAR":
78
76
  while len(unit_data) < self.MIN_LENGTH_IRREGULAR:
@@ -86,8 +84,6 @@ class XSECTION(UrbanUnit):
86
84
 
87
85
  _validate_unit(self, urban=True)
88
86
 
89
- # TODO:Improve indentation format when writing and include header for completeness
90
-
91
87
  params1 = join_n_char_ljust(17, self.name)
92
88
 
93
89
  if self.shape in _shape_options: