def __init__(self):
        """Define the fields of a SWMM Project by creating an empty placeholder for each section"""

        ProjectBase.__init__(self)

        self.title = Title()  # TITLE         project title
        self.options = General()  # OPTIONS       analysis options
        self.report = Report()  # REPORT        output reporting instructions
        self.files = Files()  # FILES         interface file options
        self.backdrop = BackdropOptions(
        )  # BACKDROP      bounding rectangle and file name of backdrop image
        self.map = MapOptions(
        )  # MAP           map's bounding rectangle and units
        self.raingages = SectionAsList(
            "[RAINGAGES]"
        )  # (list of RainGage)  # RAINGAGES  rain gage information

        self.hydrographs = SectionAsList(
            "[HYDROGRAPHS]")  # (list of UnitHydrograph)
        # unit hydrograph data used to construct RDII inflows

        self.evaporation = Evaporation()  # EVAPORATION   evaporation data
        self.temperature = Temperature(
        )  # TEMPERATURE   air temperature and snow melt data
        self.adjustments = Adjustments(
        )  # ADJUSTMENTS   monthly climate adjustments
        self.subcatchments = SectionAsList(
            "[SUBCATCHMENTS]")  # (list of Subcatchment)
        # basic subcatchment information

        # self.subareas = [Section]               # SUBAREAS      subcatchment impervious/pervious sub-area data

        self.infiltration = SectionAsList("[INFILTRATION]")  # (list of str)
        # subcatchment infiltration parameters

        self.lid_controls = SectionAsList(
            "[LID_CONTROLS]")  # (list of LIDControl)
        # low impact development control information

        self.lid_usage = SectionAsList("[LID_USAGE]")  # (list of LIDUsage)
        # assignment of LID controls to subcatchments

        self.aquifers = SectionAsList("[AQUIFERS]")  # (list of Aquifer)
        # groundwater aquifer parameters

        self.groundwater = SectionAsList(
            "[GROUNDWATER]")  # (list of Groundwater)
        # subcatchment groundwater parameters

        self.snowpacks = SectionAsList("[SNOWPACKS]")  # (list of SnowPack)
        # subcatchment snow pack parameters

        self.junctions = SectionAsList("[JUNCTIONS]")  # (list of Junction)
        # junction node information

        self.outfalls = SectionAsList("[OUTFALLS]")  # (list of Outfall)
        #  outfall node information

        self.dividers = SectionAsList("[DIVIDERS]")  # (list of Divider)
        #  flow divider node information

        self.storage = SectionAsList("[STORAGE]")  # (list of StorageUnit)
        #  storage node information

        self.conduits = SectionAsList("[CONDUITS]")  # (list of Conduit)
        # conduit link information

        self.pumps = SectionAsList("[PUMPS]")  # (list of Pump)
        # pump link information

        self.orifices = SectionAsList("[ORIFICES]")  # (list of Orifice)
        # orifice link information

        self.weirs = SectionAsList("[WEIRS]")  # (list of Weir)
        # weir link information

        self.outlets = SectionAsList("[OUTLETS]")  # (list of Outlet)
        # outlet link information

        self.xsections = SectionAsList("[XSECTIONS]")  # (list of CrossSection)
        # conduit, orifice, and weir cross-section geometry

        self.transects = Transects(
        )  # transect geometry for conduits with irregular cross-sections

        self.controls = Controls()
        # rules that control pump and regulator operation

        self.events = SectionAsList("[EVENTS]")  # (list of Events)

        self.landuses = SectionAsList(
            "[LANDUSES]")  # (list of Landuse)     # land use categories

        self.buildup = SectionAsList("[BUILDUP]")  # (list of Buildup)
        # buildup functions for pollutants and land uses

        self.washoff = SectionAsList("[WASHOFF]")  # (list of Washoff)
        # washoff functions for pollutants and land uses

        self.pollutants = SectionAsList("[POLLUTANTS]")  # (list of Pollutant)
        # pollutant information

        self.coverages = Coverages(
        )  # COVERAGES   assignment of land uses to subcatchments
        self.treatment = SectionAsList("[TREATMENT]")  # (list of Treatment)
        # pollutant removal functions at conveyance system nodes

        self.inflows = SectionAsList("[INFLOWS]")  # (list of DirectInflow)
        # INFLOWS # external hydrograph/pollutograph inflow at nodes

        self.dwf = SectionAsList("[DWF]")  # (list of DryWeatherInflow)
        # baseline dry weather sanitary inflow at nodes

        self.patterns = SectionAsList("[PATTERNS]")  # (list of Pattern)
        # periodic variation in dry weather inflow

        self.rdii = SectionAsList("[RDII]")  # (list of RDIInflow)
        # rainfall-dependent I/I information at nodes

        self.loadings = InitialLoadings()
        # initial pollutant loads on subcatchments

        self.curves = SectionAsList("[CURVES]")  # (list of Curve)
        # CURVES        x-y tabular data referenced in other sections

        self.timeseries = SectionAsList("[TIMESERIES]")  # (list of TimeSeries)
        # time series data referenced in other sections

        self.labels = SectionAsList("[LABELS]")  # (list of Label)
        # X, Y coordinates and text of labels

        self.subcentroids = SectionAsList(
            "[SUBCENTROIDS]")  # (list of subcentroids)
        # X, Y coordinates and text of subcentroids

        self.sublinks = SectionAsList("[SUBLINKS]")  # (list of sublinks)
        # sublinks information

        self.sections = [
            self.title, self.options, self.evaporation, self.raingages,
            self.subcatchments, self.infiltration, self.junctions,
            self.dividers, self.storage, self.outfalls, self.conduits,
            self.pumps, self.orifices, self.weirs, self.outlets,
            self.xsections, self.landuses, self.coverages, self.pollutants,
            self.timeseries, self.patterns, self.curves, self.dwf, self.rdii,
            self.loadings, self.buildup, self.washoff, self.report,
            self.events, self.files, self.backdrop, self.map, self.hydrographs,
            self.temperature, self.adjustments, self.lid_controls,
            self.lid_usage, self.aquifers, self.groundwater, self.snowpacks,
            self.transects, self.controls, self.treatment, self.inflows,
            self.labels, self.subcentroids, self.sublinks
        ]  # Start with a sensible order of sections.
        self.add_sections_from_attributes(
        )  # Add any sections not added in the line above, should not be any left.
