Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
example/data/*

.ipynb_checkpoints

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
71 changes: 71 additions & 0 deletions activitysim/activitysim.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
import urbansim.sim.simulation as sim
from urbansim.urbanchoice import interaction, mnl
import pandas as pd
import numpy as np
import os


def random_rows(df, n):
return df.take(np.random.choice(len(df), size=n, replace=False))


def read_model_spec(fname,
description_name="Description",
expression_name="Expression"):
"""
Read in the excel file and reformat for machines

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excel!?! No thanks!

"""
cfg = pd.read_csv(fname)
# don't need description and set the expression to the index
cfg = cfg.drop(description_name, axis=1).set_index(expression_name).stack()
return cfg


def identity_matrix(alt_names):
return pd.DataFrame(np.identity(len(alt_names)),
columns=alt_names,
index=alt_names)


def simple_simulate(choosers, alternatives, spec):
exprs = spec.index
coeffs = spec.values

# merge choosers and alternatives
_, df, _ = interaction.mnl_interaction_dataset(
choosers, alternatives, len(alternatives))

# evaluate the expressions to build the final matrix
vars, names = [], []
for expr in exprs:
if expr[0][0] == "@":
expr = "({}) * df.{}".format(expr[0][1:], expr[1])
try:
s = eval(expr)
except Exception as e:
print "Failed with Python eval:\n%s" % expr
raise e
else:
expr = "({}) * {}".format(*expr)
try:
s = df.eval(expr)
except Exception as e:
print "Failed with DataFrame eval:\n%s" % expr
raise e
names.append(expr)
vars.append(s)
model_design = pd.concat(vars, axis=1)
model_design.columns = names

df = random_rows(model_design, 100000).describe().transpose()
df = df[df["std"] == 0]
if len(df):
print "WARNING: Describe of columns with no variability:\n", df

choices = mnl.mnl_simulate(
model_design.as_matrix(),
coeffs,
numalts=len(alternatives),
returnprobs=False)

return pd.Series(choices, index=choosers.index), model_design
Empty file.
74 changes: 74 additions & 0 deletions activitysim/defaults/datasources.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
import numpy as np
import pandas as pd
import os
import uuid
import yaml
from urbansim.utils import misc
import urbansim.sim.simulation as sim
from .. import activitysim as asim

import warnings

warnings.filterwarnings('ignore', category=pd.io.pytables.PerformanceWarning)
pd.options.mode.chained_assignment = None


@sim.injectable('settings', cache=True)
def settings():
with open(os.path.join(misc.configs_dir(), "settings.yaml")) as f:
settings = yaml.load(f)
# monkey patch on the settings object since it's pretty global
# but will also be available as injectable
sim.settings = settings
return settings


@sim.injectable('run_number')
def run_number():
return misc.get_run_number()


@sim.injectable('uuid', cache=True)
def uuid_hex():
return uuid.uuid4().hex


@sim.injectable('store', cache=True)
def hdfstore(settings):
return pd.HDFStore(
os.path.join(misc.data_dir(), settings["store"]),
mode='r')


@sim.injectable("scenario")
def scenario(settings):
return settings["scenario"]


@sim.table(cache=True)
def land_use(store):
return store["land_use/taz_data"]


@sim.table(cache=True)
def accessibility(store):
df = store["skims/accessibility"]
df.columns = [c.upper() for c in df.columns]
return df


@sim.table(cache=True)
def households(store, settings):
if "households_sample_size" in settings:
return asim.random_rows(store["households"],
settings["households_sample_size"])
return store["households"]


@sim.table(cache=True)
def persons(store):
return store["persons"]


sim.broadcast('land_use', 'households', cast_index=True, onto_on='TAZ')
sim.broadcast('accessibility', 'households', cast_index=True, onto_on='TAZ')
73 changes: 73 additions & 0 deletions activitysim/defaults/variables.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
import urbansim.sim.simulation as sim
from activitysim.defaults import datasources


@sim.column("households")
def income_in_thousands(households):
return households.income / 1000


@sim.column("households")
def drivers(households, persons):
# we assume that everyone 16 and older is a potential driver
return persons.local.query("16 <= age").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_children(households, persons):
return persons.local.query("age <= 4").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_children(households, persons):
return persons.local.query("5 <= age <= 15").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_adolescents(households, persons):
return persons.local.query("16 <= age <= 17").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_college_age(households, persons):
return persons.local.query("18 <= age <= 24").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_adults(households, persons):
return persons.local.query("25 <= age <= 34").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("land_use")
def household_density(land_use):
return land_use.total_households / land_use.total_acres


@sim.column("land_use")
def employment_density(land_use):
return land_use.total_employment / land_use.total_acres


@sim.column("land_use")
def density_index(land_use):
return (land_use.household_density * land_use.employment_density) / \
(land_use.household_density + land_use.employment_density)


@sim.column("land_use")
def county_name(land_use, settings):
assert "county_map" in settings
inv_map = {v: k for k, v in settings["county_map"].items()}
return land_use.county_id.map(inv_map)
1 change: 1 addition & 0 deletions example/configs/auto_ownership_coeffs.csv
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Description,Expression,cars0,cars1,cars2,cars3,cars42 Adults (age 16+),drivers==2,,0,3.0773,3.1962,2.66163 Adults (age 16+),drivers==3,,0,3.5401,5.5131,5.2084+ Adults (age 16+),drivers>3,,2.0107,6.3662,8.5148,9.5807Persons age 16-17,num_adolescents,,0,-0.881,-1.7313,-1.7313Persons age 18-24,num_college_age,,-0.4087,-1.0095,-1.0107,-1.0107Persons age 35-34,num_young_adults,,0,-0.4849,-0.8596,-0.8596Presence of children age 0-4,num_young_children>0,,0.3669,0.7627,0.7627,0.7627Presence of children age 5-17,(num_children+num_adolescents)>0,,0.0158,0.2936,0.4769,0.4769"Number of workers, capped at 3",@df.workers.clip(upper=3),,0,0.2936,0.6389,0.8797"Piecewise Linear household income, $0-30k","@df.income_in_thousands.clip(0, 30)",,0.0383,0.054,0.0559,0.0619"Piecewise Linear household income, $30-75k","@(df.income_in_thousands-30).clip(0, 45)",,0,0.0083,0.011,0.0147"Piecewise Linear household income, $75k+, capped at $125k","@(df.income_in_thousands-75).clip(0, 50)",,0,0.0083,0.011,0.0147"Density index up to 10, if 0 workers","@(df.workers==0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 0 workers",@(df.workers==0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766"Density index up to 10, if 1+ workers","@(df.workers>0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 1+ workers",@(df.workers>0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766Constants,@1,,1.1865,-1.0846,-3.2502,-5.313San Francisco county,county_name == 'San Francisco',,0.4259,0.4683,0.1458,0.1458Solano county,county_name == 'Solano',,-0.566,-0.4429,-0.2372,-0.2372Napa county,county_name == 'Napa',,-0.566,-0.4429,-0.2372,-0.2372Sonoma county,county_name == 'Sonoma',,-0.566,-0.4429,-0.2372,-0.2372Marin county,county_name == 'Marin',,-0.2434,0,0,0"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 0 workers",(workers==0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.0626,0.0626,0.0626,0.0626"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 1+ workers",(workers>0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.1646,0.1646,0.1646,0.1646"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 0 workers",(workers==0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.3053,-0.3053,-0.3053,-0.3053"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 1+ workers",(workers>0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.5117,-0.5117,-0.5117,-0.5117"Retail accessibility by non-motorized, if 0 workers",(workers==0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Retail accessibility by non-motorized, if 1+ workers",(workers>0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Auto time savings per worker (over walk or transit, max 120) to work",workTourAutoTimeSavings/workers,,0.4707,0.6142,0.5705,0.7693
Expand Down
14 changes: 14 additions & 0 deletions example/configs/settings.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
store: mtc_asim.h5

households_sample_size: 100000

county_map:
San Francisco: 1
San Mateo: 2
Santa Clara: 3
Alameda: 4
Contra Costa: 5
Solano: 6
Napa: 7
Sonoma: 8
Marin: 9
1 change: 1 addition & 0 deletions example/data/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Keep data here
35 changes: 35 additions & 0 deletions example/models.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
import urbansim.sim.simulation as sim
import os
from activitysim import activitysim as asim


@sim.table()
def auto_alts():
return asim.identity_matrix(["cars%d" % i for i in range(5)])


@sim.injectable()
def auto_ownership_spec():
f = os.path.join('configs', "auto_ownership_coeffs.csv")
return asim.read_model_spec(f).head(4*26)


@sim.model()
def auto_ownership_simulate(households,
auto_alts,
auto_ownership_spec,
land_use,
accessibility):

choosers = sim.merge_tables(households.name, tables=[households,
land_use,
accessibility])
alternatives = auto_alts.to_frame()

choices, model_design = \
asim.simple_simulate(choosers, alternatives, auto_ownership_spec)

print "Choices:\n", choices.value_counts()
sim.add_column("households", "auto_ownership", choices)

return model_design
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
example/data/*

.ipynb_checkpoints

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
71 changes: 71 additions & 0 deletions activitysim/activitysim.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
import urbansim.sim.simulation as sim
from urbansim.urbanchoice import interaction, mnl
import pandas as pd
import numpy as np
import os


def random_rows(df, n):
return df.take(np.random.choice(len(df), size=n, replace=False))


def read_model_spec(fname,
description_name="Description",
expression_name="Expression"):
"""
Read in the excel file and reformat for machines

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excel!?! No thanks!

"""
cfg = pd.read_csv(fname)
# don't need description and set the expression to the index
cfg = cfg.drop(description_name, axis=1).set_index(expression_name).stack()
return cfg


def identity_matrix(alt_names):
return pd.DataFrame(np.identity(len(alt_names)),
columns=alt_names,
index=alt_names)


def simple_simulate(choosers, alternatives, spec):
exprs = spec.index
coeffs = spec.values

# merge choosers and alternatives
_, df, _ = interaction.mnl_interaction_dataset(
choosers, alternatives, len(alternatives))

# evaluate the expressions to build the final matrix
vars, names = [], []
for expr in exprs:
if expr[0][0] == "@":
expr = "({}) * df.{}".format(expr[0][1:], expr[1])
try:
s = eval(expr)
except Exception as e:
print "Failed with Python eval:\n%s" % expr
raise e
else:
expr = "({}) * {}".format(*expr)
try:
s = df.eval(expr)
except Exception as e:
print "Failed with DataFrame eval:\n%s" % expr
raise e
names.append(expr)
vars.append(s)
model_design = pd.concat(vars, axis=1)
model_design.columns = names

df = random_rows(model_design, 100000).describe().transpose()
df = df[df["std"] == 0]
if len(df):
print "WARNING: Describe of columns with no variability:\n", df

choices = mnl.mnl_simulate(
model_design.as_matrix(),
coeffs,
numalts=len(alternatives),
returnprobs=False)

return pd.Series(choices, index=choosers.index), model_design
Empty file.
74 changes: 74 additions & 0 deletions activitysim/defaults/datasources.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
import numpy as np
import pandas as pd
import os
import uuid
import yaml
from urbansim.utils import misc
import urbansim.sim.simulation as sim
from .. import activitysim as asim

import warnings

warnings.filterwarnings('ignore', category=pd.io.pytables.PerformanceWarning)
pd.options.mode.chained_assignment = None


@sim.injectable('settings', cache=True)
def settings():
with open(os.path.join(misc.configs_dir(), "settings.yaml")) as f:
settings = yaml.load(f)
# monkey patch on the settings object since it's pretty global
# but will also be available as injectable
sim.settings = settings
return settings


@sim.injectable('run_number')
def run_number():
return misc.get_run_number()


@sim.injectable('uuid', cache=True)
def uuid_hex():
return uuid.uuid4().hex


@sim.injectable('store', cache=True)
def hdfstore(settings):
return pd.HDFStore(
os.path.join(misc.data_dir(), settings["store"]),
mode='r')


@sim.injectable("scenario")
def scenario(settings):
return settings["scenario"]


@sim.table(cache=True)
def land_use(store):
return store["land_use/taz_data"]


@sim.table(cache=True)
def accessibility(store):
df = store["skims/accessibility"]
df.columns = [c.upper() for c in df.columns]
return df


@sim.table(cache=True)
def households(store, settings):
if "households_sample_size" in settings:
return asim.random_rows(store["households"],
settings["households_sample_size"])
return store["households"]


@sim.table(cache=True)
def persons(store):
return store["persons"]


sim.broadcast('land_use', 'households', cast_index=True, onto_on='TAZ')
sim.broadcast('accessibility', 'households', cast_index=True, onto_on='TAZ')
73 changes: 73 additions & 0 deletions activitysim/defaults/variables.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
import urbansim.sim.simulation as sim
from activitysim.defaults import datasources


@sim.column("households")
def income_in_thousands(households):
return households.income / 1000


@sim.column("households")
def drivers(households, persons):
# we assume that everyone 16 and older is a potential driver
return persons.local.query("16 <= age").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_children(households, persons):
return persons.local.query("age <= 4").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_children(households, persons):
return persons.local.query("5 <= age <= 15").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_adolescents(households, persons):
return persons.local.query("16 <= age <= 17").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_college_age(households, persons):
return persons.local.query("18 <= age <= 24").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_adults(households, persons):
return persons.local.query("25 <= age <= 34").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("land_use")
def household_density(land_use):
return land_use.total_households / land_use.total_acres


@sim.column("land_use")
def employment_density(land_use):
return land_use.total_employment / land_use.total_acres


@sim.column("land_use")
def density_index(land_use):
return (land_use.household_density * land_use.employment_density) / \
(land_use.household_density + land_use.employment_density)


@sim.column("land_use")
def county_name(land_use, settings):
assert "county_map" in settings
inv_map = {v: k for k, v in settings["county_map"].items()}
return land_use.county_id.map(inv_map)
1 change: 1 addition & 0 deletions example/configs/auto_ownership_coeffs.csv
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Description,Expression,cars0,cars1,cars2,cars3,cars42 Adults (age 16+),drivers==2,,0,3.0773,3.1962,2.66163 Adults (age 16+),drivers==3,,0,3.5401,5.5131,5.2084+ Adults (age 16+),drivers>3,,2.0107,6.3662,8.5148,9.5807Persons age 16-17,num_adolescents,,0,-0.881,-1.7313,-1.7313Persons age 18-24,num_college_age,,-0.4087,-1.0095,-1.0107,-1.0107Persons age 35-34,num_young_adults,,0,-0.4849,-0.8596,-0.8596Presence of children age 0-4,num_young_children>0,,0.3669,0.7627,0.7627,0.7627Presence of children age 5-17,(num_children+num_adolescents)>0,,0.0158,0.2936,0.4769,0.4769"Number of workers, capped at 3",@df.workers.clip(upper=3),,0,0.2936,0.6389,0.8797"Piecewise Linear household income, $0-30k","@df.income_in_thousands.clip(0, 30)",,0.0383,0.054,0.0559,0.0619"Piecewise Linear household income, $30-75k","@(df.income_in_thousands-30).clip(0, 45)",,0,0.0083,0.011,0.0147"Piecewise Linear household income, $75k+, capped at $125k","@(df.income_in_thousands-75).clip(0, 50)",,0,0.0083,0.011,0.0147"Density index up to 10, if 0 workers","@(df.workers==0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 0 workers",@(df.workers==0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766"Density index up to 10, if 1+ workers","@(df.workers>0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 1+ workers",@(df.workers>0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766Constants,@1,,1.1865,-1.0846,-3.2502,-5.313San Francisco county,county_name == 'San Francisco',,0.4259,0.4683,0.1458,0.1458Solano county,county_name == 'Solano',,-0.566,-0.4429,-0.2372,-0.2372Napa county,county_name == 'Napa',,-0.566,-0.4429,-0.2372,-0.2372Sonoma county,county_name == 'Sonoma',,-0.566,-0.4429,-0.2372,-0.2372Marin county,county_name == 'Marin',,-0.2434,0,0,0"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 0 workers",(workers==0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.0626,0.0626,0.0626,0.0626"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 1+ workers",(workers>0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.1646,0.1646,0.1646,0.1646"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 0 workers",(workers==0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.3053,-0.3053,-0.3053,-0.3053"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 1+ workers",(workers>0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.5117,-0.5117,-0.5117,-0.5117"Retail accessibility by non-motorized, if 0 workers",(workers==0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Retail accessibility by non-motorized, if 1+ workers",(workers>0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Auto time savings per worker (over walk or transit, max 120) to work",workTourAutoTimeSavings/workers,,0.4707,0.6142,0.5705,0.7693
Expand Down
14 changes: 14 additions & 0 deletions example/configs/settings.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
store: mtc_asim.h5

households_sample_size: 100000

county_map:
San Francisco: 1
San Mateo: 2
Santa Clara: 3
Alameda: 4
Contra Costa: 5
Solano: 6
Napa: 7
Sonoma: 8
Marin: 9
1 change: 1 addition & 0 deletions example/data/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Keep data here
35 changes: 35 additions & 0 deletions example/models.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
import urbansim.sim.simulation as sim
import os
from activitysim import activitysim as asim


@sim.table()
def auto_alts():
return asim.identity_matrix(["cars%d" % i for i in range(5)])


@sim.injectable()
def auto_ownership_spec():
f = os.path.join('configs', "auto_ownership_coeffs.csv")
return asim.read_model_spec(f).head(4*26)


@sim.model()
def auto_ownership_simulate(households,
auto_alts,
auto_ownership_spec,
land_use,
accessibility):

choosers = sim.merge_tables(households.name, tables=[households,
land_use,
accessibility])
alternatives = auto_alts.to_frame()

choices, model_design = \
asim.simple_simulate(choosers, alternatives, auto_ownership_spec)

print "Choices:\n", choices.value_counts()
sim.add_column("households", "auto_ownership", choices)

return model_design
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
example/data/*

.ipynb_checkpoints

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
71 changes: 71 additions & 0 deletions activitysim/activitysim.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
import urbansim.sim.simulation as sim
from urbansim.urbanchoice import interaction, mnl
import pandas as pd
import numpy as np
import os


def random_rows(df, n):
return df.take(np.random.choice(len(df), size=n, replace=False))


def read_model_spec(fname,
description_name="Description",
expression_name="Expression"):
"""
Read in the excel file and reformat for machines

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excel!?! No thanks!

"""
cfg = pd.read_csv(fname)
# don't need description and set the expression to the index
cfg = cfg.drop(description_name, axis=1).set_index(expression_name).stack()
return cfg


def identity_matrix(alt_names):
return pd.DataFrame(np.identity(len(alt_names)),
columns=alt_names,
index=alt_names)


def simple_simulate(choosers, alternatives, spec):
exprs = spec.index
coeffs = spec.values

# merge choosers and alternatives
_, df, _ = interaction.mnl_interaction_dataset(
choosers, alternatives, len(alternatives))

# evaluate the expressions to build the final matrix
vars, names = [], []
for expr in exprs:
if expr[0][0] == "@":
expr = "({}) * df.{}".format(expr[0][1:], expr[1])
try:
s = eval(expr)
except Exception as e:
print "Failed with Python eval:\n%s" % expr
raise e
else:
expr = "({}) * {}".format(*expr)
try:
s = df.eval(expr)
except Exception as e:
print "Failed with DataFrame eval:\n%s" % expr
raise e
names.append(expr)
vars.append(s)
model_design = pd.concat(vars, axis=1)
model_design.columns = names

df = random_rows(model_design, 100000).describe().transpose()
df = df[df["std"] == 0]
if len(df):
print "WARNING: Describe of columns with no variability:\n", df

choices = mnl.mnl_simulate(
model_design.as_matrix(),
coeffs,
numalts=len(alternatives),
returnprobs=False)

return pd.Series(choices, index=choosers.index), model_design
Empty file.
74 changes: 74 additions & 0 deletions activitysim/defaults/datasources.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
import numpy as np
import pandas as pd
import os
import uuid
import yaml
from urbansim.utils import misc
import urbansim.sim.simulation as sim
from .. import activitysim as asim

import warnings

warnings.filterwarnings('ignore', category=pd.io.pytables.PerformanceWarning)
pd.options.mode.chained_assignment = None


@sim.injectable('settings', cache=True)
def settings():
with open(os.path.join(misc.configs_dir(), "settings.yaml")) as f:
settings = yaml.load(f)
# monkey patch on the settings object since it's pretty global
# but will also be available as injectable
sim.settings = settings
return settings


@sim.injectable('run_number')
def run_number():
return misc.get_run_number()


@sim.injectable('uuid', cache=True)
def uuid_hex():
return uuid.uuid4().hex


@sim.injectable('store', cache=True)
def hdfstore(settings):
return pd.HDFStore(
os.path.join(misc.data_dir(), settings["store"]),
mode='r')


@sim.injectable("scenario")
def scenario(settings):
return settings["scenario"]


@sim.table(cache=True)
def land_use(store):
return store["land_use/taz_data"]


@sim.table(cache=True)
def accessibility(store):
df = store["skims/accessibility"]
df.columns = [c.upper() for c in df.columns]
return df


@sim.table(cache=True)
def households(store, settings):
if "households_sample_size" in settings:
return asim.random_rows(store["households"],
settings["households_sample_size"])
return store["households"]


@sim.table(cache=True)
def persons(store):
return store["persons"]


sim.broadcast('land_use', 'households', cast_index=True, onto_on='TAZ')
sim.broadcast('accessibility', 'households', cast_index=True, onto_on='TAZ')
73 changes: 73 additions & 0 deletions activitysim/defaults/variables.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
import urbansim.sim.simulation as sim
from activitysim.defaults import datasources


@sim.column("households")
def income_in_thousands(households):
return households.income / 1000


@sim.column("households")
def drivers(households, persons):
# we assume that everyone 16 and older is a potential driver
return persons.local.query("16 <= age").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_children(households, persons):
return persons.local.query("age <= 4").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_children(households, persons):
return persons.local.query("5 <= age <= 15").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_adolescents(households, persons):
return persons.local.query("16 <= age <= 17").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_college_age(households, persons):
return persons.local.query("18 <= age <= 24").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_adults(households, persons):
return persons.local.query("25 <= age <= 34").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("land_use")
def household_density(land_use):
return land_use.total_households / land_use.total_acres


@sim.column("land_use")
def employment_density(land_use):
return land_use.total_employment / land_use.total_acres


@sim.column("land_use")
def density_index(land_use):
return (land_use.household_density * land_use.employment_density) / \
(land_use.household_density + land_use.employment_density)


@sim.column("land_use")
def county_name(land_use, settings):
assert "county_map" in settings
inv_map = {v: k for k, v in settings["county_map"].items()}
return land_use.county_id.map(inv_map)
1 change: 1 addition & 0 deletions example/configs/auto_ownership_coeffs.csv
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Description,Expression,cars0,cars1,cars2,cars3,cars42 Adults (age 16+),drivers==2,,0,3.0773,3.1962,2.66163 Adults (age 16+),drivers==3,,0,3.5401,5.5131,5.2084+ Adults (age 16+),drivers>3,,2.0107,6.3662,8.5148,9.5807Persons age 16-17,num_adolescents,,0,-0.881,-1.7313,-1.7313Persons age 18-24,num_college_age,,-0.4087,-1.0095,-1.0107,-1.0107Persons age 35-34,num_young_adults,,0,-0.4849,-0.8596,-0.8596Presence of children age 0-4,num_young_children>0,,0.3669,0.7627,0.7627,0.7627Presence of children age 5-17,(num_children+num_adolescents)>0,,0.0158,0.2936,0.4769,0.4769"Number of workers, capped at 3",@df.workers.clip(upper=3),,0,0.2936,0.6389,0.8797"Piecewise Linear household income, $0-30k","@df.income_in_thousands.clip(0, 30)",,0.0383,0.054,0.0559,0.0619"Piecewise Linear household income, $30-75k","@(df.income_in_thousands-30).clip(0, 45)",,0,0.0083,0.011,0.0147"Piecewise Linear household income, $75k+, capped at $125k","@(df.income_in_thousands-75).clip(0, 50)",,0,0.0083,0.011,0.0147"Density index up to 10, if 0 workers","@(df.workers==0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 0 workers",@(df.workers==0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766"Density index up to 10, if 1+ workers","@(df.workers>0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 1+ workers",@(df.workers>0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766Constants,@1,,1.1865,-1.0846,-3.2502,-5.313San Francisco county,county_name == 'San Francisco',,0.4259,0.4683,0.1458,0.1458Solano county,county_name == 'Solano',,-0.566,-0.4429,-0.2372,-0.2372Napa county,county_name == 'Napa',,-0.566,-0.4429,-0.2372,-0.2372Sonoma county,county_name == 'Sonoma',,-0.566,-0.4429,-0.2372,-0.2372Marin county,county_name == 'Marin',,-0.2434,0,0,0"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 0 workers",(workers==0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.0626,0.0626,0.0626,0.0626"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 1+ workers",(workers>0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.1646,0.1646,0.1646,0.1646"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 0 workers",(workers==0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.3053,-0.3053,-0.3053,-0.3053"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 1+ workers",(workers>0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.5117,-0.5117,-0.5117,-0.5117"Retail accessibility by non-motorized, if 0 workers",(workers==0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Retail accessibility by non-motorized, if 1+ workers",(workers>0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Auto time savings per worker (over walk or transit, max 120) to work",workTourAutoTimeSavings/workers,,0.4707,0.6142,0.5705,0.7693
Expand Down
14 changes: 14 additions & 0 deletions example/configs/settings.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
store: mtc_asim.h5

households_sample_size: 100000

county_map:
San Francisco: 1
San Mateo: 2
Santa Clara: 3
Alameda: 4
Contra Costa: 5
Solano: 6
Napa: 7
Sonoma: 8
Marin: 9
1 change: 1 addition & 0 deletions example/data/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Keep data here
35 changes: 35 additions & 0 deletions example/models.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
import urbansim.sim.simulation as sim
import os
from activitysim import activitysim as asim


@sim.table()
def auto_alts():
return asim.identity_matrix(["cars%d" % i for i in range(5)])


@sim.injectable()
def auto_ownership_spec():
f = os.path.join('configs', "auto_ownership_coeffs.csv")
return asim.read_model_spec(f).head(4*26)


@sim.model()
def auto_ownership_simulate(households,
auto_alts,
auto_ownership_spec,
land_use,
accessibility):

choosers = sim.merge_tables(households.name, tables=[households,
land_use,
accessibility])
alternatives = auto_alts.to_frame()

choices, model_design = \
asim.simple_simulate(choosers, alternatives, auto_ownership_spec)

print "Choices:\n", choices.value_counts()
sim.add_column("households", "auto_ownership", choices)

return model_design
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
example/data/*

.ipynb_checkpoints

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
71 changes: 71 additions & 0 deletions activitysim/activitysim.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
import urbansim.sim.simulation as sim
from urbansim.urbanchoice import interaction, mnl
import pandas as pd
import numpy as np
import os


def random_rows(df, n):
return df.take(np.random.choice(len(df), size=n, replace=False))


def read_model_spec(fname,
description_name="Description",
expression_name="Expression"):
"""
Read in the excel file and reformat for machines

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excel!?! No thanks!

"""
cfg = pd.read_csv(fname)
# don't need description and set the expression to the index
cfg = cfg.drop(description_name, axis=1).set_index(expression_name).stack()
return cfg


def identity_matrix(alt_names):
return pd.DataFrame(np.identity(len(alt_names)),
columns=alt_names,
index=alt_names)


def simple_simulate(choosers, alternatives, spec):
exprs = spec.index
coeffs = spec.values

# merge choosers and alternatives
_, df, _ = interaction.mnl_interaction_dataset(
choosers, alternatives, len(alternatives))

# evaluate the expressions to build the final matrix
vars, names = [], []
for expr in exprs:
if expr[0][0] == "@":
expr = "({}) * df.{}".format(expr[0][1:], expr[1])
try:
s = eval(expr)
except Exception as e:
print "Failed with Python eval:\n%s" % expr
raise e
else:
expr = "({}) * {}".format(*expr)
try:
s = df.eval(expr)
except Exception as e:
print "Failed with DataFrame eval:\n%s" % expr
raise e
names.append(expr)
vars.append(s)
model_design = pd.concat(vars, axis=1)
model_design.columns = names

df = random_rows(model_design, 100000).describe().transpose()
df = df[df["std"] == 0]
if len(df):
print "WARNING: Describe of columns with no variability:\n", df

choices = mnl.mnl_simulate(
model_design.as_matrix(),
coeffs,
numalts=len(alternatives),
returnprobs=False)

return pd.Series(choices, index=choosers.index), model_design
Empty file.
74 changes: 74 additions & 0 deletions activitysim/defaults/datasources.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
import numpy as np
import pandas as pd
import os
import uuid
import yaml
from urbansim.utils import misc
import urbansim.sim.simulation as sim
from .. import activitysim as asim

import warnings

warnings.filterwarnings('ignore', category=pd.io.pytables.PerformanceWarning)
pd.options.mode.chained_assignment = None


@sim.injectable('settings', cache=True)
def settings():
with open(os.path.join(misc.configs_dir(), "settings.yaml")) as f:
settings = yaml.load(f)
# monkey patch on the settings object since it's pretty global
# but will also be available as injectable
sim.settings = settings
return settings


@sim.injectable('run_number')
def run_number():
return misc.get_run_number()


@sim.injectable('uuid', cache=True)
def uuid_hex():
return uuid.uuid4().hex


@sim.injectable('store', cache=True)
def hdfstore(settings):
return pd.HDFStore(
os.path.join(misc.data_dir(), settings["store"]),
mode='r')


@sim.injectable("scenario")
def scenario(settings):
return settings["scenario"]


@sim.table(cache=True)
def land_use(store):
return store["land_use/taz_data"]


@sim.table(cache=True)
def accessibility(store):
df = store["skims/accessibility"]
df.columns = [c.upper() for c in df.columns]
return df


@sim.table(cache=True)
def households(store, settings):
if "households_sample_size" in settings:
return asim.random_rows(store["households"],
settings["households_sample_size"])
return store["households"]


@sim.table(cache=True)
def persons(store):
return store["persons"]


sim.broadcast('land_use', 'households', cast_index=True, onto_on='TAZ')
sim.broadcast('accessibility', 'households', cast_index=True, onto_on='TAZ')
73 changes: 73 additions & 0 deletions activitysim/defaults/variables.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
import urbansim.sim.simulation as sim
from activitysim.defaults import datasources


@sim.column("households")
def income_in_thousands(households):
return households.income / 1000


@sim.column("households")
def drivers(households, persons):
# we assume that everyone 16 and older is a potential driver
return persons.local.query("16 <= age").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_children(households, persons):
return persons.local.query("age <= 4").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_children(households, persons):
return persons.local.query("5 <= age <= 15").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_adolescents(households, persons):
return persons.local.query("16 <= age <= 17").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_college_age(households, persons):
return persons.local.query("18 <= age <= 24").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_adults(households, persons):
return persons.local.query("25 <= age <= 34").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("land_use")
def household_density(land_use):
return land_use.total_households / land_use.total_acres


@sim.column("land_use")
def employment_density(land_use):
return land_use.total_employment / land_use.total_acres


@sim.column("land_use")
def density_index(land_use):
return (land_use.household_density * land_use.employment_density) / \
(land_use.household_density + land_use.employment_density)


@sim.column("land_use")
def county_name(land_use, settings):
assert "county_map" in settings
inv_map = {v: k for k, v in settings["county_map"].items()}
return land_use.county_id.map(inv_map)
1 change: 1 addition & 0 deletions example/configs/auto_ownership_coeffs.csv
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Description,Expression,cars0,cars1,cars2,cars3,cars42 Adults (age 16+),drivers==2,,0,3.0773,3.1962,2.66163 Adults (age 16+),drivers==3,,0,3.5401,5.5131,5.2084+ Adults (age 16+),drivers>3,,2.0107,6.3662,8.5148,9.5807Persons age 16-17,num_adolescents,,0,-0.881,-1.7313,-1.7313Persons age 18-24,num_college_age,,-0.4087,-1.0095,-1.0107,-1.0107Persons age 35-34,num_young_adults,,0,-0.4849,-0.8596,-0.8596Presence of children age 0-4,num_young_children>0,,0.3669,0.7627,0.7627,0.7627Presence of children age 5-17,(num_children+num_adolescents)>0,,0.0158,0.2936,0.4769,0.4769"Number of workers, capped at 3",@df.workers.clip(upper=3),,0,0.2936,0.6389,0.8797"Piecewise Linear household income, $0-30k","@df.income_in_thousands.clip(0, 30)",,0.0383,0.054,0.0559,0.0619"Piecewise Linear household income, $30-75k","@(df.income_in_thousands-30).clip(0, 45)",,0,0.0083,0.011,0.0147"Piecewise Linear household income, $75k+, capped at $125k","@(df.income_in_thousands-75).clip(0, 50)",,0,0.0083,0.011,0.0147"Density index up to 10, if 0 workers","@(df.workers==0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 0 workers",@(df.workers==0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766"Density index up to 10, if 1+ workers","@(df.workers>0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 1+ workers",@(df.workers>0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766Constants,@1,,1.1865,-1.0846,-3.2502,-5.313San Francisco county,county_name == 'San Francisco',,0.4259,0.4683,0.1458,0.1458Solano county,county_name == 'Solano',,-0.566,-0.4429,-0.2372,-0.2372Napa county,county_name == 'Napa',,-0.566,-0.4429,-0.2372,-0.2372Sonoma county,county_name == 'Sonoma',,-0.566,-0.4429,-0.2372,-0.2372Marin county,county_name == 'Marin',,-0.2434,0,0,0"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 0 workers",(workers==0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.0626,0.0626,0.0626,0.0626"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 1+ workers",(workers>0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.1646,0.1646,0.1646,0.1646"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 0 workers",(workers==0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.3053,-0.3053,-0.3053,-0.3053"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 1+ workers",(workers>0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.5117,-0.5117,-0.5117,-0.5117"Retail accessibility by non-motorized, if 0 workers",(workers==0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Retail accessibility by non-motorized, if 1+ workers",(workers>0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Auto time savings per worker (over walk or transit, max 120) to work",workTourAutoTimeSavings/workers,,0.4707,0.6142,0.5705,0.7693
Expand Down
14 changes: 14 additions & 0 deletions example/configs/settings.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
store: mtc_asim.h5

households_sample_size: 100000

county_map:
San Francisco: 1
San Mateo: 2
Santa Clara: 3
Alameda: 4
Contra Costa: 5
Solano: 6
Napa: 7
Sonoma: 8
Marin: 9
1 change: 1 addition & 0 deletions example/data/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Keep data here
35 changes: 35 additions & 0 deletions example/models.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
import urbansim.sim.simulation as sim
import os
from activitysim import activitysim as asim


@sim.table()
def auto_alts():
return asim.identity_matrix(["cars%d" % i for i in range(5)])


@sim.injectable()
def auto_ownership_spec():
f = os.path.join('configs', "auto_ownership_coeffs.csv")
return asim.read_model_spec(f).head(4*26)


@sim.model()
def auto_ownership_simulate(households,
auto_alts,
auto_ownership_spec,
land_use,
accessibility):

choosers = sim.merge_tables(households.name, tables=[households,
land_use,
accessibility])
alternatives = auto_alts.to_frame()

choices, model_design = \
asim.simple_simulate(choosers, alternatives, auto_ownership_spec)

print "Choices:\n", choices.value_counts()
sim.add_column("households", "auto_ownership", choices)

return model_design
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
example/data/*

.ipynb_checkpoints

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
71 changes: 71 additions & 0 deletions activitysim/activitysim.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
import urbansim.sim.simulation as sim
from urbansim.urbanchoice import interaction, mnl
import pandas as pd
import numpy as np
import os


def random_rows(df, n):
return df.take(np.random.choice(len(df), size=n, replace=False))


def read_model_spec(fname,
description_name="Description",
expression_name="Expression"):
"""
Read in the excel file and reformat for machines

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excel!?! No thanks!

"""
cfg = pd.read_csv(fname)
# don't need description and set the expression to the index
cfg = cfg.drop(description_name, axis=1).set_index(expression_name).stack()
return cfg


def identity_matrix(alt_names):
return pd.DataFrame(np.identity(len(alt_names)),
columns=alt_names,
index=alt_names)


def simple_simulate(choosers, alternatives, spec):
exprs = spec.index
coeffs = spec.values

# merge choosers and alternatives
_, df, _ = interaction.mnl_interaction_dataset(
choosers, alternatives, len(alternatives))

# evaluate the expressions to build the final matrix
vars, names = [], []
for expr in exprs:
if expr[0][0] == "@":
expr = "({}) * df.{}".format(expr[0][1:], expr[1])
try:
s = eval(expr)
except Exception as e:
print "Failed with Python eval:\n%s" % expr
raise e
else:
expr = "({}) * {}".format(*expr)
try:
s = df.eval(expr)
except Exception as e:
print "Failed with DataFrame eval:\n%s" % expr
raise e
names.append(expr)
vars.append(s)
model_design = pd.concat(vars, axis=1)
model_design.columns = names

df = random_rows(model_design, 100000).describe().transpose()
df = df[df["std"] == 0]
if len(df):
print "WARNING: Describe of columns with no variability:\n", df

choices = mnl.mnl_simulate(
model_design.as_matrix(),
coeffs,
numalts=len(alternatives),
returnprobs=False)

return pd.Series(choices, index=choosers.index), model_design
Empty file.
74 changes: 74 additions & 0 deletions activitysim/defaults/datasources.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
import numpy as np
import pandas as pd
import os
import uuid
import yaml
from urbansim.utils import misc
import urbansim.sim.simulation as sim
from .. import activitysim as asim

import warnings

warnings.filterwarnings('ignore', category=pd.io.pytables.PerformanceWarning)
pd.options.mode.chained_assignment = None


@sim.injectable('settings', cache=True)
def settings():
with open(os.path.join(misc.configs_dir(), "settings.yaml")) as f:
settings = yaml.load(f)
# monkey patch on the settings object since it's pretty global
# but will also be available as injectable
sim.settings = settings
return settings


@sim.injectable('run_number')
def run_number():
return misc.get_run_number()


@sim.injectable('uuid', cache=True)
def uuid_hex():
return uuid.uuid4().hex


@sim.injectable('store', cache=True)
def hdfstore(settings):
return pd.HDFStore(
os.path.join(misc.data_dir(), settings["store"]),
mode='r')


@sim.injectable("scenario")
def scenario(settings):
return settings["scenario"]


@sim.table(cache=True)
def land_use(store):
return store["land_use/taz_data"]


@sim.table(cache=True)
def accessibility(store):
df = store["skims/accessibility"]
df.columns = [c.upper() for c in df.columns]
return df


@sim.table(cache=True)
def households(store, settings):
if "households_sample_size" in settings:
return asim.random_rows(store["households"],
settings["households_sample_size"])
return store["households"]


@sim.table(cache=True)
def persons(store):
return store["persons"]


sim.broadcast('land_use', 'households', cast_index=True, onto_on='TAZ')
sim.broadcast('accessibility', 'households', cast_index=True, onto_on='TAZ')
73 changes: 73 additions & 0 deletions activitysim/defaults/variables.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
import urbansim.sim.simulation as sim
from activitysim.defaults import datasources


@sim.column("households")
def income_in_thousands(households):
return households.income / 1000


@sim.column("households")
def drivers(households, persons):
# we assume that everyone 16 and older is a potential driver
return persons.local.query("16 <= age").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_children(households, persons):
return persons.local.query("age <= 4").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_children(households, persons):
return persons.local.query("5 <= age <= 15").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_adolescents(households, persons):
return persons.local.query("16 <= age <= 17").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_college_age(households, persons):
return persons.local.query("18 <= age <= 24").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_adults(households, persons):
return persons.local.query("25 <= age <= 34").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("land_use")
def household_density(land_use):
return land_use.total_households / land_use.total_acres


@sim.column("land_use")
def employment_density(land_use):
return land_use.total_employment / land_use.total_acres


@sim.column("land_use")
def density_index(land_use):
return (land_use.household_density * land_use.employment_density) / \
(land_use.household_density + land_use.employment_density)


@sim.column("land_use")
def county_name(land_use, settings):
assert "county_map" in settings
inv_map = {v: k for k, v in settings["county_map"].items()}
return land_use.county_id.map(inv_map)
1 change: 1 addition & 0 deletions example/configs/auto_ownership_coeffs.csv
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Description,Expression,cars0,cars1,cars2,cars3,cars42 Adults (age 16+),drivers==2,,0,3.0773,3.1962,2.66163 Adults (age 16+),drivers==3,,0,3.5401,5.5131,5.2084+ Adults (age 16+),drivers>3,,2.0107,6.3662,8.5148,9.5807Persons age 16-17,num_adolescents,,0,-0.881,-1.7313,-1.7313Persons age 18-24,num_college_age,,-0.4087,-1.0095,-1.0107,-1.0107Persons age 35-34,num_young_adults,,0,-0.4849,-0.8596,-0.8596Presence of children age 0-4,num_young_children>0,,0.3669,0.7627,0.7627,0.7627Presence of children age 5-17,(num_children+num_adolescents)>0,,0.0158,0.2936,0.4769,0.4769"Number of workers, capped at 3",@df.workers.clip(upper=3),,0,0.2936,0.6389,0.8797"Piecewise Linear household income, $0-30k","@df.income_in_thousands.clip(0, 30)",,0.0383,0.054,0.0559,0.0619"Piecewise Linear household income, $30-75k","@(df.income_in_thousands-30).clip(0, 45)",,0,0.0083,0.011,0.0147"Piecewise Linear household income, $75k+, capped at $125k","@(df.income_in_thousands-75).clip(0, 50)",,0,0.0083,0.011,0.0147"Density index up to 10, if 0 workers","@(df.workers==0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 0 workers",@(df.workers==0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766"Density index up to 10, if 1+ workers","@(df.workers>0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 1+ workers",@(df.workers>0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766Constants,@1,,1.1865,-1.0846,-3.2502,-5.313San Francisco county,county_name == 'San Francisco',,0.4259,0.4683,0.1458,0.1458Solano county,county_name == 'Solano',,-0.566,-0.4429,-0.2372,-0.2372Napa county,county_name == 'Napa',,-0.566,-0.4429,-0.2372,-0.2372Sonoma county,county_name == 'Sonoma',,-0.566,-0.4429,-0.2372,-0.2372Marin county,county_name == 'Marin',,-0.2434,0,0,0"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 0 workers",(workers==0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.0626,0.0626,0.0626,0.0626"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 1+ workers",(workers>0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.1646,0.1646,0.1646,0.1646"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 0 workers",(workers==0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.3053,-0.3053,-0.3053,-0.3053"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 1+ workers",(workers>0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.5117,-0.5117,-0.5117,-0.5117"Retail accessibility by non-motorized, if 0 workers",(workers==0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Retail accessibility by non-motorized, if 1+ workers",(workers>0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Auto time savings per worker (over walk or transit, max 120) to work",workTourAutoTimeSavings/workers,,0.4707,0.6142,0.5705,0.7693
Expand Down
14 changes: 14 additions & 0 deletions example/configs/settings.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
store: mtc_asim.h5

households_sample_size: 100000

county_map:
San Francisco: 1
San Mateo: 2
Santa Clara: 3
Alameda: 4
Contra Costa: 5
Solano: 6
Napa: 7
Sonoma: 8
Marin: 9
1 change: 1 addition & 0 deletions example/data/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Keep data here
35 changes: 35 additions & 0 deletions example/models.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
import urbansim.sim.simulation as sim
import os
from activitysim import activitysim as asim


@sim.table()
def auto_alts():
return asim.identity_matrix(["cars%d" % i for i in range(5)])


@sim.injectable()
def auto_ownership_spec():
f = os.path.join('configs', "auto_ownership_coeffs.csv")
return asim.read_model_spec(f).head(4*26)


@sim.model()
def auto_ownership_simulate(households,
auto_alts,
auto_ownership_spec,
land_use,
accessibility):

choosers = sim.merge_tables(households.name, tables=[households,
land_use,
accessibility])
alternatives = auto_alts.to_frame()

choices, model_design = \
asim.simple_simulate(choosers, alternatives, auto_ownership_spec)

print "Choices:\n", choices.value_counts()
sim.add_column("households", "auto_ownership", choices)

return model_design
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
example/data/*

.ipynb_checkpoints

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
71 changes: 71 additions & 0 deletions activitysim/activitysim.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
import urbansim.sim.simulation as sim
from urbansim.urbanchoice import interaction, mnl
import pandas as pd
import numpy as np
import os


def random_rows(df, n):
return df.take(np.random.choice(len(df), size=n, replace=False))


def read_model_spec(fname,
description_name="Description",
expression_name="Expression"):
"""
Read in the excel file and reformat for machines

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excel!?! No thanks!

"""
cfg = pd.read_csv(fname)
# don't need description and set the expression to the index
cfg = cfg.drop(description_name, axis=1).set_index(expression_name).stack()
return cfg


def identity_matrix(alt_names):
return pd.DataFrame(np.identity(len(alt_names)),
columns=alt_names,
index=alt_names)


def simple_simulate(choosers, alternatives, spec):
exprs = spec.index
coeffs = spec.values

# merge choosers and alternatives
_, df, _ = interaction.mnl_interaction_dataset(
choosers, alternatives, len(alternatives))

# evaluate the expressions to build the final matrix
vars, names = [], []
for expr in exprs:
if expr[0][0] == "@":
expr = "({}) * df.{}".format(expr[0][1:], expr[1])
try:
s = eval(expr)
except Exception as e:
print "Failed with Python eval:\n%s" % expr
raise e
else:
expr = "({}) * {}".format(*expr)
try:
s = df.eval(expr)
except Exception as e:
print "Failed with DataFrame eval:\n%s" % expr
raise e
names.append(expr)
vars.append(s)
model_design = pd.concat(vars, axis=1)
model_design.columns = names

df = random_rows(model_design, 100000).describe().transpose()
df = df[df["std"] == 0]
if len(df):
print "WARNING: Describe of columns with no variability:\n", df

choices = mnl.mnl_simulate(
model_design.as_matrix(),
coeffs,
numalts=len(alternatives),
returnprobs=False)

return pd.Series(choices, index=choosers.index), model_design
Empty file.
74 changes: 74 additions & 0 deletions activitysim/defaults/datasources.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
import numpy as np
import pandas as pd
import os
import uuid
import yaml
from urbansim.utils import misc
import urbansim.sim.simulation as sim
from .. import activitysim as asim

import warnings

warnings.filterwarnings('ignore', category=pd.io.pytables.PerformanceWarning)
pd.options.mode.chained_assignment = None


@sim.injectable('settings', cache=True)
def settings():
with open(os.path.join(misc.configs_dir(), "settings.yaml")) as f:
settings = yaml.load(f)
# monkey patch on the settings object since it's pretty global
# but will also be available as injectable
sim.settings = settings
return settings


@sim.injectable('run_number')
def run_number():
return misc.get_run_number()


@sim.injectable('uuid', cache=True)
def uuid_hex():
return uuid.uuid4().hex


@sim.injectable('store', cache=True)
def hdfstore(settings):
return pd.HDFStore(
os.path.join(misc.data_dir(), settings["store"]),
mode='r')


@sim.injectable("scenario")
def scenario(settings):
return settings["scenario"]


@sim.table(cache=True)
def land_use(store):
return store["land_use/taz_data"]


@sim.table(cache=True)
def accessibility(store):
df = store["skims/accessibility"]
df.columns = [c.upper() for c in df.columns]
return df


@sim.table(cache=True)
def households(store, settings):
if "households_sample_size" in settings:
return asim.random_rows(store["households"],
settings["households_sample_size"])
return store["households"]


@sim.table(cache=True)
def persons(store):
return store["persons"]


sim.broadcast('land_use', 'households', cast_index=True, onto_on='TAZ')
sim.broadcast('accessibility', 'households', cast_index=True, onto_on='TAZ')
73 changes: 73 additions & 0 deletions activitysim/defaults/variables.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
import urbansim.sim.simulation as sim
from activitysim.defaults import datasources


@sim.column("households")
def income_in_thousands(households):
return households.income / 1000


@sim.column("households")
def drivers(households, persons):
# we assume that everyone 16 and older is a potential driver
return persons.local.query("16 <= age").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_children(households, persons):
return persons.local.query("age <= 4").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_children(households, persons):
return persons.local.query("5 <= age <= 15").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_adolescents(households, persons):
return persons.local.query("16 <= age <= 17").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_college_age(households, persons):
return persons.local.query("18 <= age <= 24").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_adults(households, persons):
return persons.local.query("25 <= age <= 34").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("land_use")
def household_density(land_use):
return land_use.total_households / land_use.total_acres


@sim.column("land_use")
def employment_density(land_use):
return land_use.total_employment / land_use.total_acres


@sim.column("land_use")
def density_index(land_use):
return (land_use.household_density * land_use.employment_density) / \
(land_use.household_density + land_use.employment_density)


@sim.column("land_use")
def county_name(land_use, settings):
assert "county_map" in settings
inv_map = {v: k for k, v in settings["county_map"].items()}
return land_use.county_id.map(inv_map)
1 change: 1 addition & 0 deletions example/configs/auto_ownership_coeffs.csv
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Description,Expression,cars0,cars1,cars2,cars3,cars42 Adults (age 16+),drivers==2,,0,3.0773,3.1962,2.66163 Adults (age 16+),drivers==3,,0,3.5401,5.5131,5.2084+ Adults (age 16+),drivers>3,,2.0107,6.3662,8.5148,9.5807Persons age 16-17,num_adolescents,,0,-0.881,-1.7313,-1.7313Persons age 18-24,num_college_age,,-0.4087,-1.0095,-1.0107,-1.0107Persons age 35-34,num_young_adults,,0,-0.4849,-0.8596,-0.8596Presence of children age 0-4,num_young_children>0,,0.3669,0.7627,0.7627,0.7627Presence of children age 5-17,(num_children+num_adolescents)>0,,0.0158,0.2936,0.4769,0.4769"Number of workers, capped at 3",@df.workers.clip(upper=3),,0,0.2936,0.6389,0.8797"Piecewise Linear household income, $0-30k","@df.income_in_thousands.clip(0, 30)",,0.0383,0.054,0.0559,0.0619"Piecewise Linear household income, $30-75k","@(df.income_in_thousands-30).clip(0, 45)",,0,0.0083,0.011,0.0147"Piecewise Linear household income, $75k+, capped at $125k","@(df.income_in_thousands-75).clip(0, 50)",,0,0.0083,0.011,0.0147"Density index up to 10, if 0 workers","@(df.workers==0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 0 workers",@(df.workers==0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766"Density index up to 10, if 1+ workers","@(df.workers>0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 1+ workers",@(df.workers>0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766Constants,@1,,1.1865,-1.0846,-3.2502,-5.313San Francisco county,county_name == 'San Francisco',,0.4259,0.4683,0.1458,0.1458Solano county,county_name == 'Solano',,-0.566,-0.4429,-0.2372,-0.2372Napa county,county_name == 'Napa',,-0.566,-0.4429,-0.2372,-0.2372Sonoma county,county_name == 'Sonoma',,-0.566,-0.4429,-0.2372,-0.2372Marin county,county_name == 'Marin',,-0.2434,0,0,0"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 0 workers",(workers==0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.0626,0.0626,0.0626,0.0626"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 1+ workers",(workers>0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.1646,0.1646,0.1646,0.1646"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 0 workers",(workers==0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.3053,-0.3053,-0.3053,-0.3053"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 1+ workers",(workers>0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.5117,-0.5117,-0.5117,-0.5117"Retail accessibility by non-motorized, if 0 workers",(workers==0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Retail accessibility by non-motorized, if 1+ workers",(workers>0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Auto time savings per worker (over walk or transit, max 120) to work",workTourAutoTimeSavings/workers,,0.4707,0.6142,0.5705,0.7693
Expand Down
14 changes: 14 additions & 0 deletions example/configs/settings.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
store: mtc_asim.h5

households_sample_size: 100000

county_map:
San Francisco: 1
San Mateo: 2
Santa Clara: 3
Alameda: 4
Contra Costa: 5
Solano: 6
Napa: 7
Sonoma: 8
Marin: 9
1 change: 1 addition & 0 deletions example/data/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Keep data here
35 changes: 35 additions & 0 deletions example/models.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
import urbansim.sim.simulation as sim
import os
from activitysim import activitysim as asim


@sim.table()
def auto_alts():
return asim.identity_matrix(["cars%d" % i for i in range(5)])


@sim.injectable()
def auto_ownership_spec():
f = os.path.join('configs', "auto_ownership_coeffs.csv")
return asim.read_model_spec(f).head(4*26)


@sim.model()
def auto_ownership_simulate(households,
auto_alts,
auto_ownership_spec,
land_use,
accessibility):

choosers = sim.merge_tables(households.name, tables=[households,
land_use,
accessibility])
alternatives = auto_alts.to_frame()

choices, model_design = \
asim.simple_simulate(choosers, alternatives, auto_ownership_spec)

print "Choices:\n", choices.value_counts()
sim.add_column("households", "auto_ownership", choices)

return model_design
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
example/data/*

.ipynb_checkpoints

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
71 changes: 71 additions & 0 deletions activitysim/activitysim.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
import urbansim.sim.simulation as sim
from urbansim.urbanchoice import interaction, mnl
import pandas as pd
import numpy as np
import os


def random_rows(df, n):
return df.take(np.random.choice(len(df), size=n, replace=False))


def read_model_spec(fname,
description_name="Description",
expression_name="Expression"):
"""
Read in the excel file and reformat for machines

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excel!?! No thanks!

"""
cfg = pd.read_csv(fname)
# don't need description and set the expression to the index
cfg = cfg.drop(description_name, axis=1).set_index(expression_name).stack()
return cfg


def identity_matrix(alt_names):
return pd.DataFrame(np.identity(len(alt_names)),
columns=alt_names,
index=alt_names)


def simple_simulate(choosers, alternatives, spec):
exprs = spec.index
coeffs = spec.values

# merge choosers and alternatives
_, df, _ = interaction.mnl_interaction_dataset(
choosers, alternatives, len(alternatives))

# evaluate the expressions to build the final matrix
vars, names = [], []
for expr in exprs:
if expr[0][0] == "@":
expr = "({}) * df.{}".format(expr[0][1:], expr[1])
try:
s = eval(expr)
except Exception as e:
print "Failed with Python eval:\n%s" % expr
raise e
else:
expr = "({}) * {}".format(*expr)
try:
s = df.eval(expr)
except Exception as e:
print "Failed with DataFrame eval:\n%s" % expr
raise e
names.append(expr)
vars.append(s)
model_design = pd.concat(vars, axis=1)
model_design.columns = names

df = random_rows(model_design, 100000).describe().transpose()
df = df[df["std"] == 0]
if len(df):
print "WARNING: Describe of columns with no variability:\n", df

choices = mnl.mnl_simulate(
model_design.as_matrix(),
coeffs,
numalts=len(alternatives),
returnprobs=False)

return pd.Series(choices, index=choosers.index), model_design
Empty file.
74 changes: 74 additions & 0 deletions activitysim/defaults/datasources.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
import numpy as np
import pandas as pd
import os
import uuid
import yaml
from urbansim.utils import misc
import urbansim.sim.simulation as sim
from .. import activitysim as asim

import warnings

warnings.filterwarnings('ignore', category=pd.io.pytables.PerformanceWarning)
pd.options.mode.chained_assignment = None


@sim.injectable('settings', cache=True)
def settings():
with open(os.path.join(misc.configs_dir(), "settings.yaml")) as f:
settings = yaml.load(f)
# monkey patch on the settings object since it's pretty global
# but will also be available as injectable
sim.settings = settings
return settings


@sim.injectable('run_number')
def run_number():
return misc.get_run_number()


@sim.injectable('uuid', cache=True)
def uuid_hex():
return uuid.uuid4().hex


@sim.injectable('store', cache=True)
def hdfstore(settings):
return pd.HDFStore(
os.path.join(misc.data_dir(), settings["store"]),
mode='r')


@sim.injectable("scenario")
def scenario(settings):
return settings["scenario"]


@sim.table(cache=True)
def land_use(store):
return store["land_use/taz_data"]


@sim.table(cache=True)
def accessibility(store):
df = store["skims/accessibility"]
df.columns = [c.upper() for c in df.columns]
return df


@sim.table(cache=True)
def households(store, settings):
if "households_sample_size" in settings:
return asim.random_rows(store["households"],
settings["households_sample_size"])
return store["households"]


@sim.table(cache=True)
def persons(store):
return store["persons"]


sim.broadcast('land_use', 'households', cast_index=True, onto_on='TAZ')
sim.broadcast('accessibility', 'households', cast_index=True, onto_on='TAZ')
73 changes: 73 additions & 0 deletions activitysim/defaults/variables.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
import urbansim.sim.simulation as sim
from activitysim.defaults import datasources


@sim.column("households")
def income_in_thousands(households):
return households.income / 1000


@sim.column("households")
def drivers(households, persons):
# we assume that everyone 16 and older is a potential driver
return persons.local.query("16 <= age").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_children(households, persons):
return persons.local.query("age <= 4").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_children(households, persons):
return persons.local.query("5 <= age <= 15").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_adolescents(households, persons):
return persons.local.query("16 <= age <= 17").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_college_age(households, persons):
return persons.local.query("18 <= age <= 24").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_adults(households, persons):
return persons.local.query("25 <= age <= 34").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("land_use")
def household_density(land_use):
return land_use.total_households / land_use.total_acres


@sim.column("land_use")
def employment_density(land_use):
return land_use.total_employment / land_use.total_acres


@sim.column("land_use")
def density_index(land_use):
return (land_use.household_density * land_use.employment_density) / \
(land_use.household_density + land_use.employment_density)


@sim.column("land_use")
def county_name(land_use, settings):
assert "county_map" in settings
inv_map = {v: k for k, v in settings["county_map"].items()}
return land_use.county_id.map(inv_map)
1 change: 1 addition & 0 deletions example/configs/auto_ownership_coeffs.csv
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Description,Expression,cars0,cars1,cars2,cars3,cars42 Adults (age 16+),drivers==2,,0,3.0773,3.1962,2.66163 Adults (age 16+),drivers==3,,0,3.5401,5.5131,5.2084+ Adults (age 16+),drivers>3,,2.0107,6.3662,8.5148,9.5807Persons age 16-17,num_adolescents,,0,-0.881,-1.7313,-1.7313Persons age 18-24,num_college_age,,-0.4087,-1.0095,-1.0107,-1.0107Persons age 35-34,num_young_adults,,0,-0.4849,-0.8596,-0.8596Presence of children age 0-4,num_young_children>0,,0.3669,0.7627,0.7627,0.7627Presence of children age 5-17,(num_children+num_adolescents)>0,,0.0158,0.2936,0.4769,0.4769"Number of workers, capped at 3",@df.workers.clip(upper=3),,0,0.2936,0.6389,0.8797"Piecewise Linear household income, $0-30k","@df.income_in_thousands.clip(0, 30)",,0.0383,0.054,0.0559,0.0619"Piecewise Linear household income, $30-75k","@(df.income_in_thousands-30).clip(0, 45)",,0,0.0083,0.011,0.0147"Piecewise Linear household income, $75k+, capped at $125k","@(df.income_in_thousands-75).clip(0, 50)",,0,0.0083,0.011,0.0147"Density index up to 10, if 0 workers","@(df.workers==0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 0 workers",@(df.workers==0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766"Density index up to 10, if 1+ workers","@(df.workers>0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 1+ workers",@(df.workers>0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766Constants,@1,,1.1865,-1.0846,-3.2502,-5.313San Francisco county,county_name == 'San Francisco',,0.4259,0.4683,0.1458,0.1458Solano county,county_name == 'Solano',,-0.566,-0.4429,-0.2372,-0.2372Napa county,county_name == 'Napa',,-0.566,-0.4429,-0.2372,-0.2372Sonoma county,county_name == 'Sonoma',,-0.566,-0.4429,-0.2372,-0.2372Marin county,county_name == 'Marin',,-0.2434,0,0,0"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 0 workers",(workers==0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.0626,0.0626,0.0626,0.0626"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 1+ workers",(workers>0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.1646,0.1646,0.1646,0.1646"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 0 workers",(workers==0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.3053,-0.3053,-0.3053,-0.3053"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 1+ workers",(workers>0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.5117,-0.5117,-0.5117,-0.5117"Retail accessibility by non-motorized, if 0 workers",(workers==0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Retail accessibility by non-motorized, if 1+ workers",(workers>0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Auto time savings per worker (over walk or transit, max 120) to work",workTourAutoTimeSavings/workers,,0.4707,0.6142,0.5705,0.7693
Expand Down
14 changes: 14 additions & 0 deletions example/configs/settings.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
store: mtc_asim.h5

households_sample_size: 100000

county_map:
San Francisco: 1
San Mateo: 2
Santa Clara: 3
Alameda: 4
Contra Costa: 5
Solano: 6
Napa: 7
Sonoma: 8
Marin: 9
1 change: 1 addition & 0 deletions example/data/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Keep data here
35 changes: 35 additions & 0 deletions example/models.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
import urbansim.sim.simulation as sim
import os
from activitysim import activitysim as asim


@sim.table()
def auto_alts():
return asim.identity_matrix(["cars%d" % i for i in range(5)])


@sim.injectable()
def auto_ownership_spec():
f = os.path.join('configs', "auto_ownership_coeffs.csv")
return asim.read_model_spec(f).head(4*26)


@sim.model()
def auto_ownership_simulate(households,
auto_alts,
auto_ownership_spec,
land_use,
accessibility):

choosers = sim.merge_tables(households.name, tables=[households,
land_use,
accessibility])
alternatives = auto_alts.to_frame()

choices, model_design = \
asim.simple_simulate(choosers, alternatives, auto_ownership_spec)

print "Choices:\n", choices.value_counts()
sim.add_column("households", "auto_ownership", choices)

return model_design
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
example/data/*

.ipynb_checkpoints

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
71 changes: 71 additions & 0 deletions activitysim/activitysim.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
import urbansim.sim.simulation as sim
from urbansim.urbanchoice import interaction, mnl
import pandas as pd
import numpy as np
import os


def random_rows(df, n):
return df.take(np.random.choice(len(df), size=n, replace=False))


def read_model_spec(fname,
description_name="Description",
expression_name="Expression"):
"""
Read in the excel file and reformat for machines

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excel!?! No thanks!

"""
cfg = pd.read_csv(fname)
# don't need description and set the expression to the index
cfg = cfg.drop(description_name, axis=1).set_index(expression_name).stack()
return cfg


def identity_matrix(alt_names):
return pd.DataFrame(np.identity(len(alt_names)),
columns=alt_names,
index=alt_names)


def simple_simulate(choosers, alternatives, spec):
exprs = spec.index
coeffs = spec.values

# merge choosers and alternatives
_, df, _ = interaction.mnl_interaction_dataset(
choosers, alternatives, len(alternatives))

# evaluate the expressions to build the final matrix
vars, names = [], []
for expr in exprs:
if expr[0][0] == "@":
expr = "({}) * df.{}".format(expr[0][1:], expr[1])
try:
s = eval(expr)
except Exception as e:
print "Failed with Python eval:\n%s" % expr
raise e
else:
expr = "({}) * {}".format(*expr)
try:
s = df.eval(expr)
except Exception as e:
print "Failed with DataFrame eval:\n%s" % expr
raise e
names.append(expr)
vars.append(s)
model_design = pd.concat(vars, axis=1)
model_design.columns = names

df = random_rows(model_design, 100000).describe().transpose()
df = df[df["std"] == 0]
if len(df):
print "WARNING: Describe of columns with no variability:\n", df

choices = mnl.mnl_simulate(
model_design.as_matrix(),
coeffs,
numalts=len(alternatives),
returnprobs=False)

return pd.Series(choices, index=choosers.index), model_design
Empty file.
74 changes: 74 additions & 0 deletions activitysim/defaults/datasources.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
import numpy as np
import pandas as pd
import os
import uuid
import yaml
from urbansim.utils import misc
import urbansim.sim.simulation as sim
from .. import activitysim as asim

import warnings

warnings.filterwarnings('ignore', category=pd.io.pytables.PerformanceWarning)
pd.options.mode.chained_assignment = None


@sim.injectable('settings', cache=True)
def settings():
with open(os.path.join(misc.configs_dir(), "settings.yaml")) as f:
settings = yaml.load(f)
# monkey patch on the settings object since it's pretty global
# but will also be available as injectable
sim.settings = settings
return settings


@sim.injectable('run_number')
def run_number():
return misc.get_run_number()


@sim.injectable('uuid', cache=True)
def uuid_hex():
return uuid.uuid4().hex


@sim.injectable('store', cache=True)
def hdfstore(settings):
return pd.HDFStore(
os.path.join(misc.data_dir(), settings["store"]),
mode='r')


@sim.injectable("scenario")
def scenario(settings):
return settings["scenario"]


@sim.table(cache=True)
def land_use(store):
return store["land_use/taz_data"]


@sim.table(cache=True)
def accessibility(store):
df = store["skims/accessibility"]
df.columns = [c.upper() for c in df.columns]
return df


@sim.table(cache=True)
def households(store, settings):
if "households_sample_size" in settings:
return asim.random_rows(store["households"],
settings["households_sample_size"])
return store["households"]


@sim.table(cache=True)
def persons(store):
return store["persons"]


sim.broadcast('land_use', 'households', cast_index=True, onto_on='TAZ')
sim.broadcast('accessibility', 'households', cast_index=True, onto_on='TAZ')
73 changes: 73 additions & 0 deletions activitysim/defaults/variables.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
import urbansim.sim.simulation as sim
from activitysim.defaults import datasources


@sim.column("households")
def income_in_thousands(households):
return households.income / 1000


@sim.column("households")
def drivers(households, persons):
# we assume that everyone 16 and older is a potential driver
return persons.local.query("16 <= age").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_children(households, persons):
return persons.local.query("age <= 4").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_children(households, persons):
return persons.local.query("5 <= age <= 15").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_adolescents(households, persons):
return persons.local.query("16 <= age <= 17").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_college_age(households, persons):
return persons.local.query("18 <= age <= 24").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("households")
def num_young_adults(households, persons):
return persons.local.query("25 <= age <= 34").\
groupby("household_id").size().\
reindex(households.index).fillna(0)


@sim.column("land_use")
def household_density(land_use):
return land_use.total_households / land_use.total_acres


@sim.column("land_use")
def employment_density(land_use):
return land_use.total_employment / land_use.total_acres


@sim.column("land_use")
def density_index(land_use):
return (land_use.household_density * land_use.employment_density) / \
(land_use.household_density + land_use.employment_density)


@sim.column("land_use")
def county_name(land_use, settings):
assert "county_map" in settings
inv_map = {v: k for k, v in settings["county_map"].items()}
return land_use.county_id.map(inv_map)
1 change: 1 addition & 0 deletions example/configs/auto_ownership_coeffs.csv
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Description,Expression,cars0,cars1,cars2,cars3,cars42 Adults (age 16+),drivers==2,,0,3.0773,3.1962,2.66163 Adults (age 16+),drivers==3,,0,3.5401,5.5131,5.2084+ Adults (age 16+),drivers>3,,2.0107,6.3662,8.5148,9.5807Persons age 16-17,num_adolescents,,0,-0.881,-1.7313,-1.7313Persons age 18-24,num_college_age,,-0.4087,-1.0095,-1.0107,-1.0107Persons age 35-34,num_young_adults,,0,-0.4849,-0.8596,-0.8596Presence of children age 0-4,num_young_children>0,,0.3669,0.7627,0.7627,0.7627Presence of children age 5-17,(num_children+num_adolescents)>0,,0.0158,0.2936,0.4769,0.4769"Number of workers, capped at 3",@df.workers.clip(upper=3),,0,0.2936,0.6389,0.8797"Piecewise Linear household income, $0-30k","@df.income_in_thousands.clip(0, 30)",,0.0383,0.054,0.0559,0.0619"Piecewise Linear household income, $30-75k","@(df.income_in_thousands-30).clip(0, 45)",,0,0.0083,0.011,0.0147"Piecewise Linear household income, $75k+, capped at $125k","@(df.income_in_thousands-75).clip(0, 50)",,0,0.0083,0.011,0.0147"Density index up to 10, if 0 workers","@(df.workers==0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 0 workers",@(df.workers==0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766"Density index up to 10, if 1+ workers","@(df.workers>0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654"Density index in excess of 10, if 1+ workers",@(df.workers>0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766Constants,@1,,1.1865,-1.0846,-3.2502,-5.313San Francisco county,county_name == 'San Francisco',,0.4259,0.4683,0.1458,0.1458Solano county,county_name == 'Solano',,-0.566,-0.4429,-0.2372,-0.2372Napa county,county_name == 'Napa',,-0.566,-0.4429,-0.2372,-0.2372Sonoma county,county_name == 'Sonoma',,-0.566,-0.4429,-0.2372,-0.2372Marin county,county_name == 'Marin',,-0.2434,0,0,0"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 0 workers",(workers==0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.0626,0.0626,0.0626,0.0626"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 1+ workers",(workers>0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.1646,0.1646,0.1646,0.1646"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 0 workers",(workers==0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.3053,-0.3053,-0.3053,-0.3053"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 1+ workers",(workers>0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.5117,-0.5117,-0.5117,-0.5117"Retail accessibility by non-motorized, if 0 workers",(workers==0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Retail accessibility by non-motorized, if 1+ workers",(workers>0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03"Auto time savings per worker (over walk or transit, max 120) to work",workTourAutoTimeSavings/workers,,0.4707,0.6142,0.5705,0.7693
Expand Down
14 changes: 14 additions & 0 deletions example/configs/settings.yaml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
store: mtc_asim.h5

households_sample_size: 100000

county_map:
San Francisco: 1
San Mateo: 2
Santa Clara: 3
Alameda: 4
Contra Costa: 5
Solano: 6
Napa: 7
Sonoma: 8
Marin: 9
1 change: 1 addition & 0 deletions example/data/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Keep data here
35 changes: 35 additions & 0 deletions example/models.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
import urbansim.sim.simulation as sim
import os
from activitysim import activitysim as asim


@sim.table()
def auto_alts():
return asim.identity_matrix(["cars%d" % i for i in range(5)])


@sim.injectable()
def auto_ownership_spec():
f = os.path.join('configs', "auto_ownership_coeffs.csv")
return asim.read_model_spec(f).head(4*26)


@sim.model()
def auto_ownership_simulate(households,
auto_alts,
auto_ownership_spec,
land_use,
accessibility):

choosers = sim.merge_tables(households.name, tables=[households,
land_use,
accessibility])
alternatives = auto_alts.to_frame()

choices, model_design = \
asim.simple_simulate(choosers, alternatives, auto_ownership_spec)

print "Choices:\n", choices.value_counts()
sim.add_column("households", "auto_ownership", choices)

return model_design
Loading