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 SwmmProject(ProjectBase):
    """Manage a complete SWMM input sequence"""
    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.

    def nodes_groups(self):
        return [self.junctions, self.outfalls, self.dividers, self.storage]

    def links_groups(self):
        return [
            self.conduits, self.pumps, self.orifices, self.weirs, self.outlets
        ]

    @staticmethod
    def get_dwf_label_text(pattern=None):
        if pattern:
            return u'"' + pattern.name + u'"'
        else:
            return u'""'

    def set_pattern_object_references(self):
        """
        setup node <-> pattern object reference
        which can be used for handling pattern name changes
        Returns:
        """
        if self.inflows.value:
            for obj_inflow in self.inflows.value:
                obj_inflow.baseline_pattern_object = self.patterns.find_item(
                    obj_inflow.baseline_pattern)

        if self.aquifers.value:
            for obj_aquifer in self.aquifers.value:
                obj_aquifer.upper_evaporation_pattern_object = \
                    self.patterns.find_item(obj_aquifer.upper_evaporation_pattern)

        if self.dwf.value:
            for obj_dwf in self.dwf.value:
                del obj_dwf.time_pattern_objects[:]
                # order of patterns should be kept intact
                for i in range(0, len(obj_dwf.time_patterns)):
                    if obj_dwf.time_patterns[i]:
                        pat = self.patterns.find_item(
                            obj_dwf.time_patterns[i].strip("\""))
                        obj_dwf.time_pattern_objects.append(pat)
                    else:
                        obj_dwf.time_pattern_objects.append(None)

    def refresh_pattern_object_references(self):
        """
        refresh pattern object id references of various model objects
        Returns:
        """
        if self.inflows.value:
            for obj_inflow in self.inflows.value:
                if obj_inflow.baseline_pattern_object:
                    obj_inflow.baseline_pattern = obj_inflow.baseline_pattern_object.name

        if self.aquifers.value:
            for obj_aquifer in self.aquifers.value:
                if obj_aquifer.upper_evaporation_pattern_object:
                    obj_aquifer.upper_evaporation_pattern = obj_aquifer.upper_evaporation_pattern_object.name

        if self.dwf.value:
            for obj_dwf in self.dwf.value:
                del obj_dwf.time_patterns[:]
                # order of patterns should be kept intact
                for i in range(0, len(obj_dwf.time_pattern_objects)):
                    if obj_dwf.time_pattern_objects[i]:
                        # obj_dwf.time_patterns.append(u'"' + obj_dwf.time_pattern_objects[i].name + u'"')
                        obj_dwf.time_patterns.append(
                            self.get_dwf_label_text(
                                obj_dwf.time_pattern_objects[i]))
                    else:
                        obj_dwf.time_patterns.append(self.get_dwf_label_text())

    def delete_pattern(self, pattern):
        objects_with_pattern = {}
        if self.inflows.value:
            for obj_inflow in self.inflows.value:
                if pattern in [obj_inflow.baseline_pattern_object]:
                    obj_inflow.baseline_pattern = ""
                    obj_inflow.baseline_pattern_object = None
                    objects_with_pattern[obj_inflow] = None

        if self.aquifers.value:
            for obj_aquifer in self.aquifers.value:
                if pattern in [obj_aquifer.upper_evaporation_pattern_object]:
                    obj_aquifer.upper_evaporation_pattern = ""
                    obj_aquifer.upper_evaporation_pattern_object = None
                    objects_with_pattern[obj_aquifer] = None

        if self.dwf.value:
            for obj_dwf in self.dwf.value:
                # del obj_dwf.time_patterns[:]
                # order of patterns should be kept intact
                if pattern in obj_dwf.time_pattern_objects:
                    objects_with_pattern[obj_dwf] = []
                    lbl_dwf_pattern = self.get_dwf_label_text(pattern)
                    for i in range(0, len(obj_dwf.time_patterns)):
                        if lbl_dwf_pattern.replace('"', '') in [
                                obj_dwf.time_patterns[i].replace('"', '')
                        ]:
                            obj_dwf.time_patterns[i] = self.get_dwf_label_text(
                            )
                            obj_dwf.time_pattern_objects[i] = None
                            objects_with_pattern[obj_dwf].append(i)

        return objects_with_pattern

    def restore_pattern(self, objects_with_pattern, pattern):
        for obj in objects_with_pattern.keys():
            if self.inflows.value:
                if obj in self.inflows.value:
                    obj.baseline_pattern = pattern.name
                    obj.baseline_pattern_object = pattern

            if self.aquifers.value:
                if obj in self.aquifers.value:
                    obj.upper_evaporation_pattern = pattern.name
                    obj.upper_evaporation_pattern_object = pattern

            if self.dwf.value:
                if obj in self.dwf.value:
                    for i in objects_with_pattern[obj]:
                        # order of patterns should be kept intact
                        if i < len(obj.time_patterns):
                            obj.time_pattern_objects[i] = pattern
                            obj.time_patterns[i] = self.get_dwf_label_text(
                                pattern)
