コード例 #1
0
def plot(table_names=None):
    """
    Plot relationships between columns and tables using Graphviz.

    Parameters
    ----------
    table_names : iterable of str, optional
        Names of UrbanSim registered tables to plot.
        Defaults to all registered tables.

    Returns
    -------
    graph : pygraphviz.AGraph
        PyGraphviz graph object.

    """
    if not table_names:
        # Default to all registered tables.
        table_names = simulation.list_tables()

    graph = AGraph(directed=True)
    graph.graph_attr['fontname'] = 'Sans'
    graph.graph_attr['fontsize'] = 28
    graph.node_attr['shape'] = 'box'
    graph.node_attr['fontname'] = 'Sans'
    graph.node_attr['fontcolor'] = 'blue'
    graph.edge_attr['weight'] = 2

    # Add each registered table as a subgraph with columns as nodes.
    for table_name in table_names:
        subgraph = graph.add_subgraph(name='cluster_' + table_name,
                                      label=table_name,
                                      fontcolor='red')
        table = simulation.get_table(table_name)
        for column_name in table.columns:
            full_name = table_name + '.' + column_name
            subgraph.add_node(full_name, label=column_name)

    # Iterate over computed columns to build nodes.
    for key, wrapped_col in simulation._COLUMNS.items():
        table_name = key[0]
        column_name = key[1]

        # Combine inputs from argument names and argument default values.
        args = list(wrapped_col._argspec.args)
        if wrapped_col._argspec.defaults:
            default_args = list(wrapped_col._argspec.defaults)
        else:
            default_args = []
        inputs = args[:len(args) - len(default_args)] + default_args

        # Create edge from each input column to the computed column.
        for input_name in inputs:
            full_name = table_name + '.' + column_name
            graph.add_edge(input_name, full_name)

    graph.layout(prog='dot')
    return graph
コード例 #2
0
ファイル: sim.py プロジェクト: UDST/spandex
def plot(table_names=None):
    """
    Plot relationships between columns and tables using Graphviz.

    Parameters
    ----------
    table_names : iterable of str, optional
        Names of UrbanSim registered tables to plot.
        Defaults to all registered tables.

    Returns
    -------
    graph : pygraphviz.AGraph
        PyGraphviz graph object.

    """
    if not table_names:
        # Default to all registered tables.
        table_names = simulation.list_tables()

    graph = AGraph(directed=True)
    graph.graph_attr['fontname'] = 'Sans'
    graph.graph_attr['fontsize'] = 28
    graph.node_attr['shape'] = 'box'
    graph.node_attr['fontname'] = 'Sans'
    graph.node_attr['fontcolor'] = 'blue'
    graph.edge_attr['weight'] = 2

    # Add each registered table as a subgraph with columns as nodes.
    for table_name in table_names:
        subgraph = graph.add_subgraph(name='cluster_' + table_name,
                                      label=table_name, fontcolor='red')
        table = simulation.get_table(table_name)
        for column_name in table.columns:
            full_name = table_name + '.' + column_name
            subgraph.add_node(full_name, label=column_name)

    # Iterate over computed columns to build nodes.
    for key, wrapped_col in simulation._COLUMNS.items():
        table_name = key[0]
        column_name = key[1]

        # Combine inputs from argument names and argument default values.
        args = list(wrapped_col._argspec.args)
        if wrapped_col._argspec.defaults:
            default_args = list(wrapped_col._argspec.defaults)
        else:
            default_args = []
        inputs = args[:len(args) - len(default_args)] + default_args

        # Create edge from each input column to the computed column.
        for input_name in inputs:
            full_name = table_name + '.' + column_name
            graph.add_edge(input_name, full_name)

    graph.layout(prog='dot')
    return graph
