Beispiel #1
0
def setup(the_scenario, logger):

    logger.debug("start: setup")
    start_time = datetime.datetime.now()
    logger.info("Scenario Name: \t{}".format(the_scenario.scenario_name))
    logger.debug("Scenario Description: \t{}".format(
        the_scenario.scenario_description))
    logger.info("Scenario Start Date/Time: \t{}".format(start_time))

    # create a folder for debug and intermediate files
    # delete everything in there if it exists
    # ------------------------------------------------
    debug_directory = os.path.join(the_scenario.scenario_run_directory,
                                   "debug")

    if os.path.exists(debug_directory):
        logger.debug("deleting debug_directory and contents.")
        rmtree(debug_directory)

    if not os.path.exists(debug_directory):
        os.makedirs(debug_directory)
        logger.debug("creating debug_directory.")

    # create the scenario database main.db
    create_main_db(logger, the_scenario)

    # create the scenario geodatabase; main.gdb
    create_main_gdb(logger, the_scenario)

    logger.debug("finish: SETUP:  Runtime (HMS): \t{}".format(
        ftot_supporting.get_total_runtime_string(start_time)))
def export_fcs_from_main_gdb(the_scenario, logger):
    # export fcs from the main.GDB to individual shapefiles
    logger.info("start: export_fcs_from_main_gdb")
    start_time = datetime.datetime.now()

    # export network and locations fc's to shapefiles
    main_gdb = the_scenario.main_gdb
    output_path = the_scenario.lyr_files_dir
    input_features = "\""

    logger.debug("delete the temp_networkx_shp_files dir")
    if os.path.exists(output_path):
        logger.debug("deleting temp_networkx_shp_files directory.")
        rmtree(output_path)

    if not os.path.exists(output_path):
        os.makedirs(output_path)
        logger.debug("finished: create_temp_gdbs_dir")

    # get the locations and network feature layers
    for fc in ['\\locations;', '\\network\\intermodal;', '\\network\\locks;', '\\network\\pipeline_prod_trf_rts;',
               '\\network\\pipeline_crude_trf_rts;', '\\network\\water;', '\\network\\rail;', '\\network\\road']:
        input_features += main_gdb + fc
    input_features += "\""
    arcpy.FeatureClassToShapefile_conversion(Input_Features=input_features, Output_Folder=output_path)

    logger.debug("finished: export_fcs_from_main_gdb: Runtime (HMS): \t{}".format(
        ftot_supporting.get_total_runtime_string(start_time)))
def gis_populate_fc(the_scenario, logger):

    logger.info("start: gis_populate_fc")

    start_time = datetime.datetime.now()

    # populate the destinations fc in main.gdb
    gis_ultimate_destinations_setup_fc(the_scenario, logger)

    # populate the RMPs fc in main.gdb
    gis_rmp_setup_fc(the_scenario, logger)

    # populate the processors fc in main.gdb
    gis_processors_setup_fc(the_scenario, logger)

    logger.debug("finished: gis_populate_fc: Runtime (HMS): \t{}".format(
        ftot_supporting.get_total_runtime_string(start_time)))
Beispiel #4
0
def make_networkx_graph(the_scenario, logger):
    # High level work flow:
    # ------------------------
    # make_networkx_graph
    # create the multidigraph
    # convert the node labels to integers
    # reverse the graph and compose with self

    logger.info("start: make_networkx_graph")
    start_time = datetime.datetime.now()

    # read the shapefiles in the customized read_shp method
    input_path = the_scenario.lyr_files_dir

    logger.debug("start: read_shp")
    G = read_shp(input_path, logger)  # note this custom and not nx.read_shp()

    # cleanup the node labels
    logger.debug("start: convert node labels")
    G = nx.convert_node_labels_to_integers(G,
                                           first_label=0,
                                           ordering='default',
                                           label_attribute="x_y_location")

    # create a reversed graph
    logger.debug("start: reverse G graph to H")
    H = G.reverse()  # this is a reversed version of the graph.

    # set the a new attribute for every edge that says its a "reversed" link
    # we will use this to delete edges that shouldn't be reversed later.
    logger.debug("start: set 'reversed' attribute in H")
    nx.set_edge_attributes(H, 1, "REVERSED")

    # add the two graphs together
    logger.debug("start: compose G and H")
    G = nx.compose(G, H)

    # print out some stats on the Graph
    logger.info("Number of nodes in the raw graph: {}".format(G.order()))
    logger.info("Number of edges in the raw graph: {}".format(G.size()))

    logger.debug("finished: make_networkx_graph: Runtime (HMS): \t{}".format(
        ftot_supporting.get_total_runtime_string(start_time)))

    return G