class OptionsGeneralTest(unittest.TestCase):
    """Test OPTIONS section
     In core.swmm.options, test field values after setting from text.
     This primarily tests General, but also tests Dates, TimeSteps, and DynamicWave since those are set from General.
    """

    TEST_TEXT = (("""[OPTIONS]
 FLOW_UNITS            \tCFS
 INFILTRATION          \tHORTON
 FLOW_ROUTING          \tKW
 START_DATE            \t01/01/1998
 START_TIME            \t00:00:00
 REPORT_START_DATE     \t01/01/1998
 REPORT_START_TIME     \t00:00:00
 END_DATE              \t01/02/1998
 END_TIME              \t12:00:00
 DRY_DAYS              \t5
 WET_STEP              \t00:15:00
 DRY_STEP              \t01:00:00
 ROUTING_STEP          \t00:01:00
 REPORT_STEP           \t01:00:00
 ALLOW_PONDING         \tNO
 INERTIAL_DAMPING      \tPARTIAL
 VARIABLE_STEP         \t0.75
 LENGTHENING_STEP      \t0
 MIN_SURFAREA          \t0
 COMPATIBILITY         \t5
 IGNORE_GROUNDWATER    \tYES""", FlowUnits.CFS, "HORTON", FlowRouting.KINWAVE,
                  "01/01/1998", "00:00:00", "01/01/1998", "00:00:00",
                  "01/02/1998", "12:00:00", "5", "00:15:00", "01:00:00",
                  "00:01:00", "01:00:00", False, "PARTIAL", "0.75", "0", "0",
                  "5", True),
                 ("""[OPTIONS]
 FLOW_UNITS            \tMGD
 INFILTRATION          \tGREEN_AMPT
 FLOW_ROUTING          \tDYNWAVE
 START_DATE            \t02/02/2000
 START_TIME            \t00:01:00
 REPORT_START_DATE     \t02/03/2000
 REPORT_START_TIME     \t00:02:00
 END_DATE              \t02/04/2000
 END_TIME              \t12:30:00
 DRY_DAYS              \t4
 WET_STEP              \t00:30:00
 DRY_STEP              \t01:30:00
 ROUTING_STEP          \t00:02:00
 REPORT_STEP           \t02:00:00
 ALLOW_PONDING         \tYES
 INERTIAL_DAMPING      \tPARTIAL
 VARIABLE_STEP         \t0.6
 LENGTHENING_STEP      \t1
 MIN_SURFAREA          \t2
 COMPATIBILITY         \t4
 IGNORE_GROUNDWATER    \tNO""", FlowUnits.MGD, "GREEN_AMPT",
                  FlowRouting.DYNWAVE, "02/02/2000", "00:01:00", "02/03/2000",
                  "00:02:00", "02/04/2000", "12:30:00", "4", "00:30:00",
                  "01:30:00", "00:02:00", "02:00:00", True, "PARTIAL", "0.6",
                  "1", "2", "4", False))

    def test_all_opts(self):
        """Test all default values specified in 5.1"""
        test_all_ops = r"""[OPTIONS]
FLOW_UNITS CFS
INFILTRATION HORTON
FLOW_ROUTING KINWAVE
LINK_OFFSETS DEPTH
FORCE_MAIN_EQUATION H-W
IGNORE_RAINFALL NO
IGNORE_SNOWMELT NO
IGNORE_GROUNDWATER NO
IGNORE_RDII NO
IGNORE_ROUTING NO
IGNORE_QUALITY NO
ALLOW_PONDING NO
SKIP_STEADY_STATE NO
SYS_FLOW_TOL 5
LAT_FLOW_TOL 5
START_DATE 1/1/2002
START_TIME 0:00:00
END_DATE 1/1/2002
END_TIME 24:00:00
REPORT_START_DATE 4/11/2016
REPORT_START_TIME 09:00:00
SWEEP_START 1/1
SWEEP_END 12/31
DRY_DAYS 0
REPORT_STEP 0:15:00
WET_STEP 0:05:00
DRY_STEP 1:00:00
ROUTING_STEP 600
LENGTHENING_STEP 0
VARIABLE_STEP 0
MINIMUM_STEP 0.5
INERTIAL_DAMPING NONE
NORMAL_FLOW_LIMITED BOTH
MIN_SURFAREA 0
MIN_SLOPE 0
MAX_TRIALS 8
HEAD_TOLERANCE 0.005
THREADS 1
TEMPDIR .\temp"""

        self.options = General()
        # Set_text
        self.options.set_text(test_all_ops)

        # Assert attributes
        assert self.options.flow_units == FlowUnits.CFS
        assert self.options.flow_routing == FlowRouting.KINWAVE
        assert self.options.ignore_snowmelt == False
        assert self.options.ignore_groundwater == False
        assert self.options.ignore_rdii == False
        assert self.options.dates.start_date == '1/1/2002'
        assert self.options.dates.start_time == '0:00:00'
        assert float(self.options.time_steps.system_flow_tolerance) == 5.0
        assert float(self.options.time_steps.lateral_inflow_tolerance) == 5.0
        assert self.options.temp_dir == r'.\temp'

        # Get_text
        actual_text = self.options.get_text()

        # Set_text again
        self.options.set_text(actual_text)
        assert self.options.flow_units == FlowUnits.CFS
        assert self.options.flow_routing == FlowRouting.KINWAVE
        assert self.options.ignore_snowmelt == False
        assert self.options.ignore_rdii == False
        assert self.options.dates.start_date == '1/1/2002'
        assert self.options.dates.start_time == '0:00:00'
        assert self.options.matches(test_all_ops), 'incorrect title block'

    def test_current_text(self):
        """Test setting from the current text array"""
        self.options = General()
        for current_text in self.TEST_TEXT:
            self.options.set_text(current_text[0])
            assert self.options.flow_units == current_text[1]
            assert self.options.infiltration == current_text[2]
            assert self.options.flow_routing == current_text[3]
            assert self.options.dates.start_date == current_text[4]
            assert self.options.dates.start_time == current_text[5]
            assert self.options.dates.report_start_date == current_text[6]
            assert self.options.dates.report_start_time == current_text[7]
            assert self.options.dates.end_date == current_text[8]
            assert self.options.dates.end_time == current_text[9]
            assert int(self.options.dates.dry_days) == int(current_text[10])
            assert self.options.time_steps.wet_step == current_text[11]
            assert self.options.time_steps.dry_step == current_text[12]
            assert self.options.time_steps.routing_step == current_text[13]
            assert self.options.time_steps.report_step == current_text[14]
            assert self.options.allow_ponding == current_text[15]
            assert self.options.dynamic_wave.inertial_damping.name == current_text[
                16]
            assert float(self.options.dynamic_wave.variable_step) == float(
                current_text[17])
            assert int(self.options.dynamic_wave.lengthening_step) == int(
                current_text[18])
            assert float(self.options.dynamic_wave.min_surface_area) == float(
                current_text[19])
            assert int(self.options.compatibility) == int(current_text[20])
            assert self.options.ignore_groundwater == current_text[21]

        expected_text = "[OPTIONS]\n"\
                        " IGNORE_GROUNDWATER 	NO\n"\
                        " IGNORE_QUALITY     	NO\n"\
                        " IGNORE_ROUTING     	NO\n"\
                        " LINK_OFFSETS       	DEPTH\n"\
                        " FLOW_UNITS         	MGD\n"\
                        " MIN_SLOPE          	0.0\n"\
                        " INFILTRATION       	GREEN_AMPT\n"\
                        " ALLOW_PONDING      	YES\n"\
                        " IGNORE_SNOWMELT    	NO\n"\
                        " IGNORE_RDII        	NO\n"\
                        " IGNORE_RAINFALL    	NO\n"\
                        " COMPATIBILITY      	4\n"\
                        " FLOW_ROUTING       	DYNWAVE\n"\
                        ";; Dates\n"\
                        " END_TIME           	12:30:00\n"\
                        " END_DATE           	02/04/2000\n"\
                        " SWEEP_END          	12/31\n"\
                        " START_TIME         	00:01:00\n"\
                        " DRY_DAYS           	4\n"\
                        " REPORT_START_TIME  	00:02:00\n"\
                        " START_DATE         	02/02/2000\n"\
                        " SWEEP_START        	1/1\n"\
                        " REPORT_START_DATE  	02/03/2000\n"\
                        ";; Time Steps\n"\
                        " SKIP_STEADY_STATE  	NO\n"\
                        " LAT_FLOW_TOL       	5\n"\
                        " DRY_STEP           	01:30:00\n"\
                        " REPORT_STEP        	02:00:00\n"\
                        " WET_STEP           	00:30:00\n"\
                        " SYS_FLOW_TOL       	5\n"\
                        " ROUTING_STEP       	00:02:00\n"\
                        ";; Dynamic Wave\n"\
                        " LENGTHENING_STEP   	1.0\n"\
                        " VARIABLE_STEP      	0.6\n"\
                        " INERTIAL_DAMPING   	PARTIAL\n"\
                        " FORCE_MAIN_EQUATION	H-W\n"\
                        " NORMAL_FLOW_LIMITED	BOTH\n"\
                        " MAX_TRIALS         	8\n"\
                        " MIN_SURFAREA       	2.0\n"\
                        " HEAD_TOLERANCE     	0.005\n"\
                        " THREADS            	1\n"\
                        " MINIMUM_STEP       	0.5"

        self.options.set_text(expected_text)
        actual_text = self.options.get_text()
        assert self.options.matches(expected_text)
    def test_all_opts(self):
        """Test all default values specified in 5.1"""
        test_all_ops = r"""[OPTIONS]
FLOW_UNITS CFS
INFILTRATION HORTON
FLOW_ROUTING KINWAVE
LINK_OFFSETS DEPTH
FORCE_MAIN_EQUATION H-W
IGNORE_RAINFALL NO
IGNORE_SNOWMELT NO
IGNORE_GROUNDWATER NO
IGNORE_RDII NO
IGNORE_ROUTING NO
IGNORE_QUALITY NO
ALLOW_PONDING NO
SKIP_STEADY_STATE NO
SYS_FLOW_TOL 5
LAT_FLOW_TOL 5
START_DATE 1/1/2002
START_TIME 0:00:00
END_DATE 1/1/2002
END_TIME 24:00:00
REPORT_START_DATE 4/11/2016
REPORT_START_TIME 09:00:00
SWEEP_START 1/1
SWEEP_END 12/31
DRY_DAYS 0
REPORT_STEP 0:15:00
WET_STEP 0:05:00
DRY_STEP 1:00:00
ROUTING_STEP 600
LENGTHENING_STEP 0
VARIABLE_STEP 0
MINIMUM_STEP 0.5
INERTIAL_DAMPING NONE
NORMAL_FLOW_LIMITED BOTH
MIN_SURFAREA 0
MIN_SLOPE 0
MAX_TRIALS 8
HEAD_TOLERANCE 0.005
THREADS 1
TEMPDIR .\temp"""

        self.options = General()
        # Set_text
        self.options.set_text(test_all_ops)

        # Assert attributes
        assert self.options.flow_units == FlowUnits.CFS
        assert self.options.flow_routing == FlowRouting.KINWAVE
        assert self.options.ignore_snowmelt == False
        assert self.options.ignore_groundwater == False
        assert self.options.ignore_rdii == False
        assert self.options.dates.start_date == '1/1/2002'
        assert self.options.dates.start_time == '0:00:00'
        assert float(self.options.time_steps.system_flow_tolerance) == 5.0
        assert float(self.options.time_steps.lateral_inflow_tolerance) == 5.0
        assert self.options.temp_dir == r'.\temp'

        # Get_text
        actual_text = self.options.get_text()

        # Set_text again
        self.options.set_text(actual_text)
        assert self.options.flow_units == FlowUnits.CFS
        assert self.options.flow_routing == FlowRouting.KINWAVE
        assert self.options.ignore_snowmelt == False
        assert self.options.ignore_rdii == False
        assert self.options.dates.start_date == '1/1/2002'
        assert self.options.dates.start_time == '0:00:00'
        assert self.options.matches(test_all_ops), 'incorrect title block'
    def test_current_text(self):
        """Test setting from the current text array"""
        self.options = General()
        for current_text in self.TEST_TEXT:
            self.options.set_text(current_text[0])
            assert self.options.flow_units == current_text[1]
            assert self.options.infiltration == current_text[2]
            assert self.options.flow_routing == current_text[3]
            assert self.options.dates.start_date == current_text[4]
            assert self.options.dates.start_time == current_text[5]
            assert self.options.dates.report_start_date == current_text[6]
            assert self.options.dates.report_start_time == current_text[7]
            assert self.options.dates.end_date == current_text[8]
            assert self.options.dates.end_time == current_text[9]
            assert int(self.options.dates.dry_days) == int(current_text[10])
            assert self.options.time_steps.wet_step == current_text[11]
            assert self.options.time_steps.dry_step == current_text[12]
            assert self.options.time_steps.routing_step == current_text[13]
            assert self.options.time_steps.report_step == current_text[14]
            assert self.options.allow_ponding == current_text[15]
            assert self.options.dynamic_wave.inertial_damping.name == current_text[
                16]
            assert float(self.options.dynamic_wave.variable_step) == float(
                current_text[17])
            assert int(self.options.dynamic_wave.lengthening_step) == int(
                current_text[18])
            assert float(self.options.dynamic_wave.min_surface_area) == float(
                current_text[19])
            assert int(self.options.compatibility) == int(current_text[20])
            assert self.options.ignore_groundwater == current_text[21]

        expected_text = "[OPTIONS]\n"\
                        " IGNORE_GROUNDWATER 	NO\n"\
                        " IGNORE_QUALITY     	NO\n"\
                        " IGNORE_ROUTING     	NO\n"\
                        " LINK_OFFSETS       	DEPTH\n"\
                        " FLOW_UNITS         	MGD\n"\
                        " MIN_SLOPE          	0.0\n"\
                        " INFILTRATION       	GREEN_AMPT\n"\
                        " ALLOW_PONDING      	YES\n"\
                        " IGNORE_SNOWMELT    	NO\n"\
                        " IGNORE_RDII        	NO\n"\
                        " IGNORE_RAINFALL    	NO\n"\
                        " COMPATIBILITY      	4\n"\
                        " FLOW_ROUTING       	DYNWAVE\n"\
                        ";; Dates\n"\
                        " END_TIME           	12:30:00\n"\
                        " END_DATE           	02/04/2000\n"\
                        " SWEEP_END          	12/31\n"\
                        " START_TIME         	00:01:00\n"\
                        " DRY_DAYS           	4\n"\
                        " REPORT_START_TIME  	00:02:00\n"\
                        " START_DATE         	02/02/2000\n"\
                        " SWEEP_START        	1/1\n"\
                        " REPORT_START_DATE  	02/03/2000\n"\
                        ";; Time Steps\n"\
                        " SKIP_STEADY_STATE  	NO\n"\
                        " LAT_FLOW_TOL       	5\n"\
                        " DRY_STEP           	01:30:00\n"\
                        " REPORT_STEP        	02:00:00\n"\
                        " WET_STEP           	00:30:00\n"\
                        " SYS_FLOW_TOL       	5\n"\
                        " ROUTING_STEP       	00:02:00\n"\
                        ";; Dynamic Wave\n"\
                        " LENGTHENING_STEP   	1.0\n"\
                        " VARIABLE_STEP      	0.6\n"\
                        " INERTIAL_DAMPING   	PARTIAL\n"\
                        " FORCE_MAIN_EQUATION	H-W\n"\
                        " NORMAL_FLOW_LIMITED	BOTH\n"\
                        " MAX_TRIALS         	8\n"\
                        " MIN_SURFAREA       	2.0\n"\
                        " HEAD_TOLERANCE     	0.005\n"\
                        " THREADS            	1\n"\
                        " MINIMUM_STEP       	0.5"

        self.options.set_text(expected_text)
        actual_text = self.options.get_text()
        assert self.options.matches(expected_text)
