Skip to content

Commit 8a311d9

Browse files
committed
comments, a few extra items on the todo list, and a few cosmetic changes to the code
1 parent ddf4b16 commit 8a311d9

File tree

2 files changed

+101
-27
lines changed

2 files changed

+101
-27
lines changed

example/todo.md renamed to example/README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ categories are shared? Income categories are unique?
2020

2121
A few overarching principles
2222

23-
* A little discussion of NOT so object oriented - this is more like a
24-
database - data is in tables, NOT in objects
23+
* A little discussion of "NOT so object oriented" - this is more like a
24+
database - data is in standard tables, NOT in objects
2525

2626
* The implications of this are that most of the core code is pandas and thus
2727
the quality is controlled by the larger community. We are thankful that its
@@ -45,13 +45,19 @@ Case study of `num_under16_not_at_school` to show the inter-dependencies.
4545
A few questions about "best practices"
4646

4747
* What to put into the default data sources and variable specs and what to
48-
put in the examples / client-specific stuff?
48+
put in the example / client-specific stuff?
4949

5050
* Want to split up injectables from variables from tables or all one big file
5151
so it's easier to search?
5252

5353
* How much variable computation to put in excel versus Python
5454

55+
* There were some hard coded limits in the original csv - (area_type < 4 and
56+
distance_to_work < 3) - these are now just left in the csv spec. Why would
57+
this be different than (income_in_thousands > 50)? I've made an effort to
58+
not have such "magic numbers" in Python code. (Elizabeth: MAX_NUM_AUTOS
59+
exists now)
60+
5561
* Want to name or number the person types in the spec files?
5662

5763
* Testing for client-specific code? It's harder because outputs are "data

example/models.py

Lines changed: 92 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,36 @@
88
import pandas as pd
99

1010

11+
# this is the max number of cars allowable in the auto ownership model
1112
MAX_NUM_CARS = 5
1213

1314

15+
"""
16+
This part of this file is currently creating small tables to serve as
17+
alternatives in the various models
18+
"""
19+
20+
1421
@sim.table()
1522
def auto_alts():
1623
return asim.identity_matrix(["cars%d" % i for i in range(MAX_NUM_CARS)])
1724

1825

26+
@sim.table()
27+
def mandatory_tour_frequency_alts():
28+
return asim.identity_matrix(["work1", "work2", "school1", "school2",
29+
"work_and_school"])
30+
31+
# these are the alternatives for the workplace choice
1932
@sim.table()
2033
def zones():
2134
# I grant this is a weird idiom but it helps to name the index
2235
return pd.DataFrame({"TAZ": np.arange(1454)+1}).set_index("TAZ")
2336

2437

25-
@sim.table()
26-
def mandatory_tour_frequency_alts():
27-
return asim.identity_matrix(["work1", "work2", "school1", "school2",
28-
"work_and_school"])
38+
"""
39+
Read in the omx files and create the skim objects
40+
"""
2941

3042

3143
@sim.injectable()
@@ -56,15 +68,22 @@ def sovpm_skim(nonmotskm_omx):
5668
return skim.Skim(nonmotskm_omx['DIST'], offset=-1)
5769

5870

71+
"""
72+
Read in the spec files and reformat as necessary
73+
"""
74+
75+
5976
@sim.injectable()
6077
def auto_ownership_spec():
6178
f = os.path.join('configs', "auto_ownership.csv")
79+
# FIXME should read in all variables and comment out ones not used
6280
return asim.read_model_spec(f).head(4*26)
6381

6482

6583
@sim.injectable()
6684
def workplace_location_spec():
6785
f = os.path.join('configs', "workplace_location.csv")
86+
# FIXME should read in all variables and comment out ones not used
6887
return asim.read_model_spec(f).head(15)
6988

7089

@@ -80,6 +99,11 @@ def workplace_size_spec():
8099
return pd.read_csv(f)
81100

82101