def gis_clean_fc(the_scenario, logger):

    logger.info("start: gis_clean_fc")

    start_time = datetime.datetime.now()

    # clear the destinations
    gis_clear_feature_class(the_scenario.destinations_fc, logger)

    # clear the RMPs
    gis_clear_feature_class(the_scenario.rmp_fc, logger)

    # clear the processors
    gis_clear_feature_class(the_scenario.processors_fc, logger)

    # clear the processors
    gis_clear_feature_class(the_scenario.locations_fc, logger)

    logger.debug("finished: gis_clean_fc: Runtime (HMS): \t{}".format(
        ftot_supporting.get_total_runtime_string(start_time)))
    except:

        stack_trace = traceback.format_exc()
        split_stack_trace = stack_trace.split('\n')
        logger.error(
            "!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EXCEPTION RAISED !!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        )
        for i in range(0, len(split_stack_trace)):
            trace_line = split_stack_trace[i].rstrip()
            if trace_line != "":  # issue #182 - check if the line is blank. if it isn't, record it in the log.
                logger.error(trace_line)
        logger.error(
            "!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EXCEPTION RAISED !!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
        )

        sys.exit(1)

    logger.info(
        "======================== FTOT RUN FINISHED: {:2} =================================="
        .format(str(args.task).upper()))
    logger.info(
        "======================== Total Runtime (HMS): \t{} \t ".format(
            ftot_supporting.get_total_runtime_string(start_time)))
    logger.info(
        "================================================================================="
    )
    logger.runtime("{} Step - Total Runtime (HMS): \t{}".format(
        args.task, ftot_supporting.get_total_runtime_string(start_time)))
    logging.shutdown()
def clean_networkx_graph(the_scenario, G, logger):
    # VERSION 3:
    # renamed clean_networkx_graph ()
    # remove reversed links for pipeline
    # selectivity remove links for location _IN and _OUT nodes
    # preserve the route_cost_scaling factor in an attribute by phase of matter
    # -------------------------------------------------------------------------
    
    logger.info("start: clean_networkx_graph")
    start_time = datetime.datetime.now()

    logger.debug("Processing the {} edges in the uncosted graph.".format(G.size()))

    # use the artificial and reversed attribute to determine if
    # the link is kept
    # -------------------------------------------------------------
    edge_attrs = {}  # for storing the edge attributes which are set all at once
    deleted_edge_count = 0

    # note: For digraphs, edges=out_edges
    # for some reason it shows up as out_edges in the debugger, but
    # when caching to the database both in_edges and out_edges are stored.
    for u, v, keys, artificial in G.edges(data='Artificial', keys=True):

        # initialize the route_cost_scaling variable to something
        # absurd so we know if its getting set properly in the loop:
        route_cost_scaling = -999999999

        # check if the link is reversed
        if 'REVERSED' in G.edges[u, v, keys]:
            reversed_link = G.edges[u, v, keys]['REVERSED']
        else:
            reversed_link = 0

        # check if capacity is 0
        # Network Edges - artificial == 0
        # -----------------------------------
        if artificial == 0:

            # check the mode type
            # ----------------------
            mode_type = G.edges[u, v, keys]['MODE_TYPE']

            # set the mode specific weights
            # -----------------------------

            if mode_type == "rail":
                d_code = G.edges[u, v, keys]["DENSITY_CO"]
                if d_code in [7]:
                    route_cost_scaling = the_scenario.rail_dc_7
                elif d_code in [6]:
                    route_cost_scaling = the_scenario.rail_dc_6
                elif d_code in [5]:
                    route_cost_scaling = the_scenario.rail_dc_5
                elif d_code in [4]:
                    route_cost_scaling = the_scenario.rail_dc_4
                elif d_code in [3]:
                    route_cost_scaling = the_scenario.rail_dc_3
                elif d_code in [2]:
                    route_cost_scaling = the_scenario.rail_dc_2
                elif d_code in [1]:
                    route_cost_scaling = the_scenario.rail_dc_1
                elif d_code in [0]:
                    route_cost_scaling = the_scenario.rail_dc_0
                else:
                    logger.warning("The d_code {} is not supported".format(d_code))

            elif mode_type == "water":

                # get the total vol of water traffic
                tot_vol = G.edges[u, v, keys]['TOT_UP_DWN']
                if tot_vol >= 10000000:
                    route_cost_scaling = the_scenario.water_high_vol
                elif 1000000 <= tot_vol < 10000000:
                    route_cost_scaling = the_scenario.water_med_vol
                elif 1 <= tot_vol < 1000000:
                    route_cost_scaling = the_scenario.water_low_vol
                else:
                    route_cost_scaling = the_scenario.water_no_vol

            elif mode_type == "road":

                # get fclass
                fclass = G.edges[u, v, keys]['FCLASS']
                if fclass in [1]:
                    route_cost_scaling = the_scenario.truck_interstate
                elif fclass in [2, 3]:
                    route_cost_scaling = the_scenario.truck_pr_art
                elif fclass in [4]:
                    route_cost_scaling = the_scenario.truck_m_art
                else:
                    route_cost_scaling = the_scenario.truck_local

            elif 'pipeline' in mode_type:
                if reversed_link == 1:
                    G.remove_edge(u, v, keys)
                    deleted_edge_count += 1
                    continue  # move on to the next edge
                else:
                    route_cost_scaling = (((float(G.edges[u, v, keys]['base_rate']) / 100) / 42.0) * 1000.0)

        # Intermodal Edges - artificial == 2
        # ------------------------------------
        elif artificial == 2:
            # set it to 1 because we'll multiply by the appropriate
            # link_cost later for transloading
            route_cost_scaling = 1

            # nothing else to do with intermodal edges.
            # they need to be unscaled in both directions

        # Artificial Edge - artificial == 1
        # ----------------------------------
        # need to check if its an IN location or an OUT location and delete selectively.
        # assume always connecting from the node to the network.
        # so _OUT locations should delete the reversed link
        # _IN locations should delete the non-reversed link.
        elif artificial == 1:
            # delete edges we dont want

			try:
				if G.edges[u, v, keys]['LOCATION_1'].find("_OUT") > -1 and reversed_link == 1:
					G.remove_edge(u, v, keys)
					deleted_edge_count += 1
					continue  # move on to the next edge
				elif G.edges[u, v, keys]['LOCATION_1'].find("_IN") > -1 and reversed_link == 0:
					G.remove_edge(u, v, keys)
					deleted_edge_count += 1
					continue  # move on to the next edge

				# there is no scaling of artificial links.
				# the cost_penalty is calculated in get_network_link_cost()
				else:
					route_cost_scaling = 1
			except:
				logger.warning("the following keys didn't work:u - {}, v- {}".format(u, v)) 
        else:
            logger.warning("found an edge without artificial attribute: {} ")
            continue

        edge_attrs[u, v, keys] = {
            'route_cost_scaling': route_cost_scaling
            }

    nx.set_edge_attributes(G, edge_attrs)

    # print out some stats on the Graph
    logger.info("Number of nodes in the clean graph: {}".format(G.order()))
    logger.info("Number of edges in the clean graph: {}".format(G.size()))

    logger.debug("finished: clean_networkx_graph: Runtime (HMS): \t{}".format(
        ftot_supporting.get_total_runtime_string(start_time)))

    return G
def gis_processors_setup_fc(the_scenario, logger):

    logger.info("start: gis_processors_setup_fc")
    start_time = datetime.datetime.now()

    if str(the_scenario.base_processors_layer).lower() == "null" or \
       str(the_scenario.base_processors_layer).lower() == "none":
        # create an empty processors layer
        # -------------------------
        processors_fc = the_scenario.processors_fc

        if arcpy.Exists(processors_fc):
            arcpy.Delete_management(processors_fc)
            logger.debug("deleted existing {} layer".format(processors_fc))

        arcpy.CreateFeatureclass_management(the_scenario.main_gdb, "processors", \
                                            "POINT", "#", "DISABLED", "DISABLED", ftot_supporting_gis.LCC_PROJ, "#",
                                            "0", "0", "0")

        arcpy.AddField_management(processors_fc, "Facility_Name", "TEXT", "#",
                                  "#", "25", "#", "NULLABLE", "NON_REQUIRED",
                                  "#")
        arcpy.AddField_management(processors_fc, "Candidate", "SHORT")
        # logger.info("note: processors layer specified in the XML: {}".format(the_scenario.base_processors_layer))
        # empty_processors_fc = str("{}\\facilities\\test_facilities.gdb\\test_processors_empty"
        #                           .format(the_scenario.common_data_folder))
        # processors_fc = the_scenario.processors_fc
        # arcpy.Project_management(empty_processors_fc, processors_fc, ftot_supporting_gis.LCC_PROJ)

    else:
        # copy the processors from the baseline data to the working gdb
        # ----------------------------------------------------------------
        if not arcpy.Exists(the_scenario.base_processors_layer):
            error = "can't find baseline data processors layer {}".format(
                the_scenario.base_processors_layer)
            raise IOError(error)

        processors_fc = the_scenario.processors_fc
        arcpy.Project_management(the_scenario.base_processors_layer,
                                 processors_fc, ftot_supporting_gis.LCC_PROJ)

        arcpy.AddField_management(processors_fc, "Candidate", "SHORT")

        # Delete features with no data in csv-- cleans up GIS output and eliminates unnecessary GIS processing
        # --------------------------------------------------------------
        # create a temp dict to store values from CSV
        temp_facility_commodities_dict = {}
        counter = 0

        # read through facility_commodities input CSV
        import csv
        with open(the_scenario.processors_commodity_data, 'rb') as f:

            reader = csv.DictReader(f)
            for row in reader:
                facility_name = str(row["facility_name"])
                commodity_quantity = row["value"]

                if facility_name not in temp_facility_commodities_dict.keys():
                    if commodity_quantity > 0:
                        temp_facility_commodities_dict[facility_name] = True

        with arcpy.da.UpdateCursor(processors_fc, ['Facility_Name']) as cursor:
            for row in cursor:
                if row[0] in temp_facility_commodities_dict:
                    pass
                else:
                    cursor.deleteRow()
                    counter += 1

        del cursor
        logger.config(
            "Number of processors removed due to lack of commodity data: \t{}".
            format(counter))

        with arcpy.da.SearchCursor(
                processors_fc,
            ['Facility_Name', 'SHAPE@X', 'SHAPE@Y']) as scursor:
            for row in scursor:
                # Check if coordinates of facility are roughly within North America
                if -6500000 < row[1] < 6500000 and -3000000 < row[2] < 5000000:
                    pass
                else:
                    logger.warning(
                        "Facility: {} is not located in North America.".format(
                            row[0]))
                    logger.info(
                        "remove the facility from the scenario or make adjustments to the facility's location "
                        "in the processors feature class: {}".format(
                            the_scenario.base_processors_layer))
                    error = "Facilities outside North America are not supported in FTOT"
                    logger.error(error)
                    raise Exception(error)

        del scursor

    # check for candidates or other processors specified in either XML or
    layers_to_merge = []

    # add the candidates_for_merging if they exists.
    if arcpy.Exists(the_scenario.processor_candidates_fc):
        logger.info(
            "adding {} candidate processors to the processors fc".format(
                gis_get_feature_count(the_scenario.processor_candidates_fc,
                                      logger)))
        layers_to_merge.append(the_scenario.processor_candidates_fc)
        gis_merge_processor_fc(the_scenario, layers_to_merge, logger)

    result = gis_get_feature_count(processors_fc, logger)

    logger.config("Number of Processors: \t{}".format(result))

    logger.debug("finish: gis_processors_setup_fc: Runtime (HMS): \t{}".format(
        ftot_supporting.get_total_runtime_string(start_time)))
def gis_rmp_setup_fc(the_scenario, logger):

    logger.info("start: gis_rmp_setup_fc")
    start_time = datetime.datetime.now()

    # copy the rmp from the baseline data to the working gdb
    # ----------------------------------------------------------------
    if not arcpy.Exists(the_scenario.base_rmp_layer):
        error = "can't find baseline data rmp layer {}".format(
            the_scenario.base_rmp_layer)
        raise IOError(error)

    rmp_fc = the_scenario.rmp_fc
    arcpy.Project_management(the_scenario.base_rmp_layer, rmp_fc,
                             ftot_supporting_gis.LCC_PROJ)

    # Delete features with no data in csv-- cleans up GIS output and eliminates unnecessary GIS processing
    # --------------------------------------------------------------
    # create a temp dict to store values from CSV
    temp_facility_commodities_dict = {}
    counter = 0

    # read through facility_commodities input CSV
    import csv
    with open(the_scenario.rmp_commodity_data, 'rb') as f:

        reader = csv.DictReader(f)
        for row in reader:
            facility_name = str(row["facility_name"])
            commodity_quantity = row["value"]

            if not facility_name in temp_facility_commodities_dict.keys():
                if commodity_quantity > 0:
                    temp_facility_commodities_dict[facility_name] = True

    with arcpy.da.UpdateCursor(rmp_fc, ['Facility_Name']) as cursor:
        for row in cursor:
            if row[0] in temp_facility_commodities_dict:
                pass
            else:
                cursor.deleteRow()
                counter += 1
    del cursor
    logger.config(
        "Number of RMPs removed due to lack of commodity data: \t{}".format(
            counter))

    with arcpy.da.SearchCursor(
            rmp_fc, ['Facility_Name', 'SHAPE@X', 'SHAPE@Y']) as scursor:
        for row in scursor:
            # Check if coordinates of facility are roughly within North America
            if -6500000 < row[1] < 6500000 and -3000000 < row[2] < 5000000:
                pass
            else:
                logger.warning(
                    "Facility: {} is not located in North America.".format(
                        row[0]))
                logger.info(
                    "remove the facility from the scenario or make adjustments to the facility's location in "
                    "the RMP feature class: {}".format(
                        the_scenario.base_rmp_layer))
                error = "Facilities outside North America are not supported in FTOT"
                logger.error(error)
                raise Exception(error)

    del scursor

    result = gis_get_feature_count(rmp_fc, logger)
    logger.config("Number of RMPs: \t{}".format(result))

    logger.debug("finished: gis_rmp_setup_fc: Runtime (HMS): \t{}".format(
        ftot_supporting.get_total_runtime_string(start_time)))
Beispiel #10
0
        elif args.task == "m":
            from ftot_maps import new_map_creation
            new_map_creation(the_scenario, logger)

        # Time and Commodity Mapping
        elif args.task == "m2":
            from ftot_maps import prepare_time_commodity_subsets_for_mapping
            prepare_time_commodity_subsets_for_mapping(the_scenario, logger)

        elif args.task == "test":
            logger.info("in the test case")

    except:

        stack_trace = traceback.format_exc()

        logger.error("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
        logger.error("\n\n" + stack_trace)
        logger.error("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")

        sys.exit(1)

    logger.info("======================== FTOT RUN FINISHED: {:2} ==================================".format(
        str(args.task).upper()))
    logger.info("======================== Total Runtime (HMS): \t{} \t ".format(
        ftot_supporting.get_total_runtime_string(start_time)))
    logger.info("=================================================================================")
    logger.runtime(
        "{} Step - Total Runtime (HMS): \t{}".format(args.task, ftot_supporting.get_total_runtime_string(start_time)))
    logging.shutdown()