swmm-pandas 0.6.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.
@@ -0,0 +1,888 @@
1
+ # swmm-pandas input
2
+ # scope:
3
+ # - high level api for loading, inspecting, changing, and
4
+ # altering a SWMM input file using pandas dataframes
5
+ from __future__ import annotations
6
+
7
+ from swmm.pandas.input._section_classes import SectionBase, _sections
8
+ import swmm.pandas.input._section_classes as sc
9
+ import pathlib
10
+ import re
11
+ import warnings
12
+ from typing import TYPE_CHECKING, Optional, Self
13
+
14
+ if TYPE_CHECKING:
15
+ from swmm.pandas.input.model import Model
16
+
17
+
18
+ class InputFile:
19
+ _section_re = re.compile(R"^\[[\s\S]*?(?=^\[)", re.MULTILINE)
20
+ _section_keys = tuple(_sections.keys())
21
+
22
+ def __init__(self, inpfile: Optional[str | pathlib.Path] = None):
23
+ """Base class for a SWMM input file.
24
+
25
+ The input object provides an attribute for each section supported the SWMM inp file. The
26
+ section properties are created dynamically at runtime to keep source code dry and concise, but
27
+ typehints provide minimal docstrings for dataframe column names. Most sections are represented
28
+ by a pandas dataframe, with the exception of a few.
29
+
30
+ This class was written based on the `SWMM Users Manual`_, any parsing bugs might require bug reports to the
31
+ USEPA repo for updates to the users manual.
32
+
33
+ .. DANGER::
34
+ This class provides **minimal to no error checking** on your input file when loading it or writing it.
35
+
36
+ When creating new model elements or updating the properties of existing ones, swmm.pandas expects
37
+ that the user knows what they are doing.
38
+
39
+ Just because swmm.pandas allows you to do something, does not mean SWMM will accept it.
40
+
41
+ .. _SWMM Users Manual: https://www.epa.gov/system/files/documents/2022-04/swmm-users-manual-version-5.2.pdf
42
+
43
+ .. code-block:: python
44
+
45
+ # Using a the _close method
46
+ >>> from swmm.pandas import Input
47
+ >>> inp = Input('tests/data/bench_inp.inp')
48
+ >>> print(inp.option.head())
49
+ Value desc
50
+ Option
51
+ FLOW_UNITS CFS
52
+ INFILTRATION GREEN_AMPT
53
+ FLOW_ROUTING DYNWAVE
54
+ LINK_OFFSETS DEPTH
55
+ MIN_SLOPE 0
56
+ >>> print(inp.junc.head())
57
+ Elevation MaxDepth InitDepth SurDepth Aponded desc
58
+ Name
59
+ JUNC1 1.5 10.25 0 0 5000
60
+ JUNC2 -1.04 6.2 0 0 5000
61
+ JUNC3 -3.47 11.5 0 0 5000
62
+ JUNC4 -5.25 13.8 0 0 5000
63
+ JUNC6 0 9 0 200 0
64
+ >>> inp.junc['Elevation']+=100
65
+ >>> inp.junc['Elevation']
66
+ Name
67
+ JUNC1 101.5
68
+ JUNC2 98.96
69
+ JUNC3 96.53
70
+ JUNC4 94.75
71
+ JUNC6 100
72
+ Name: Elevation, dtype: object
73
+ >>> inp.to_file('new_inp_file.inp')
74
+
75
+ Parameters
76
+ ----------
77
+ inpfile: str
78
+ model inp file path
79
+ """
80
+ if inpfile is not None:
81
+ self.path: str = inpfile
82
+ self._load_inp_file()
83
+ # for sect in _sections.keys():
84
+ # # print(sect)
85
+ # self._set_section_prop(sect)
86
+
87
+ def _load_inp_file(self) -> None:
88
+ with open(self.path) as inp:
89
+ self.text: str = inp.read()
90
+
91
+ self._sections: dict[str, SectionBase] = {}
92
+ self._section_texts: dict[str, str] = {}
93
+
94
+ for section in self._section_re.findall(self.text):
95
+ name = re.findall(R"^\[(.*)\]", section)[0]
96
+
97
+ data = "\n".join(re.findall(R"^(?!;{2,}|\[).+$", section, re.MULTILINE))
98
+
99
+ try:
100
+ section_idx = list(
101
+ name.lower().startswith(x.lower()) for x in _sections
102
+ ).index(True)
103
+ section_key = self._section_keys[section_idx]
104
+ self._section_texts[section_key] = data
105
+ except Exception as e:
106
+ print(e)
107
+ self._sections[name] = data
108
+ # self.__setattr__(name.lower(), "Not Implemented")
109
+
110
+ print(f"Section {name} not yet supported")
111
+
112
+ def _get_section(self, key):
113
+ if key in self._section_texts:
114
+ data = self._section_texts[key]
115
+ return _sections[key].from_section_text(data)
116
+
117
+ else:
118
+ return _sections[key]._new_empty()
119
+
120
+ @classmethod
121
+ def _set_section_prop(cls, section: str) -> None:
122
+ section_class = _sections[section]
123
+ public_property_name = section_class.__name__.lower()
124
+ private_property_name = f"_{public_property_name}"
125
+
126
+ def getter(self):
127
+ if not hasattr(self, private_property_name):
128
+ setattr(self, private_property_name, self._get_section(section))
129
+ return getattr(self, private_property_name)
130
+
131
+ def setter(self, obj):
132
+ setattr(self, private_property_name, section_class._newobj(obj))
133
+
134
+ setattr(cls, public_property_name, property(getter, setter))
135
+
136
+ def to_string(self):
137
+ with warnings.catch_warnings():
138
+ warnings.simplefilter(action="ignore", category=FutureWarning)
139
+ out_str = ""
140
+ for sect in _sections.keys():
141
+ section_class = _sections[sect]
142
+ public_property_name = section_class.__name__.lower()
143
+ # private_property_name = f"_{public_property_name}"
144
+ if len(sect_obj := getattr(self, public_property_name)) > 0:
145
+ try:
146
+ sect_string = sect_obj.to_swmm_string()
147
+ out_str += f"[{sect_obj._section_name}]\n{sect_string}\n\n"
148
+ except Exception as e:
149
+ print(f"error parsing {sect_obj.__class__.__name__}")
150
+ raise e
151
+
152
+ return out_str
153
+
154
+ def to_file(self, path: str | pathlib.Path):
155
+ with open(path, "w") as f:
156
+ f.write(self.to_string())
157
+
158
+ @property
159
+ def title(self) -> sc.Title:
160
+
161
+ if not hasattr(self, "_title"):
162
+ self._title = self._get_section("TITLE")
163
+
164
+ return self._title
165
+
166
+ @title.setter
167
+ def title(self, obj) -> None:
168
+ self._title = sc.Title._newobj(obj)
169
+
170
+ @property
171
+ def option(self) -> sc.Option:
172
+ "['Option', 'Value', 'desc']"
173
+
174
+ if not hasattr(self, "_option"):
175
+ self._option = self._get_section("OPTION")
176
+
177
+ return self._option
178
+
179
+ @option.setter
180
+ def option(self, obj) -> None:
181
+ self._option = sc.Option._newobj(obj)
182
+
183
+ @property
184
+ def report(self) -> sc.Report:
185
+
186
+ if not hasattr(self, "_report"):
187
+ self._report = self._get_section("REPORT")
188
+
189
+ return self._report
190
+
191
+ @report.setter
192
+ def report(self, obj) -> None:
193
+ self._report = sc.Report._newobj(obj)
194
+
195
+ @property
196
+ def event(self) -> sc.Event:
197
+ "['Start', 'End', 'desc']"
198
+
199
+ if not hasattr(self, "_event"):
200
+ self._event = self._get_section("EVENT")
201
+
202
+ return self._event
203
+
204
+ @event.setter
205
+ def event(self, obj) -> None:
206
+ self._event = sc.Event._newobj(obj)
207
+
208
+ @property
209
+ def files(self) -> sc.Files:
210
+
211
+ if not hasattr(self, "_files"):
212
+ self._files = self._get_section("FILE")
213
+
214
+ return self._files
215
+
216
+ @files.setter
217
+ def files(self, obj) -> None:
218
+ self._files = sc.Files._newobj(obj)
219
+
220
+ @property
221
+ def raingage(self) -> sc.Raingage:
222
+ "['Name', 'Format', 'Interval', 'SCF', 'Source_Type', 'Source', 'Station', 'Units', 'desc']"
223
+
224
+ if not hasattr(self, "_raingage"):
225
+ self._raingage = self._get_section("RAINGAGE")
226
+
227
+ return self._raingage
228
+
229
+ @raingage.setter
230
+ def raingage(self, obj) -> None:
231
+ self._raingage = sc.Raingage._newobj(obj)
232
+
233
+ @property
234
+ def evap(self) -> sc.Evap:
235
+ "['Type', 'param1', 'param2', 'param3', 'param4', 'param5', 'param6', 'param7', 'param8', 'param9', 'param10', 'param11', 'param12', 'desc']"
236
+
237
+ if not hasattr(self, "_evap"):
238
+ self._evap = self._get_section("EVAP")
239
+
240
+ return self._evap
241
+
242
+ @evap.setter
243
+ def evap(self, obj) -> None:
244
+ self._evap = sc.Evap._newobj(obj)
245
+
246
+ @property
247
+ def temperature(self) -> sc.Temperature:
248
+ "['Option', 'param1', 'param2', 'param3', 'param4', 'param5', 'param6', 'param7', 'param8', 'param9', 'param10', 'param11', 'param12', 'param13', 'desc']"
249
+
250
+ if not hasattr(self, "_temperature"):
251
+ self._temperature = self._get_section("TEMPERATURE")
252
+
253
+ return self._temperature
254
+
255
+ @temperature.setter
256
+ def temperature(self, obj) -> None:
257
+ self._temperature = sc.Temperature._newobj(obj)
258
+
259
+ @property
260
+ def adjustments(self) -> sc.Adjustments:
261
+ "['Parameter', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'desc']"
262
+
263
+ if not hasattr(self, "_adjustments"):
264
+ self._adjustments = self._get_section("ADJUSTMENT")
265
+
266
+ return self._adjustments
267
+
268
+ @adjustments.setter
269
+ def adjustments(self, obj) -> None:
270
+ self._adjustments = sc.Adjustments._newobj(obj)
271
+
272
+ @property
273
+ def subcatchment(self) -> sc.Subcatchment:
274
+ "['Name', 'RainGage', 'Outlet', 'Area', 'PctImp', 'Width', 'Slope', 'CurbLeng', 'SnowPack', 'desc']"
275
+
276
+ if not hasattr(self, "_subcatchment"):
277
+ self._subcatchment = self._get_section("SUBCATCHMENT")
278
+
279
+ return self._subcatchment
280
+
281
+ @subcatchment.setter
282
+ def subcatchment(self, obj) -> None:
283
+ self._subcatchment = sc.Subcatchment._newobj(obj)
284
+
285
+ @property
286
+ def subarea(self) -> sc.Subarea:
287
+ "['Subcatchment', 'Nimp', 'Nperv', 'Simp', 'Sperv', 'PctZero', 'RouteTo', 'PctRouted', 'desc']"
288
+
289
+ if not hasattr(self, "_subarea"):
290
+ self._subarea = self._get_section("SUBAREA")
291
+
292
+ return self._subarea
293
+
294
+ @subarea.setter
295
+ def subarea(self, obj) -> None:
296
+ self._subarea = sc.Subarea._newobj(obj)
297
+
298
+ @property
299
+ def infil(self) -> sc.Infil:
300
+ "['Subcatchment', 'param1', 'param2', 'param3', 'param4', 'param5', 'Method', 'desc']"
301
+
302
+ if not hasattr(self, "_infil"):
303
+ self._infil = self._get_section("INFIL")
304
+
305
+ return self._infil
306
+
307
+ @infil.setter
308
+ def infil(self, obj) -> None:
309
+ self._infil = sc.Infil._newobj(obj)
310
+
311
+ @property
312
+ def lid_control(self) -> sc.LID_Control:
313
+ "['Name', 'Type', 'param1', 'param2', 'param3', 'param4', 'param5', 'param6', 'param7', 'desc']"
314
+
315
+ if not hasattr(self, "_lid_control"):
316
+ self._lid_control = self._get_section("LID_CONTROL")
317
+
318
+ return self._lid_control
319
+
320
+ @lid_control.setter
321
+ def lid_control(self, obj) -> None:
322
+ self._lid_control = sc.LID_Control._newobj(obj)
323
+
324
+ @property
325
+ def lid_usage(self) -> sc.LID_Usage:
326
+ "['Subcatchment', 'LIDProcess', 'Number', 'Area', 'Width', 'InitSat', 'FromImp', 'ToPerv', 'RptFile', 'DrainTo', 'FromPerv', 'desc']"
327
+
328
+ if not hasattr(self, "_lid_usage"):
329
+ self._lid_usage = self._get_section("LID_USAGE")
330
+
331
+ return self._lid_usage
332
+
333
+ @lid_usage.setter
334
+ def lid_usage(self, obj) -> None:
335
+ self._lid_usage = sc.LID_Usage._newobj(obj)
336
+
337
+ @property
338
+ def aquifer(self) -> sc.Aquifer:
339
+ "['Name', 'Por', 'WP', 'FC', 'Ksat', 'Kslope', 'Tslope', 'ETu', 'ETs', 'Seep', 'Ebot', 'Egw', 'Umc', 'ETupat', 'desc']"
340
+
341
+ if not hasattr(self, "_aquifer"):
342
+ self._aquifer = self._get_section("AQUIFER")
343
+
344
+ return self._aquifer
345
+
346
+ @aquifer.setter
347
+ def aquifer(self, obj) -> None:
348
+ self._aquifer = sc.Aquifer._newobj(obj)
349
+
350
+ @property
351
+ def groundwater(self) -> sc.Groundwater:
352
+ "['Subcatchment', 'Aquifer', 'Node', 'Esurf', 'A1', 'B1', 'A2', 'B2', 'A3', 'Dsw', 'Egwt', 'Ebot', 'Wgr', 'Umc', 'desc']"
353
+
354
+ if not hasattr(self, "_groundwater"):
355
+ self._groundwater = self._get_section("GROUNDWATER")
356
+
357
+ return self._groundwater
358
+
359
+ @groundwater.setter
360
+ def groundwater(self, obj) -> None:
361
+ self._groundwater = sc.Groundwater._newobj(obj)
362
+
363
+ @property
364
+ def gwf(self) -> sc.GWF:
365
+ "['Subcatch', 'Type', 'Expr', 'desc']"
366
+
367
+ if not hasattr(self, "_gwf"):
368
+ self._gwf = self._get_section("GWF")
369
+
370
+ return self._gwf
371
+
372
+ @gwf.setter
373
+ def gwf(self, obj) -> None:
374
+ self._gwf = sc.GWF._newobj(obj)
375
+
376
+ @property
377
+ def snowpack(self) -> sc.Snowpack:
378
+ "['Name', 'Surface', 'param1', 'param2', 'param3', 'param4', 'param5', 'param6', 'param7', 'desc']"
379
+
380
+ if not hasattr(self, "_snowpack"):
381
+ self._snowpack = self._get_section("SNOWPACK")
382
+
383
+ return self._snowpack
384
+
385
+ @snowpack.setter
386
+ def snowpack(self, obj) -> None:
387
+ self._snowpack = sc.Snowpack._newobj(obj)
388
+
389
+ @property
390
+ def junc(self) -> sc.Junc:
391
+ "['Name', 'Elevation', 'MaxDepth', 'InitDepth', 'SurDepth', 'Aponded', 'desc']"
392
+
393
+ if not hasattr(self, "_junc"):
394
+ self._junc = self._get_section("JUNC")
395
+
396
+ return self._junc
397
+
398
+ @junc.setter
399
+ def junc(self, obj) -> None:
400
+ self._junc = sc.Junc._newobj(obj)
401
+
402
+ @property
403
+ def outfall(self) -> sc.Outfall:
404
+ "['Name', 'Elevation', 'Type', 'StageData', 'Gated', 'RouteTo', 'desc']"
405
+
406
+ if not hasattr(self, "_outfall"):
407
+ self._outfall = self._get_section("OUTFALL")
408
+
409
+ return self._outfall
410
+
411
+ @outfall.setter
412
+ def outfall(self, obj) -> None:
413
+ self._outfall = sc.Outfall._newobj(obj)
414
+
415
+ @property
416
+ def divider(self) -> sc.Divider:
417
+ "['Name', 'Elevation', 'DivLink', 'DivType', 'DivCurve', 'Qmin', 'Height', 'Cd', 'Ymax', 'Y0', 'Ysur', 'Apond', 'desc']"
418
+
419
+ if not hasattr(self, "_divider"):
420
+ self._divider = self._get_section("DIVIDER")
421
+
422
+ return self._divider
423
+
424
+ @divider.setter
425
+ def divider(self, obj) -> None:
426
+ self._divider = sc.Divider._newobj(obj)
427
+
428
+ @property
429
+ def storage(self) -> sc.Storage:
430
+ "['Name', 'Elev', 'MaxDepth', 'InitDepth', 'Shape', 'CurveName', 'A1_L', 'A2_W', 'A0_Z', 'SurDepth', 'Fevap', 'Psi', 'Ksat', 'IMD', 'desc']"
431
+
432
+ if not hasattr(self, "_storage"):
433
+ self._storage = self._get_section("STORAGE")
434
+
435
+ return self._storage
436
+
437
+ @storage.setter
438
+ def storage(self, obj) -> None:
439
+ self._storage = sc.Storage._newobj(obj)
440
+
441
+ @property
442
+ def conduit(self) -> sc.Conduit:
443
+ "['Name', 'FromNode', 'ToNode', 'Length', 'Roughness', 'InOffset', 'OutOffset', 'InitFlow', 'MaxFlow', 'desc']"
444
+
445
+ if not hasattr(self, "_conduit"):
446
+ self._conduit = self._get_section("CONDUIT")
447
+
448
+ return self._conduit
449
+
450
+ @conduit.setter
451
+ def conduit(self, obj) -> None:
452
+ self._conduit = sc.Conduit._newobj(obj)
453
+
454
+ @property
455
+ def pump(self) -> sc.Pump:
456
+ "['Name', 'FromNode', 'ToNode', 'PumpCurve', 'Status', 'Startup', 'Shutoff', 'desc']"
457
+
458
+ if not hasattr(self, "_pump"):
459
+ self._pump = self._get_section("PUMP")
460
+
461
+ return self._pump
462
+
463
+ @pump.setter
464
+ def pump(self, obj) -> None:
465
+ self._pump = sc.Pump._newobj(obj)
466
+
467
+ @property
468
+ def orifice(self) -> sc.Orifice:
469
+ "['Name', 'FromNode', 'ToNode', 'Type', 'Offset', 'Qcoeff', 'Gated', 'CloseTime', 'desc']"
470
+
471
+ if not hasattr(self, "_orifice"):
472
+ self._orifice = self._get_section("ORIFICE")
473
+
474
+ return self._orifice
475
+
476
+ @orifice.setter
477
+ def orifice(self, obj) -> None:
478
+ self._orifice = sc.Orifice._newobj(obj)
479
+
480
+ @property
481
+ def weir(self) -> sc.Weir:
482
+ "['Name', 'FromNode', 'ToNode', 'Type', 'CrestHt', 'Qcoeff', 'Gated', 'EndCon', 'EndCoeff', 'Surcharge', 'RoadWidth', 'RoadSurf', 'CoeffCurve', 'desc']"
483
+
484
+ if not hasattr(self, "_weir"):
485
+ self._weir = self._get_section("WEIR")
486
+
487
+ return self._weir
488
+
489
+ @weir.setter
490
+ def weir(self, obj) -> None:
491
+ self._weir = sc.Weir._newobj(obj)
492
+
493
+ @property
494
+ def outlet(self) -> sc.Outlet:
495
+ "['Name', 'FromNode', 'ToNode', 'Offset', 'Type', 'CurveName', 'Qcoeff', 'Qexpon', 'Gated', 'desc']"
496
+
497
+ if not hasattr(self, "_outlet"):
498
+ self._outlet = self._get_section("OUTLET")
499
+
500
+ return self._outlet
501
+
502
+ @outlet.setter
503
+ def outlet(self, obj) -> None:
504
+ self._outlet = sc.Outlet._newobj(obj)
505
+
506
+ @property
507
+ def xsections(self) -> sc.Xsections:
508
+ "['Link', 'Shape', 'Geom1', 'Curve', 'Geom2', 'Geom3', 'Geom4', 'Barrels', 'Culvert', 'desc']"
509
+
510
+ if not hasattr(self, "_xsections"):
511
+ self._xsections = self._get_section("XSECT")
512
+
513
+ return self._xsections
514
+
515
+ @xsections.setter
516
+ def xsections(self, obj) -> None:
517
+ self._xsections = sc.Xsections._newobj(obj)
518
+
519
+ @property
520
+ def transects(self) -> sc.Transects:
521
+
522
+ if not hasattr(self, "_transects"):
523
+ self._transects = self._get_section("TRANSECT")
524
+
525
+ return self._transects
526
+
527
+ @transects.setter
528
+ def transects(self, obj) -> None:
529
+ self._transects = sc.Transects._newobj(obj)
530
+
531
+ @property
532
+ def street(self) -> sc.Street:
533
+ "['Name', 'Tcrown', 'Hcurb', 'Sroad', 'nRoad', 'Hdep', 'Wdep', 'Sides', 'Wback', 'Sback', 'nBack', 'desc']"
534
+
535
+ if not hasattr(self, "_street"):
536
+ self._street = self._get_section("STREETS")
537
+
538
+ return self._street
539
+
540
+ @street.setter
541
+ def street(self, obj) -> None:
542
+ self._street = sc.Street._newobj(obj)
543
+
544
+ @property
545
+ def inlet_usage(self) -> sc.Inlet_Usage:
546
+ "['Conduit', 'Inlet', 'Node', 'Number', '%Clogged', 'MaxFlow', 'hDStore', 'wDStore', 'Placement', 'desc']"
547
+
548
+ if not hasattr(self, "_inlet_usage"):
549
+ self._inlet_usage = self._get_section("INLET_USAGE")
550
+
551
+ return self._inlet_usage
552
+
553
+ @inlet_usage.setter
554
+ def inlet_usage(self, obj) -> None:
555
+ self._inlet_usage = sc.Inlet_Usage._newobj(obj)
556
+
557
+ @property
558
+ def inlet(self) -> sc.Inlet:
559
+ "['Name', 'Type', 'param1', 'param2', 'param3', 'param4', 'param5', 'desc']"
560
+
561
+ if not hasattr(self, "_inlet"):
562
+ self._inlet = self._get_section("INLET")
563
+
564
+ return self._inlet
565
+
566
+ @inlet.setter
567
+ def inlet(self, obj) -> None:
568
+ self._inlet = sc.Inlet._newobj(obj)
569
+
570
+ @property
571
+ def losses(self) -> sc.Losses:
572
+ "['Link', 'Kentry', 'Kexit', 'Kavg', 'FlapGate', 'Seepage', 'desc']"
573
+
574
+ if not hasattr(self, "_losses"):
575
+ self._losses = self._get_section("LOSS")
576
+
577
+ return self._losses
578
+
579
+ @losses.setter
580
+ def losses(self, obj) -> None:
581
+ self._losses = sc.Losses._newobj(obj)
582
+
583
+ @property
584
+ def controls(self) -> sc.Controls:
585
+
586
+ if not hasattr(self, "_controls"):
587
+ self._controls = self._get_section("CONTROL")
588
+
589
+ return self._controls
590
+
591
+ @controls.setter
592
+ def controls(self, obj) -> None:
593
+ self._controls = sc.Controls._newobj(obj)
594
+
595
+ @property
596
+ def pollutants(self) -> sc.Pollutants:
597
+ "['Name', 'Units', 'Crain', 'Cgw', 'Crdii', 'Kdecay', 'SnowOnly', 'CoPollutant', 'CoFrac', 'Cdwf', 'Cinit', 'desc']"
598
+
599
+ if not hasattr(self, "_pollutants"):
600
+ self._pollutants = self._get_section("POLLUT")
601
+
602
+ return self._pollutants
603
+
604
+ @pollutants.setter
605
+ def pollutants(self, obj) -> None:
606
+ self._pollutants = sc.Pollutants._newobj(obj)
607
+
608
+ @property
609
+ def landuse(self) -> sc.LandUse:
610
+ "['Name', 'SweepInterval', 'Availability', 'LastSweep', 'desc']"
611
+
612
+ if not hasattr(self, "_landuse"):
613
+ self._landuse = self._get_section("LANDUSE")
614
+
615
+ return self._landuse
616
+
617
+ @landuse.setter
618
+ def landuse(self, obj) -> None:
619
+ self._landuse = sc.LandUse._newobj(obj)
620
+
621
+ @property
622
+ def coverage(self) -> sc.Coverage:
623
+ "['Subcatchment', 'landuse', 'Percent', 'desc']"
624
+
625
+ if not hasattr(self, "_coverage"):
626
+ self._coverage = self._get_section("COVERAGE")
627
+
628
+ return self._coverage
629
+
630
+ @coverage.setter
631
+ def coverage(self, obj) -> None:
632
+ self._coverage = sc.Coverage._newobj(obj)
633
+
634
+ @property
635
+ def loading(self) -> sc.Loading:
636
+ "['Subcatchment', 'Pollutant', 'InitBuildup', 'desc']"
637
+
638
+ if not hasattr(self, "_loading"):
639
+ self._loading = self._get_section("LOADING")
640
+
641
+ return self._loading
642
+
643
+ @loading.setter
644
+ def loading(self, obj) -> None:
645
+ self._loading = sc.Loading._newobj(obj)
646
+
647
+ @property
648
+ def buildup(self) -> sc.Buildup:
649
+ "['Landuse', 'Pollutant', 'FuncType', 'C1', 'C2', 'C3', 'PerUnit', 'desc']"
650
+
651
+ if not hasattr(self, "_buildup"):
652
+ self._buildup = self._get_section("BUILDUP")
653
+
654
+ return self._buildup
655
+
656
+ @buildup.setter
657
+ def buildup(self, obj) -> None:
658
+ self._buildup = sc.Buildup._newobj(obj)
659
+
660
+ @property
661
+ def washoff(self) -> sc.Washoff:
662
+ "['Landuse', 'Pollutant', 'FuncType', 'C1', 'C2', 'SweepRmvl', 'BmpRmvl', 'desc']"
663
+
664
+ if not hasattr(self, "_washoff"):
665
+ self._washoff = self._get_section("WASHOFF")
666
+
667
+ return self._washoff
668
+
669
+ @washoff.setter
670
+ def washoff(self, obj) -> None:
671
+ self._washoff = sc.Washoff._newobj(obj)
672
+
673
+ @property
674
+ def treatment(self) -> sc.Treatment:
675
+ "['Node', 'Pollutant', 'Func', 'desc']"
676
+
677
+ if not hasattr(self, "_treatment"):
678
+ self._treatment = self._get_section("TREATMENT")
679
+
680
+ return self._treatment
681
+
682
+ @treatment.setter
683
+ def treatment(self, obj) -> None:
684
+ self._treatment = sc.Treatment._newobj(obj)
685
+
686
+ @property
687
+ def inflow(self) -> sc.Inflow:
688
+ "['Node', 'Constituent', 'TimeSeries', 'Type', 'Mfactor', 'Sfactor', 'Baseline', 'Pattern', 'desc']"
689
+
690
+ if not hasattr(self, "_inflow"):
691
+ self._inflow = self._get_section("INFLOW")
692
+
693
+ return self._inflow
694
+
695
+ @inflow.setter
696
+ def inflow(self, obj) -> None:
697
+ self._inflow = sc.Inflow._newobj(obj)
698
+
699
+ @property
700
+ def dwf(self) -> sc.DWF:
701
+ "['Node', 'Constituent', 'Baseline', 'Pat1', 'Pat2', 'Pat3', 'Pat4', 'desc']"
702
+
703
+ if not hasattr(self, "_dwf"):
704
+ self._dwf = self._get_section("DWF")
705
+
706
+ return self._dwf
707
+
708
+ @dwf.setter
709
+ def dwf(self, obj) -> None:
710
+ self._dwf = sc.DWF._newobj(obj)
711
+
712
+ @property
713
+ def rdii(self) -> sc.RDII:
714
+ "['Node', 'UHgroup', 'SewerArea', 'desc']"
715
+
716
+ if not hasattr(self, "_rdii"):
717
+ self._rdii = self._get_section("RDII")
718
+
719
+ return self._rdii
720
+
721
+ @rdii.setter
722
+ def rdii(self, obj) -> None:
723
+ self._rdii = sc.RDII._newobj(obj)
724
+
725
+ @property
726
+ def hydrographs(self) -> sc.Hydrographs:
727
+ "['Name', 'Month_RG', 'Response', 'R', 'T', 'K', 'IA_max', 'IA_rec', 'IA_ini', 'desc']"
728
+
729
+ if not hasattr(self, "_hydrographs"):
730
+ self._hydrographs = self._get_section("HYDROGRAPH")
731
+
732
+ return self._hydrographs
733
+
734
+ @hydrographs.setter
735
+ def hydrographs(self, obj) -> None:
736
+ self._hydrographs = sc.Hydrographs._newobj(obj)
737
+
738
+ @property
739
+ def curves(self) -> sc.Curves:
740
+ "['Name', 'Type', 'X_Value', 'Y_Value', 'desc']"
741
+
742
+ if not hasattr(self, "_curves"):
743
+ self._curves = self._get_section("CURVE")
744
+
745
+ return self._curves
746
+
747
+ @curves.setter
748
+ def curves(self, obj) -> None:
749
+ self._curves = sc.Curves._newobj(obj)
750
+
751
+ @property
752
+ def timeseries(self) -> sc.Timeseries:
753
+
754
+ if not hasattr(self, "_timeseries"):
755
+ self._timeseries = self._get_section("TIMESERIES")
756
+
757
+ return self._timeseries
758
+
759
+ @timeseries.setter
760
+ def timeseries(self, obj) -> None:
761
+ self._timeseries = sc.Timeseries._newobj(obj)
762
+
763
+ @property
764
+ def patterns(self) -> sc.Patterns:
765
+ "['Name', 'Type', 'Multiplier', 'desc']"
766
+
767
+ if not hasattr(self, "_patterns"):
768
+ self._patterns = self._get_section("PATTERN")
769
+
770
+ return self._patterns
771
+
772
+ @patterns.setter
773
+ def patterns(self, obj) -> None:
774
+ self._patterns = sc.Patterns._newobj(obj)
775
+
776
+ @property
777
+ def map(self) -> sc.Map:
778
+
779
+ if not hasattr(self, "_map"):
780
+ self._map = self._get_section("MAP")
781
+
782
+ return self._map
783
+
784
+ @map.setter
785
+ def map(self, obj) -> None:
786
+ self._map = sc.Map._newobj(obj)
787
+
788
+ @property
789
+ def polygons(self) -> sc.Polygons:
790
+ "['Subcatch', 'X', 'Y', 'desc']"
791
+
792
+ if not hasattr(self, "_polygons"):
793
+ self._polygons = self._get_section("POLYGON")
794
+
795
+ return self._polygons
796
+
797
+ @polygons.setter
798
+ def polygons(self, obj) -> None:
799
+ self._polygons = sc.Polygons._newobj(obj)
800
+
801
+ @property
802
+ def coordinates(self) -> sc.Coordinates:
803
+ "['Node', 'X', 'Y', 'desc']"
804
+
805
+ if not hasattr(self, "_coordinates"):
806
+ self._coordinates = self._get_section("COORDINATE")
807
+
808
+ return self._coordinates
809
+
810
+ @coordinates.setter
811
+ def coordinates(self, obj) -> None:
812
+ self._coordinates = sc.Coordinates._newobj(obj)
813
+
814
+ @property
815
+ def vertices(self) -> sc.Vertices:
816
+ "['Link', 'X', 'Y', 'desc']"
817
+
818
+ if not hasattr(self, "_vertices"):
819
+ self._vertices = self._get_section("VERTICES")
820
+
821
+ return self._vertices
822
+
823
+ @vertices.setter
824
+ def vertices(self, obj) -> None:
825
+ self._vertices = sc.Vertices._newobj(obj)
826
+
827
+ @property
828
+ def labels(self) -> sc.Labels:
829
+ "['Xcoord', 'Ycoord', 'Label', 'Anchor', 'Font', 'Size', 'Bold', 'Italic', 'desc']"
830
+
831
+ if not hasattr(self, "_labels"):
832
+ self._labels = self._get_section("LABEL")
833
+
834
+ return self._labels
835
+
836
+ @labels.setter
837
+ def labels(self, obj) -> None:
838
+ self._labels = sc.Labels._newobj(obj)
839
+
840
+ @property
841
+ def symbols(self) -> sc.Symbols:
842
+ "['Gage', 'X', 'Y', 'desc']"
843
+
844
+ if not hasattr(self, "_symbols"):
845
+ self._symbols = self._get_section("SYMBOL")
846
+
847
+ return self._symbols
848
+
849
+ @symbols.setter
850
+ def symbols(self, obj) -> None:
851
+ self._symbols = sc.Symbols._newobj(obj)
852
+
853
+ @property
854
+ def backdrop(self) -> sc.Backdrop:
855
+
856
+ if not hasattr(self, "_backdrop"):
857
+ self._backdrop = self._get_section("BACKDROP")
858
+
859
+ return self._backdrop
860
+
861
+ @backdrop.setter
862
+ def backdrop(self, obj) -> None:
863
+ self._backdrop = sc.Backdrop._newobj(obj)
864
+
865
+ @property
866
+ def profile(self) -> sc.Profile:
867
+
868
+ if not hasattr(self, "_profile"):
869
+ self._profile = self._get_section("PROFILE")
870
+
871
+ return self._profile
872
+
873
+ @profile.setter
874
+ def profile(self, obj) -> None:
875
+ self._profile = sc.Profile._newobj(obj)
876
+
877
+ @property
878
+ def tags(self) -> sc.Tags:
879
+ "['Element', 'Name', 'Tag', 'desc']"
880
+
881
+ if not hasattr(self, "_tags"):
882
+ self._tags = self._get_section("TAG")
883
+
884
+ return self._tags
885
+
886
+ @tags.setter
887
+ def tags(self, obj) -> None:
888
+ self._tags = sc.Tags._newobj(obj)