102+
"""
103+
This is a special submodel for the workplace location choice
104+
"""
105+
106+
83107
@sim.table()
84108
def workplace_size_terms(land_use, workplace_size_spec):
85109
"""
@@ -104,6 +128,12 @@ def workplace_size_terms(land_use, workplace_size_spec):
104128
return new_df
105129

106130

131+
"""
132+
Auto ownership is a standard model which predicts how many cars a household
133+
with given characteristics owns
134+
"""
135+
136+
107137
@sim.model()
108138
def auto_ownership_simulate(households,
109139
auto_alts,
@@ -129,6 +159,13 @@ def auto_ownership_simulate(households,
129159
return model_design
130160

131161

162+
"""
163+
The workplace location model predicts the zones in which various people will
164+
work. Interestingly there's not really any supply side to this model - we
165+
assume there are workplaces for the people to work.
166+
"""
167+
168+
132169
@sim.model()
133170
def workplace_location_simulate(persons,
134171
households,
@@ -159,6 +196,12 @@ def workplace_location_simulate(persons,
159196
return model_design
160197

161198

199+
"""
200+
This model predicts the frequency of making mandatory trips (see the
201+
alternatives above) - these trips include work and school in some combination.
202+
"""
203+
204+
162205
@sim.model()
163206
def mandatory_tour_frequency(persons,
164207
households,
@@ -182,6 +225,15 @@ def mandatory_tour_frequency(persons,
182225
return model_design
183226

184227

228+
"""
229+
This section contains computed columns on each table.
230+
"""
231+
232+
"""
233+
for the land use table
234+
"""
235+
236+
185237
@sim.column("land_use")
186238
def total_households(land_use):
187239
return land_use.local.TOTHH
@@ -202,12 +254,17 @@ def county_id(land_use):
202254
return land_use.local.COUNTY
203255

204256

257+
"""
258+
for households
259+
"""
260+
205261
# just a rename / alias
206262
@sim.column("households")
207263
def home_taz(households):
208264
return households.TAZ
209265

210266

267+
# map household type ids to strings
211268
@sim.column("households")
212269
def household_type(households, settings):
213270
return households.HHT.map(settings["household_type_map"])
@@ -235,60 +292,58 @@ def num_under16_not_at_school(persons, households):
235292
reindex(households.index).fillna(0)
236293

237294

238-
# TODO - this is my "placeholder" for the CDAP model ;)
295+
"""
296+
for the persons table
297+
"""
298+
# FIXME - this is my "placeholder" for the CDAP model ;)
239299
@sim.column("persons")
240300
def cdap_activity(persons):
241301
return pd.Series(np.random.randint(3, size=len(persons)),
242302
index=persons.index).map({0: 'M', 1: 'N', 2: 'H'})
243303

244304

245-
@sim.column("persons")
246-
def under16_not_at_school(persons):
247-
return (persons.ptype_cat.isin(["school", "preschool"]) &
248-
persons.cdap_activity.isin(["N", "H"]))
249-
250-
251-
# for now, this really is just a dictionary lookup
305+
# convert employment categories to string descriptors
252306
@sim.column("persons")
253307
def employed_cat(persons, settings):
254308
return persons.pemploy.map(settings["employment_map"])
255309

256310

311+
# convert student categories to string descriptors
257312
@sim.column("persons")
258313
def student_cat(persons, settings):
259314
return persons.pstudent.map(settings["student_map"])
260315

261316

317+
# convert person type categories to string descriptors
262318
@sim.column("persons")
263319
def ptype_cat(persons, settings):
264320
return persons.ptype.map(settings["person_type_map"])
265321

266322

323+
# borrowing these definitions from the original code
267324
@sim.column("persons")
268325
def student_is_employed(persons):
269-
pt = persons.ptype_cat
270-
ec = persons.employed_cat
271-
return (pt.isin(['university', 'driving']) &
272-
ec.isin(['full', 'part']))
326+
return (persons.ptype_cat.isin(['university', 'driving']) &
327+
persons.employed_cat.isin(['full', 'part']))
273328

274329

275330
@sim.column("persons")
276331
def nonstudent_to_school(persons):
277-
pt = persons.ptype_cat
278-
sc = persons.student_cat
279-
return (pt.isin(['full', 'part', 'nonwork', 'retired']) &
280-
sc.isin(['high', 'college']))
332+
return (persons.ptype_cat.isin(['full', 'part', 'nonwork', 'retired']) &
333+
persons.student_cat.isin(['high', 'college']))
281334

282335

283336
@sim.column("persons")
284-
def distance_to_work(persons, distance_skim):
285-
return pd.Series(distance_skim.get(persons.home_taz,
286-
persons.workplace_taz),
287-
index=persons.index)
337+
def under16_not_at_school(persons):
338+
return (persons.ptype_cat.isin(["school", "preschool"]) &
339+
persons.cdap_activity.isin(["N", "H"]))
288340

289341

290342
@sim.column("persons")
291343
def workplace_taz(persons):
344+
# FIXME this is really because we ask for ALL columns in the persons data
345+
# FIXME frame - urbansim actually only asks for the columns that are used by
346+
# FIXME the model specs in play at that time
292347
return pd.Series(1, persons.index)
293348

294349

@@ -304,13 +359,24 @@ def school_taz(persons):
304359
return persons.workplace_taz
305360

306361

362+
# this use the distance skims to compute the raw distance to work from home
363+
@sim.column("persons")
364+
def distance_to_work(persons, distance_skim):
365+
return pd.Series(distance_skim.get(persons.home_taz,
366+
persons.workplace_taz),
367+
index=persons.index)
368+
369+
370+
# same deal but to school
307371
@sim.column("persons")
308372
def distance_to_school(persons, distance_skim):
309373
return pd.Series(distance_skim.get(persons.home_taz,
310374
persons.school_taz),
311375
index=persons.index)
312376

313377

378+
# similar but this adds the am peak travel time to the pm peak travel time in
379+
# the opposite direction (by car)
314380
@sim.column("persons")
315381
def roundtrip_auto_time_to_work(persons, sovam_skim, sovpm_skim):
316382
return pd.Series(sovam_skim.get(persons.home_taz,
@@ -320,6 +386,8 @@ def roundtrip_auto_time_to_work(persons, sovam_skim, sovpm_skim):
320386
index=persons.index)
321387

322388

389+
# this adds the am peak travel time to the md peak travel time in
390+
# the opposite direction (by car), assuming students leave school earlier
323391
@sim.column("persons")
324392
def roundtrip_auto_time_to_school(persons, sovam_skim, sovmd_skim):
325393
return pd.Series(sovam_skim.get(persons.home_taz,

0 commit comments

Comments
 (0)