class OptionsGeneralTest(unittest.TestCase):
    """Test OPTIONS section
     In core.swmm.options, test field values after setting from text.
     This primarily tests General, but also tests Dates, TimeSteps, and DynamicWave since those are set from General.
    """

    TEST_TEXT = (
        ("""[OPTIONS]
 FLOW_UNITS            \tCFS
 INFILTRATION          \tHORTON
 FLOW_ROUTING          \tKW
 START_DATE            \t01/01/1998
 START_TIME            \t00:00:00
 REPORT_START_DATE     \t01/01/1998
 REPORT_START_TIME     \t00:00:00
 END_DATE              \t01/02/1998
 END_TIME              \t12:00:00
 DRY_DAYS              \t5
 WET_STEP              \t00:15:00
 DRY_STEP              \t01:00:00
 ROUTING_STEP          \t00:01:00
 REPORT_STEP           \t01:00:00
 ALLOW_PONDING         \tNO
 INERTIAL_DAMPING      \tPARTIAL
 VARIABLE_STEP         \t0.75
 LENGTHENING_STEP      \t0
 MIN_SURFAREA          \t0
 COMPATIBILITY         \t5
 IGNORE_GROUNDWATER    \tYES""",

         FlowUnits.CFS,
         "HORTON",
         FlowRouting.KINWAVE,
         "01/01/1998",
         "00:00:00",
         "01/01/1998",
         "00:00:00",
         "01/02/1998",
         "12:00:00",
         "5",
         "00:15:00",
         "01:00:00",
         "00:01:00",
         "01:00:00",
         False,
         "PARTIAL",
         "0.75",
         "0",
         "0",
         "5",
         True),
        ("""[OPTIONS]
 FLOW_UNITS            \tMGD
 INFILTRATION          \tGREEN_AMPT
 FLOW_ROUTING          \tDYNWAVE
 START_DATE            \t02/02/2000
 START_TIME            \t00:01:00
 REPORT_START_DATE     \t02/03/2000
 REPORT_START_TIME     \t00:02:00
 END_DATE              \t02/04/2000
 END_TIME              \t12:30:00
 DRY_DAYS              \t4
 WET_STEP              \t00:30:00
 DRY_STEP              \t01:30:00
 ROUTING_STEP          \t00:02:00
 REPORT_STEP           \t02:00:00
 ALLOW_PONDING         \tYES
 INERTIAL_DAMPING      \tPARTIAL
 VARIABLE_STEP         \t0.6
 LENGTHENING_STEP      \t1
 MIN_SURFAREA          \t2
 COMPATIBILITY         \t4
 IGNORE_GROUNDWATER    \tNO""",

         FlowUnits.MGD,
         "GREEN_AMPT",
         FlowRouting.DYNWAVE,
         "02/02/2000",
         "00:01:00",
         "02/03/2000",
         "00:02:00",
         "02/04/2000",
         "12:30:00",
         "4",
         "00:30:00",
         "01:30:00",
         "00:02:00",
         "02:00:00",
         True,
         "PARTIAL",
         "0.6",
         "1",
         "2",
         "4",
         False)
    )

    def test_all_opts(self):
        """Test all default values specified in 5.1"""
        test_all_ops = r"""[OPTIONS]
FLOW_UNITS CFS
INFILTRATION HORTON
FLOW_ROUTING KINWAVE
LINK_OFFSETS DEPTH
FORCE_MAIN_EQUATION H-W
IGNORE_RAINFALL NO
IGNORE_SNOWMELT NO
IGNORE_GROUNDWATER NO
IGNORE_RDII NO
IGNORE_ROUTING NO
IGNORE_QUALITY NO
ALLOW_PONDING NO
SKIP_STEADY_STATE NO
SYS_FLOW_TOL 5
LAT_FLOW_TOL 5
START_DATE 1/1/2002
START_TIME 0:00:00
END_DATE 1/1/2002
END_TIME 24:00:00
REPORT_START_DATE 4/11/2016
REPORT_START_TIME 09:00:00
SWEEP_START 1/1
SWEEP_END 12/31
DRY_DAYS 0
REPORT_STEP 0:15:00
WET_STEP 0:05:00
DRY_STEP 1:00:00
ROUTING_STEP 600
LENGTHENING_STEP 0
VARIABLE_STEP 0
MINIMUM_STEP 0.5
INERTIAL_DAMPING NONE
NORMAL_FLOW_LIMITED BOTH
MIN_SURFAREA 0
MIN_SLOPE 0
MAX_TRIALS 8
HEAD_TOLERANCE 0.005
THREADS 1
TEMPDIR .\temp"""

        self.options = General()
        # Set_text
        self.options.set_text(test_all_ops)

        # Assert attributes
        assert self.options.flow_units == FlowUnits.CFS
        assert self.options.flow_routing == FlowRouting.KINWAVE
        assert self.options.ignore_snowmelt == False
        assert self.options.ignore_groundwater == False
        assert self.options.ignore_rdii == False
        assert self.options.dates.start_date == '1/1/2002'
        assert self.options.dates.start_time == '0:00:00'
        assert float(self.options.time_steps.system_flow_tolerance) == 5.0
        assert float(self.options.time_steps.lateral_inflow_tolerance) == 5.0
        assert self.options.temp_dir == r'.\temp'

        # Get_text
        actual_text = self.options.get_text()

        # Set_text again
        self.options.set_text(actual_text)
        assert self.options.flow_units == FlowUnits.CFS
        assert self.options.flow_routing == FlowRouting.KINWAVE
        assert self.options.ignore_snowmelt == False
        assert self.options.ignore_rdii == False
        assert self.options.dates.start_date == '1/1/2002'
        assert self.options.dates.start_time == '0:00:00'
        assert self.options.matches(test_all_ops), 'incorrect title block'

    def test_current_text(self):
        """Test setting from the current text array"""
        self.options = General()
        for current_text in self.TEST_TEXT:
            self.options.set_text(current_text[0])
            assert self.options.flow_units == current_text[1]
            assert self.options.infiltration == current_text[2]
            assert self.options.flow_routing == current_text[3]
            assert self.options.dates.start_date == current_text[4]
            assert self.options.dates.start_time == current_text[5]
            assert self.options.dates.report_start_date == current_text[6]
            assert self.options.dates.report_start_time == current_text[7]
            assert self.options.dates.end_date == current_text[8]
            assert self.options.dates.end_time == current_text[9]
            assert int(self.options.dates.dry_days) == int(current_text[10])
            assert self.options.time_steps.wet_step == current_text[11]
            assert self.options.time_steps.dry_step == current_text[12]
            assert self.options.time_steps.routing_step == current_text[13]
            assert self.options.time_steps.report_step == current_text[14]
            assert self.options.allow_ponding == current_text[15]
            assert self.options.dynamic_wave.inertial_damping.name == current_text[16]
            assert float(self.options.dynamic_wave.variable_step) == float(current_text[17])
            assert int(self.options.dynamic_wave.lengthening_step) == int(current_text[18])
            assert float(self.options.dynamic_wave.min_surface_area) == float(current_text[19])
            assert int(self.options.compatibility) == int(current_text[20])
            assert self.options.ignore_groundwater == current_text[21]

        expected_text = "[OPTIONS]\n"\
                        " IGNORE_GROUNDWATER 	NO\n"\
                        " IGNORE_QUALITY     	NO\n"\
                        " IGNORE_ROUTING     	NO\n"\
                        " LINK_OFFSETS       	DEPTH\n"\
                        " FLOW_UNITS         	MGD\n"\
                        " MIN_SLOPE          	0.0\n"\
                        " INFILTRATION       	GREEN_AMPT\n"\
                        " ALLOW_PONDING      	YES\n"\
                        " IGNORE_SNOWMELT    	NO\n"\
                        " IGNORE_RDII        	NO\n"\
                        " IGNORE_RAINFALL    	NO\n"\
                        " COMPATIBILITY      	4\n"\
                        " FLOW_ROUTING       	DYNWAVE\n"\
                        ";; Dates\n"\
                        " END_TIME           	12:30:00\n"\
                        " END_DATE           	02/04/2000\n"\
                        " SWEEP_END          	12/31\n"\
                        " START_TIME         	00:01:00\n"\
                        " DRY_DAYS           	4\n"\
                        " REPORT_START_TIME  	00:02:00\n"\
                        " START_DATE         	02/02/2000\n"\
                        " SWEEP_START        	1/1\n"\
                        " REPORT_START_DATE  	02/03/2000\n"\
                        ";; Time Steps\n"\
                        " SKIP_STEADY_STATE  	NO\n"\
                        " LAT_FLOW_TOL       	5\n"\
                        " DRY_STEP           	01:30:00\n"\
                        " REPORT_STEP        	02:00:00\n"\
                        " WET_STEP           	00:30:00\n"\
                        " SYS_FLOW_TOL       	5\n"\
                        " ROUTING_STEP       	00:02:00\n"\
                        ";; Dynamic Wave\n"\
                        " LENGTHENING_STEP   	1.0\n"\
                        " VARIABLE_STEP      	0.6\n"\
                        " INERTIAL_DAMPING   	PARTIAL\n"\
                        " FORCE_MAIN_EQUATION	H-W\n"\
                        " NORMAL_FLOW_LIMITED	BOTH\n"\
                        " MAX_TRIALS         	8\n"\
                        " MIN_SURFAREA       	2.0\n"\
                        " HEAD_TOLERANCE     	0.005\n"\
                        " THREADS            	1\n"\
                        " MINIMUM_STEP       	0.5"

        self.options.set_text(expected_text)
        actual_text = self.options.get_text()
        assert self.options.matches(expected_text)
    def test_current_text(self):
        """Test setting from the current text array"""
        self.options = General()
        for current_text in self.TEST_TEXT:
            self.options.set_text(current_text[0])
            assert self.options.flow_units == current_text[1]
            assert self.options.infiltration == current_text[2]
            assert self.options.flow_routing == current_text[3]
            assert self.options.dates.start_date == current_text[4]
            assert self.options.dates.start_time == current_text[5]
            assert self.options.dates.report_start_date == current_text[6]
            assert self.options.dates.report_start_time == current_text[7]
            assert self.options.dates.end_date == current_text[8]
            assert self.options.dates.end_time == current_text[9]
            assert int(self.options.dates.dry_days) == int(current_text[10])
            assert self.options.time_steps.wet_step == current_text[11]
            assert self.options.time_steps.dry_step == current_text[12]
            assert self.options.time_steps.routing_step == current_text[13]
            assert self.options.time_steps.report_step == current_text[14]
            assert self.options.allow_ponding == current_text[15]
            assert self.options.dynamic_wave.inertial_damping.name == current_text[16]
            assert float(self.options.dynamic_wave.variable_step) == float(current_text[17])
            assert int(self.options.dynamic_wave.lengthening_step) == int(current_text[18])
            assert float(self.options.dynamic_wave.min_surface_area) == float(current_text[19])
            assert int(self.options.compatibility) == int(current_text[20])
            assert self.options.ignore_groundwater == current_text[21]

        expected_text = "[OPTIONS]\n"\
                        " IGNORE_GROUNDWATER 	NO\n"\
                        " IGNORE_QUALITY     	NO\n"\
                        " IGNORE_ROUTING     	NO\n"\
                        " LINK_OFFSETS       	DEPTH\n"\
                        " FLOW_UNITS         	MGD\n"\
                        " MIN_SLOPE          	0.0\n"\
                        " INFILTRATION       	GREEN_AMPT\n"\
                        " ALLOW_PONDING      	YES\n"\
                        " IGNORE_SNOWMELT    	NO\n"\
                        " IGNORE_RDII        	NO\n"\
                        " IGNORE_RAINFALL    	NO\n"\
                        " COMPATIBILITY      	4\n"\
                        " FLOW_ROUTING       	DYNWAVE\n"\
                        ";; Dates\n"\
                        " END_TIME           	12:30:00\n"\
                        " END_DATE           	02/04/2000\n"\
                        " SWEEP_END          	12/31\n"\
                        " START_TIME         	00:01:00\n"\
                        " DRY_DAYS           	4\n"\
                        " REPORT_START_TIME  	00:02:00\n"\
                        " START_DATE         	02/02/2000\n"\
                        " SWEEP_START        	1/1\n"\
                        " REPORT_START_DATE  	02/03/2000\n"\
                        ";; Time Steps\n"\
                        " SKIP_STEADY_STATE  	NO\n"\
                        " LAT_FLOW_TOL       	5\n"\
                        " DRY_STEP           	01:30:00\n"\
                        " REPORT_STEP        	02:00:00\n"\
                        " WET_STEP           	00:30:00\n"\
                        " SYS_FLOW_TOL       	5\n"\
                        " ROUTING_STEP       	00:02:00\n"\
                        ";; Dynamic Wave\n"\
                        " LENGTHENING_STEP   	1.0\n"\
                        " VARIABLE_STEP      	0.6\n"\
                        " INERTIAL_DAMPING   	PARTIAL\n"\
                        " FORCE_MAIN_EQUATION	H-W\n"\
                        " NORMAL_FLOW_LIMITED	BOTH\n"\
                        " MAX_TRIALS         	8\n"\
                        " MIN_SURFAREA       	2.0\n"\
                        " HEAD_TOLERANCE     	0.005\n"\
                        " THREADS            	1\n"\
                        " MINIMUM_STEP       	0.5"

        self.options.set_text(expected_text)
        actual_text = self.options.get_text()
        assert self.options.matches(expected_text)
    def test_all_opts(self):
        """Test all default values specified in 5.1"""
        test_all_ops = r"""[OPTIONS]
FLOW_UNITS CFS
INFILTRATION HORTON
FLOW_ROUTING KINWAVE
LINK_OFFSETS DEPTH
FORCE_MAIN_EQUATION H-W
IGNORE_RAINFALL NO
IGNORE_SNOWMELT NO
IGNORE_GROUNDWATER NO
IGNORE_RDII NO
IGNORE_ROUTING NO
IGNORE_QUALITY NO
ALLOW_PONDING NO
SKIP_STEADY_STATE NO
SYS_FLOW_TOL 5
LAT_FLOW_TOL 5
START_DATE 1/1/2002
START_TIME 0:00:00
END_DATE 1/1/2002
END_TIME 24:00:00
REPORT_START_DATE 4/11/2016
REPORT_START_TIME 09:00:00
SWEEP_START 1/1
SWEEP_END 12/31
DRY_DAYS 0
REPORT_STEP 0:15:00
WET_STEP 0:05:00
DRY_STEP 1:00:00
ROUTING_STEP 600
LENGTHENING_STEP 0
VARIABLE_STEP 0
MINIMUM_STEP 0.5
INERTIAL_DAMPING NONE
NORMAL_FLOW_LIMITED BOTH
MIN_SURFAREA 0
MIN_SLOPE 0
MAX_TRIALS 8
HEAD_TOLERANCE 0.005
THREADS 1
TEMPDIR .\temp"""

        self.options = General()
        # Set_text
        self.options.set_text(test_all_ops)

        # Assert attributes
        assert self.options.flow_units == FlowUnits.CFS
        assert self.options.flow_routing == FlowRouting.KINWAVE
        assert self.options.ignore_snowmelt == False
        assert self.options.ignore_groundwater == False
        assert self.options.ignore_rdii == False
        assert self.options.dates.start_date == '1/1/2002'
        assert self.options.dates.start_time == '0:00:00'
        assert float(self.options.time_steps.system_flow_tolerance) == 5.0
        assert float(self.options.time_steps.lateral_inflow_tolerance) == 5.0
        assert self.options.temp_dir == r'.\temp'

        # Get_text
        actual_text = self.options.get_text()

        # Set_text again
        self.options.set_text(actual_text)
        assert self.options.flow_units == FlowUnits.CFS
        assert self.options.flow_routing == FlowRouting.KINWAVE
        assert self.options.ignore_snowmelt == False
        assert self.options.ignore_rdii == False
        assert self.options.dates.start_date == '1/1/2002'
        assert self.options.dates.start_time == '0:00:00'
        assert self.options.matches(test_all_ops), 'incorrect title block'