class EpanetProject(ProjectBase):
    """Manage a complete EPANET input sequence"""
    def __init__(self):
        """Initialize the sections of an EPANET input file.
           Any sections not initialized here will be handled by the generic core.project_base.Section class."""
        ProjectBase.__init__(self)

        self.title = Title()
        self.backdrop = BackdropOptions(
        )  # BACKDROP      bounding rectangle and file name of backdrop image
        self.map = MapOptions(
        )  # MAP           map's bounding rectangle and units
        self.junctions = SectionAsList("[JUNCTIONS]")  # (list of Junction)
        self.reservoirs = SectionAsList("[RESERVOIRS]")  # (list of Reservoir)
        self.tanks = SectionAsList("[TANKS]")  # (list of Tank)
        self.pipes = SectionAsList("[PIPES]")  # (list of Pipe)
        self.pumps = SectionAsList("[PUMPS]")  # (list of Pump)
        self.valves = SectionAsList("[VALVES]")  # (list of Valve)
        # self.emitters = [(Junction, "emitter_coefficient")]
        self.patterns = SectionAsList("[PATTERNS]")  # (list of Pattern)
        self.curves = SectionAsList("[CURVES]")  # (list of Curve)
        self.energy = EnergyOptions()
        self.status = SectionAsList("[STATUS]")  # (list of Status)
        self.controls = Control()
        self.rules = Rule()
        self.demands = SectionAsList("[DEMANDS]")  # (list of Demand)
        self.reactions = Reactions()
        self.sources = SectionAsList("[SOURCES]")  # (list of Source)
        # self.options = MapOptions,
        self.options = Options()
        self.times = TimesOptions()
        self.report = ReportOptions()
        self.labels = SectionAsList("[LABELS]")  # (list of Label)
        self.backdrop = BackdropOptions()
        self.calibrations = SectionAsList(
            "[CALIBRATIONS]")  # (list of Calibration)

        self.sections = [
            self.title, self.options, self.report, self.junctions, self.tanks,
            self.reservoirs, self.pipes, self.pumps, self.valves,
            self.controls, self.patterns, self.curves, self.backdrop, self.map,
            self.labels
        ]  # 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.

    def nodes_groups(self):
        return [self.junctions, self.reservoirs, self.tanks]

    def links_groups(self):
        return [self.pipes, self.pumps, self.valves]

    def set_pattern_object_references(self):
        """
        setup node <-> pattern object reference
        which can be used for handling pattern name changes
        Returns:
        """
        if self.junctions.value:
            for obj_junction in self.junctions.value:
                obj_junction.demand_pattern_object = \
                    self.patterns.find_item(obj_junction.demand_pattern_name)

        if self.reservoirs.value:
            for obj_res in self.reservoirs.value:
                obj_res.head_pattern_object = self.patterns.find_item(
                    obj_res.head_pattern_name)

        if self.demands.value:
            for obj_demand in self.demands.value:
                obj_demand.demand_pattern_object = self.patterns.find_item(
                    obj_demand.demand_pattern)

        if self.sources.value:
            for obj_src in self.sources.value:
                obj_src.pattern_object = self.patterns.find_item(
                    obj_src.pattern_name)

        # self.options.hydraulics.default_pattern = "1"
        self.options.hydraulics.default_pattern_object = \
            self.patterns.find_item(self.options.hydraulics.default_pattern)

    def refresh_pattern_object_references(self):
        """
        refresh pattern object id references of various model objects
        Returns:
        """
        if self.junctions.value:
            for obj_junction in self.junctions.value:
                if obj_junction.demand_pattern_object:
                    obj_junction.demand_pattern_name = obj_junction.demand_pattern_object.name

        if self.reservoirs.value:
            for obj_res in self.reservoirs.value:
                if obj_res.head_pattern_object:
                    obj_res.head_pattern_name = obj_res.head_pattern_object.name

        if self.demands.value:
            for obj_demand in self.demands.value:
                if obj_demand.demand_pattern_object:
                    obj_demand.demand_pattern = obj_demand.demand_pattern_object.name

        if self.sources.value:
            for obj_src in self.sources.value:
                if obj_src.pattern_object:
                    obj_src.pattern_name = obj_src.pattern_object.name

        if self.options.hydraulics.default_pattern_object:
            self.options.hydraulics.default_pattern = self.options.hydraulics.default_pattern_object.name

    def delete_pattern(self, pattern):
        objects_with_pattern = []
        if self.junctions.value:
            for obj_junction in self.junctions.value:
                if pattern in [obj_junction.demand_pattern_object]:
                    obj_junction.demand_pattern_name = ""
                    obj_junction.demand_pattern_object = None
                    objects_with_pattern.append(obj_junction)

        if self.reservoirs.value:
            for obj_res in self.reservoirs.value:
                if pattern in [obj_res.head_pattern_object]:
                    obj_res.head_pattern_name = ""
                    obj_res.head_pattern_object = None
                    objects_with_pattern.append(obj_res)

        if self.demands.value:
            for obj_demand in self.demands.value:
                if pattern in [obj_demand.demand_pattern_object]:
                    obj_demand.demand_pattern = ""
                    obj_demand.demand_pattern_object = None
                    objects_with_pattern.append(obj_demand)

        if self.sources.value:
            for obj_src in self.sources.value:
                if pattern in [obj_src.pattern_object]:
                    obj_src.pattern_name = ""
                    obj_src.pattern_object = None
                    objects_with_pattern.append(obj_src)

        if self.options.hydraulics.default_pattern_object:
            if pattern in [self.options.hydraulics.default_pattern_object]:
                self.options.hydraulics.default_pattern = ""
                self.options.hydraulics.default_pattern_object = None
                objects_with_pattern.append(self.options.hydraulics)

        return objects_with_pattern

    def restore_pattern(self, objects_with_pattern, pattern):
        for obj in objects_with_pattern:
            if self.junctions.value:
                if obj in self.junctions.value:
                    obj.demand_pattern_name = pattern.name
                    obj.demand_pattern_object = pattern

            if self.reservoirs.value:
                if obj in self.reservoirs.value:
                    obj.head_pattern_name = pattern.name
                    obj.head_pattern_object = pattern

            if self.demands.value:
                if obj in self.demands.value:
                    obj.demand_pattern = pattern.name
                    obj.demand_pattern_object = pattern

            if self.sources.value:
                if obj in self.sources.value:
                    obj.pattern_name = pattern.name
                    obj.pattern_object = pattern

            if obj in [self.options.hydraulics.default_pattern_object]:
                self.options.hydraulics.default_pattern = pattern.name
                self.options.hydraulics.default_pattern_object = pattern
    def __init__(self):
        """Initialize the sections of an EPANET input file.
           Any sections not initialized here will be handled by the generic core.project_base.Section class."""
        ProjectBase.__init__(self)

        self.title = Title()
        self.backdrop = BackdropOptions(
        )  # BACKDROP      bounding rectangle and file name of backdrop image
        self.map = MapOptions(
        )  # MAP           map's bounding rectangle and units
        self.junctions = SectionAsList("[JUNCTIONS]")  # (list of Junction)
        self.reservoirs = SectionAsList("[RESERVOIRS]")  # (list of Reservoir)
        self.tanks = SectionAsList("[TANKS]")  # (list of Tank)
        self.pipes = SectionAsList("[PIPES]")  # (list of Pipe)
        self.pumps = SectionAsList("[PUMPS]")  # (list of Pump)
        self.valves = SectionAsList("[VALVES]")  # (list of Valve)
        # self.emitters = [(Junction, "emitter_coefficient")]
        self.patterns = SectionAsList("[PATTERNS]")  # (list of Pattern)
        self.curves = SectionAsList("[CURVES]")  # (list of Curve)
        self.energy = EnergyOptions()
        self.status = SectionAsList("[STATUS]")  # (list of Status)
        self.controls = Control()
        self.rules = Rule()
        self.demands = SectionAsList("[DEMANDS]")  # (list of Demand)
        self.reactions = Reactions()
        self.sources = SectionAsList("[SOURCES]")  # (list of Source)
        # self.options = MapOptions,
        self.options = Options()
        self.times = TimesOptions()
        self.report = ReportOptions()
        self.labels = SectionAsList("[LABELS]")  # (list of Label)
        self.backdrop = BackdropOptions()
        self.calibrations = SectionAsList(
            "[CALIBRATIONS]")  # (list of Calibration)

        self.sections = [
            self.title, self.options, self.report, self.junctions, self.tanks,
            self.reservoirs, self.pipes, self.pumps, self.valves,
            self.controls, self.patterns, self.curves, self.backdrop, self.map,
            self.labels
        ]  # 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.
    def __init__(self):
        """Initialize the sections of an EPANET input file.
           Any sections not initialized here will be handled by the generic core.project_base.Section class."""
        self.title = Title()
        self.junctions = SectionAsList("[JUNCTIONS]")  # (list of Junction)
        self.reservoirs = SectionAsList("[RESERVOIRS]")  # (list of Reservoir)
        self.tanks = SectionAsList("[TANKS]")  # (list of Tank)
        self.pipes = SectionAsList("[PIPES]")  # (list of Pipe)
        self.pumps = SectionAsList("[PUMPS]")  # (list of Pump)
        self.valves = SectionAsList("[VALVES]")  # (list of Valve)
        # self.emitters = [(Junction, "emitter_coefficient")]
        self.patterns = SectionAsList("[PATTERNS]")  # (list of Pattern)
        self.curves = SectionAsList("[CURVES]")  # (list of Curve)
        self.energy = EnergyOptions()
        self.status = SectionAsList("[STATUS]")  # (list of Status)
        self.controls = Control()
        self.rules = Rule()
        self.demands = SectionAsList("[DEMANDS]")  # (list of Demand)
        self.reactions = Reactions()
        self.sources = SectionAsList("[SOURCES]")  # (list of Source)
        # self.options = MapOptions,
        self.options = Options()
        self.times = TimesOptions()
        self.report = ReportOptions()
        self.labels = SectionAsList("[LABELS]")  # (list of Label)
        self.backdrop = BackdropOptions()
        self.calibrations = SectionAsList(
            "[CALIBRATIONS]")  # (list of Calibration)

        ProjectBase.__init__(
            self
        )  # Do this after setting attributes so they will all get added to sections[]