コード例 #3
0
ファイル: utils.py プロジェクト: waddell/urbansim_defaults
def run_developer(forms, agents, buildings, supply_fname, parcel_size,
                  ave_unit_size, total_units, feasibility, year=None,
                  target_vacancy=.1, form_to_btype_callback=None,
                  add_more_columns_callback=None, max_parcel_size=2000000,
                  residential=True, bldg_sqft_per_job=400.0,
                  min_unit_size=400, remove_developed_buildings=True,
                  unplace_agents=['households', 'jobs']):
    """
    Run the developer model to pick and build buildings

    Parameters
    ----------
    forms : string or list of strings
        Passed directly dev.pick
    agents : DataFrame Wrapper
        Used to compute the current demand for units/floorspace in the area
    buildings : DataFrame Wrapper
        Used to compute the current supply of units/floorspace in the area
    supply_fname : string
        Identifies the column in buildings which indicates the supply of
        units/floorspace
    parcel_size : Series
        Passed directly to dev.pick
    ave_unit_size : Series
        Passed directly to dev.pick - average residential unit size
    total_units : Series
        Passed directly to dev.pick - total current residential_units /
        job_spaces
    feasibility : DataFrame Wrapper
        The output from feasibility above (the table called 'feasibility')
    year : int
        The year of the simulation - will be assigned to 'year_built' on the
        new buildings
    target_vacancy : float
        The target vacancy rate - used to determine how much to build
    form_to_btype_callback : function
        Will be used to convert the 'forms' in the pro forma to
        'building_type_id' in the larger model
    add_more_columns_callback : function
        Takes a dataframe and returns a dataframe - is used to make custom
        modifications to the new buildings that get added
    max_parcel_size : float
        Passed directly to dev.pick - max parcel size to consider
    min_unit_size : float
        Passed directly to dev.pick - min unit size that is valid
    residential : boolean
        Passed directly to dev.pick - switches between adding/computing
        residential_units and job_spaces
    bldg_sqft_per_job : float
        Passed directly to dev.pick - specified the multiplier between
        floor spaces and job spaces for this form (does not vary by parcel
        as ave_unit_size does)
    remove_redeveloped_buildings : optional, boolean (default True)
        Remove all buildings on the parcels which are being developed on
    unplace_agents : optional : list of strings (default ['households', 'jobs'])
        For all tables in the list, will look for field building_id and set
        it to -1 for buildings which are removed - only executed if
        remove_developed_buildings is true

    Returns
    -------
    Writes the result back to the buildings table and returns the new
    buildings with available debugging information on each new building
    """

    dev = developer.Developer(feasibility.to_frame())

    target_units = dev.\
        compute_units_to_build(len(agents),
                               buildings[supply_fname].sum(),
                               target_vacancy)

    print "{:,} feasible buildings before running developer".format(
          len(dev.feasibility))

    new_buildings = dev.pick(forms,
                             target_units,
                             parcel_size,
                             ave_unit_size,
                             total_units,
                             max_parcel_size=max_parcel_size,
                             min_unit_size=min_unit_size,
                             drop_after_build=True,
                             residential=residential,
                             bldg_sqft_per_job=bldg_sqft_per_job)

    sim.add_table("feasibility", dev.feasibility)

    if new_buildings is None:
        return

    if len(new_buildings) == 0:
        return new_buildings

    if year is not None:
        new_buildings["year_built"] = year

    if not isinstance(forms, list):
        # form gets set only if forms is a list
        new_buildings["form"] = forms

    if form_to_btype_callback is not None:
        new_buildings["building_type_id"] = new_buildings.\
            apply(form_to_btype_callback, axis=1)

    new_buildings["stories"] = new_buildings.stories.apply(np.ceil)

    ret_buildings = new_buildings
    if add_more_columns_callback is not None:
        new_buildings = add_more_columns_callback(new_buildings)

    print "Adding {:,} buildings with {:,} {}".\
        format(len(new_buildings),
               int(new_buildings[supply_fname].sum()),
               supply_fname)

    print "{:,} feasible buildings after running developer".format(
          len(dev.feasibility))

    old_buildings = buildings.to_frame(buildings.local_columns)
    new_buildings = new_buildings[buildings.local_columns]

    if remove_developed_buildings:
        redev_buildings = old_buildings.parcel_id.isin(new_buildings.parcel_id)
        l = len(old_buildings)
        drop_buildings = old_buildings[redev_buildings]
        old_buildings = old_buildings[np.logical_not(redev_buildings)]
        l2 = len(old_buildings)
        if l2-l > 0:
            print "Dropped {} buildings because they were redeveloped".\
                format(l2-l)

        for tbl in unplace_agents:
            agents = sim.get_table(tbl)
            cols = agents.local_columns
            if "building_id" not in cols:
                # if it's a unit-level model, need to add building_id
                # explicitly
                cols += ["building_id"]
            agents = agents.to_frame(cols)
            displaced_agents = agents.building_id.isin(drop_buildings.index)
            print "Unplaced {} before: {}".format(tbl, len(agents.query(
                                                  "building_id == -1")))
            agents.building_id[displaced_agents] = -1
            print "Unplaced {} after: {}".format(tbl, len(agents.query(
                                                 "building_id == -1")))
            sim.add_table(tbl, agents)

    all_buildings = dev.merge(old_buildings, new_buildings)

    sim.add_table("buildings", all_buildings)

    if "residential_units" in sim.list_tables() and residential:
        # need to add units to the units table as well
        old_units = sim.get_table("residential_units")
        old_units = old_units.to_frame(old_units.local_columns)
        new_units = pd.DataFrame({
            "unit_residential_price": 0,
            "num_units": 1,
            "deed_restricted": 0,
            "unit_num": np.concatenate([np.arange(i) for i in \
                                        new_buildings.residential_units.values]),
            "building_id": np.repeat(new_buildings.index.values,
                                     new_buildings.residential_units.\
                                     astype('int32').values)
        }).sort(columns=["building_id", "unit_num"]).reset_index(drop=True)

        print "Adding {:,} units to the residential_units table".\
            format(len(new_units))
        all_units = dev.merge(old_units, new_units)
        all_units.index.name = "unit_id"

        sim.add_table("residential_units", all_units)

        return ret_buildings
        # pondered returning ret_buildings, new_units but users can get_table
        # the units if they want them - better to avoid breaking the api

    return ret_buildings