예제 #8
0
    def __init__(self):
        """Define the fields of a SWMM Project by creating an empty placeholder for each section"""

        self.title = Title()  # TITLE         project title
        self.options = General()  # OPTIONS       analysis options
        self.report = Report()  # REPORT        output reporting instructions
        self.files = Files()  # FILES         interface file options
        self.backdrop = BackdropOptions(
        )  # BACKDROP      bounding rectangle and file name of backdrop image
        self.map = MapOptions(
        )  # MAP           map's bounding rectangle and units
        # self.raingages = [RainGage]             # RAINGAGES     rain gage information
        self.hydrographs = SectionAsListGroupByID(
            "[HYDROGRAPHS]", UnitHydrograph,
            ";;Hydrograph    \tRain Gage/Month \tResponse\tR       \tT       \tK       \tDmax    \tDrecov  \tDinit   \n"
            ";;--------------\t----------------\t--------\t--------\t--------\t--------\t--------\t--------\t--------"
        )
        # unit hydrograph data used to construct RDII inflows

        self.evaporation = Evaporation()  # EVAPORATION   evaporation data
        self.temperature = Temperature(
        )  # TEMPERATURE   air temperature and snow melt data
        self.adjustments = Adjustments(
        )  # ADJUSTMENTS   monthly climate adjustments
        self.subcatchments = SectionAsListOf(
            "[SUBCATCHMENTS]", Subcatchment,
            ";;Name          \tRain Gage       \tOutlet          \tArea    \t%Imperv \tWidth   \t%Slope  \tCurbLen \tSnowPack        \n"
            ";;--------------\t----------------\t----------------\t--------\t--------\t--------\t--------\t--------\t----------------"
        )
        # basic subcatchment information

        # self.subareas = [Section]               # SUBAREAS      subcatchment impervious/pervious sub-area data

        self.infiltration = SectionAsListOf("[INFILTRATION]", basestring)
        # This is set to SectionAsListOf HortonInfiltration or GreenAmptInfiltration or CurveNumberInfiltration on read
        # subcatchment infiltration parameters

        self.lid_controls = SectionAsListGroupByID(
            "[LID_CONTROLS]", LIDControl,
            ";;Name          \tType/Layer\tParameters\n"
            ";;--------------\t----------\t----------")
        # low impact development control information

        self.lid_usage = SectionAsListOf(
            "[LID_USAGE]", LIDUsage,
            ";;Subcatchment  \tLID Process     \tNumber \tArea      \tWidth     \tInitSat   \tFromImp   \tToPerv    \tRptFile                 \tDrainTo\n"
            ";;--------------\t----------------\t-------\t----------\t----------\t----------\t----------\t----------\t------------------------\t----------------"
        )
        # assignment of LID controls to subcatchments

        self.aquifers = SectionAsListOf(
            "[AQUIFERS]", Aquifer,
            ";;Aquifer       \tPhi   \tWP    \tFC    \tHydCon\tKslope\tTslope\tUEF   \tLED   \tLGLR  \tBEL   \tWTEL  \tUZM   \tUEF Pat\n"
            ";;--------------\t------\t------\t------\t------\t------\t------\t------\t------\t------\t------\t------\t------\t-------"
        )
        # groundwater aquifer parameters

        self.groundwater = SectionAsListOf(
            "[GROUNDWATER]", Groundwater,
            ";;Subcatchment  \tAquifer         \tNode            \tEsurf \tA1    \tB1    \tA2    \tB2    \tA3    \tDsw   \tEgwt  \tEbot  \tWgr   \tUmc   \n"
            ";;--------------\t----------------\t----------------\t------\t------\t------\t------\t------\t------\t------\t------\t------\t------\t------"
        )
        # subcatchment groundwater parameters

        self.snowpacks = SectionAsListGroupByID(
            "[SNOWPACKS]", SnowPack,
            ";;Name          \tSurface   \tParameters\n"
            ";;--------------\t----------\t----------")
        # subcatchment snow pack parameters

        self.junctions = SectionAsListOf(
            "[JUNCTIONS]", Junction,
            ";;Name          \tElevation \tMaxDepth  \tInitDepth \tSurDepth  \tAponded\n"
            ";;--------------\t----------\t----------\t----------\t----------\t----------"
        )
        # junction node information

        # self.outfalls = [Outfall] # OUTFALLS # outfall node information
        # self.dividers = [Divider] # DIVIDERS # flow divider node information
        # self.storage = [StorageUnit] # STORAGE # storage node information

        self.conduits = SectionAsListOf(
            "[CONDUITS]", Conduit,
            ";;Name          \tFrom Node       \tTo Node         \tLength    \tRoughness \tInOffset  \tOutOffset \tInitFlow  \tMaxFlow   \n"
            ";;--------------\t----------------\t----------------\t----------\t----------\t----------\t----------\t----------\t----------"
        )
        # conduit link information

        self.pumps = SectionAsListOf(
            "[PUMPS]", Pump,
            ";;Name          \tFrom Node       \tTo Node         \tPump Curve      \tStatus  \tStartup \tShutoff \n"
            ";;--------------\t----------------\t----------------\t----------------\t--------\t--------\t--------"
        )
        # pump link information

        # self.orifices = [Orifice] # ORIFICES # orifice link information
        # self.weirs = [Weir] # WEIRS # weir link information
        # self.outlets = [Outlet] # OUTLETS # outlet link information

        self.xsections = SectionAsListOf(
            "[XSECTIONS]", CrossSection,
            ";;Link          \tShape       \tGeom1           \tGeom2     \tGeom3     \tGeom4     \tBarrels   \tCulvert   \n"
            ";;--------------\t------------\t----------------\t----------\t----------\t----------\t----------\t----------"
        )
        # conduit, orifice, and weir cross-section geometry

        self.transects = Transects(
        )  # TRANSECTS # transect geometry for conduits with irregular cross-sections
        # self.losses = [Section] # LOSSES # conduit entrance/exit losses and flap valves
        self.controls = SectionAsListOf(
            "[CONTROLS]",
            basestring)  # rules that control pump and regulator operation
        self.landuses = SectionAsListOf(
            "[LANDUSES]", Landuse,
            ";;              \tSweeping  \tFraction  \tLast\n"
            ";;Name          \tInterval  \tAvailable \tSwept\n"
            ";;--------------\t----------\t----------\t----------")
        # land use categories

        self.buildup = SectionAsListOf(
            "[BUILDUP]", Buildup,
            ";;Land Use      \tPollutant       \tFunction  \tCoeff1    \tCoeff2    \tCoeff3    \tPer Unit\n"
            ";;--------------\t----------------\t----------\t----------\t----------\t----------\t----------"
        )
        # buildup functions for pollutants and land uses

        self.washoff = SectionAsListOf(
            "[WASHOFF]", Washoff,
            ";;Land Use      \tPollutant       \tFunction  \tCoeff1    \tCoeff2    \tSweepRmvl \tBmpRmvl\n"
            ";;--------------\t----------------\t----------\t----------\t----------\t----------\t----------"
        )
        # washoff functions for pollutants and land uses

        self.pollutants = SectionAsListOf(
            "[POLLUTANTS]", Pollutant,
            ";;Name          \tUnits \tCrain     \tCgw       \tCrdii     \tKdecay    \tSnowOnly  \tCo-Pollutant    \tCo-Frac   \tCdwf      \tCinit\n"
            ";;--------------\t------\t----------\t----------\t----------\t----------\t----------\t----------------\t----------\t----------\t----------"
        )
        # pollutant information

        self.coverages = Coverages(
        )  # COVERAGES # assignment of land uses to subcatchments
        self.treatment = SectionAsListOf(
            "[TREATMENT]", Treatment,
            ";;Node          \tPollutant       \tFunction\n"
            ";;--------------\t----------------\t--------")

        # pollutant removal functions at conveyance system nodes

        self.inflows = SectionAsListOf(
            "[INFLOWS]", DirectInflow,
            ";;Node          \tConstituent     \tTime Series     \tType    \tMfactor \tSfactor \tBaseline\tPattern\n"
            ";;--------------\t----------------\t----------------\t--------\t--------\t--------\t--------\t--------"
        )
        # INFLOWS # external hydrograph/pollutograph inflow at nodes

        self.dwf = SectionAsListOf(
            "[DWF]", DryWeatherInflow,
            ";;Node          \tConstituent     \tBaseline  \tPatterns  \n"
            ";;--------------\t----------------\t----------\t----------")
        # baseline dry weather sanitary inflow at nodes

        self.patterns = SectionAsListGroupByID(
            "[PATTERNS]", Pattern,
            ";;Name          \tType      \tMultipliers\n"
            ";;--------------\t----------\t-----------")
        # PATTERNS      periodic variation in dry weather inflow

        self.rdii = SectionAsListOf(
            "[RDII]", RDIInflow,
            ";;Node          \tUnit Hydrograph \tSewer Area\n"
            ";;--------------\t----------------\t----------")
        # rainfall-dependent I/I information at nodes

        self.loadings = SectionAsListOf(
            "[LOADINGS]", InitialLoading,
            ";;Subcatchment  \tPollutant       \tBuildup\n"
            ";;--------------\t----------------\t----------")
        # initial pollutant loads on subcatchments

        self.curves = SectionAsListGroupByID(
            "[CURVES]", Curve,
            ";;Name          \tType      \tX-Value   \tY-Value   \n"
            ";;--------------\t----------\t----------\t----------")
        # CURVES        x-y tabular data referenced in other sections

        self.timeseries = SectionAsListGroupByID(
            "[TIMESERIES]", TimeSeries,
            ";;Name          \tDate      \tTime      \tValue\n"
            ";;--------------\t----------\t----------\t----------")
        # time series data referenced in other sections

        # self.polygons = [Section] # POLYGONS # X,Y coordinates for each vertex of subcatchment polygons
        # self.coordinates = [Section] # COORDINATES # X,Y coordinates for nodes
        # self.vertices = [Section] # VERTICES # X,Y coordinates for each interior vertex of polyline links
        # self.labels = [Section] # LABELS # X,Y coordinates and text of labels
        # self.symbols = [Section] # SYMBOLS # X,Y coordinates for rain gages
        #  X,Y coordinates of the bounding rectangle and file name of the backdrop image.
        # [TAGS]
        InputFile.__init__(
            self
        )  # Do this after setting attributes so they will all get added to sections[]