From bc9a354a1e97f8d25046fa72db74e91e24d0fa29 Mon Sep 17 00:00:00 2001 From: Sarah Zebar Date: Thu, 6 Aug 2026 10:02:44 -0500 Subject: [PATCH 01/13] Refactoring, adding annual VMT tab, adding run types for nonIM/IM by county and just by county --- Database/post_macros/createMOVESinputfile.py | 1247 +++++++++--------- 1 file changed, 632 insertions(+), 615 deletions(-) diff --git a/Database/post_macros/createMOVESinputfile.py b/Database/post_macros/createMOVESinputfile.py index cf54513..64e77e1 100644 --- a/Database/post_macros/createMOVESinputfile.py +++ b/Database/post_macros/createMOVESinputfile.py @@ -1,5 +1,13 @@ + # %% ## ------ CREATE MOVES INPUT FILE ------ ## +# Sarah Zebar 2026/7/23 +# - Refactored code, organized into functions/loops and implemented minor readablity edits +# - Incorporated county data to output Excel Workbooks by IM region/county and just IM region (depending on 'exportAs') +# - Added tab for Annual VMT calculation +# - Incorporated globals from MOVES_constants.py, mainly for the template logic +# +# # Tim O'Leary 2023/10/3 # Script borrows from original SAS script 'create.moves.input.file.imversion.sas', # originally written by Craig Heither. @@ -38,7 +46,6 @@ # 62: Combination Long-haul Truck - 60: Combination Trucks - heavy duty trucks 200+ miles -## ------ IMPORT MODULES ------ ## import os import re @@ -48,677 +55,687 @@ from itertools import product import yaml from pathlib import Path +from MOVES_constants import SOURCE_TYPES, ROAD_TYPES, SPEED_BINS, HOURS + +# Define globals +DB_DIR = Path(__file__).resolve().parents[1] + + +def clean_linkdata(linkdata): + #column data types + for x in ['i_node', 'j_node', 'timeperiod', 'lan', 'vdf', 'zone', 'imarea', 'atype']: + linkdata[x] = linkdata[x].astype(int) + for x in ['len', 'emcap', 'timau', 'ftime', 'avauv', 'avh2v', 'avh3v', 'avbqv', 'avlqv', + 'avmqv', 'avhqv', 'atype', 'busveq']: + linkdata[x] = linkdata[x].astype(float) + + #flag ramp links + linkdata.rename(columns={"tmpl2":"isramp"}, inplace=True) + linkdata.loc[linkdata['vdf'].isin([3,5,8]),'isramp']=1 + + #include only non-attainment zones + na_zones = [ + list(range(1,2305)), + list(range(2309,2314)), + list(range(2317,2320)), + list(range(2326,2927)), + [2941,2943,2944,2949] + ] + + na_zones = [item for sublist in na_zones for item in sublist] + links = linkdata.loc[linkdata['zone'].isin(na_zones)].copy() + + + ## ------ LINK CALCULATIONS ------ ## + + # reset total mtruck/htruck veh equivalents to short-haul veh equivalents + links['m200'] = np.minimum(links['m200'], links['avmqv']) # m200 cannot exceed final MSA balanced volau + links['avmqv'] = np.maximum(links['avmqv']-links['m200'], 0) # now only short haul + links['h200'] = np.minimum(links['h200'], links['avhqv']) # h200 cannot exceed final MSA balanced volau + links['avhqv'] = np.maximum(links['avhqv']-links['h200'], 0) # now only short haul + + #total volume in vehicle equivalents + links.eval('volau = avauv + avh2v + avh3v + avbqv + avlqv + avmqv + m200 + avhqv + h200 + busveq', inplace=True) + + # volume in # vehicles (for VMT/VHT) + links['sov'] = np.maximum(links['avauv'],0) + links['hov2'] = np.maximum(links['avh2v'],0) + links['hov3'] = np.maximum(links['avh3v'],0) + links.eval('auto = sov + hov2 + hov3', inplace=True) + links['bplate'] = np.maximum(links['avbqv'],0) + links['ltruck'] = np.maximum(links['avlqv'],0) + links['mtruck'] = np.maximum(links['avmqv']/2,0) + links.eval('sush = ltruck + mtruck', inplace=True) + links['htruck'] = np.maximum(links['avhqv']/3,0) + links['bus'] = np.maximum(links['busveq']/3,0) + links['mtrucklh'] = np.maximum(links['m200']/2,0) + links['htrucklh'] = np.maximum(links['h200']/3,0) + links.eval('vehicles = auto + bplate + sush + mtrucklh + htruck + htrucklh + bus', inplace=True) + + ##link capacity calculations + + # lines 230-234 + # number of hrs per time period (for capacity calcs) + hours = {1:5, 2:1, 3:2, 4:1, 5:4, 6:2, 7:2, 8:2} ## dict format => {'timeperiod': 'number of hours'} + links['hours'] = links['timeperiod'].map(hours) + links.eval('capacity = lan * emcap * hours', inplace=True) + + # lines 238-243 + # arterial speed adjustment due to LOS C used in VDF (for VHT calculations) + links['fmph'] = np.where((links['ftime'] > 0), (links['len']/(links['ftime']/60)), 20) + links['mph'] = np.where((links['timau'] > 0), (links['len']/(links['timau']/60)), 20) + ## - NOTE: old SAS script used minimum of 0 mph. this has no difference computationally (already adjusted in model) + + # congested speed calc + #links.loc[(links['vdf'] == 1), 'mph'] = links['fmph'] * (1/((np.log(links['fmph']) * 0.249) + 0.153 * (links['volau'] / (links['capacity']*0.75))**3.98)) + links['mph'] = np.where(links['vdf']==1, links['fmph'] * (1/((np.log(links['fmph'])*0.249)+0.153*(links['volau']/(links['capacity']*0.75))**3.98)), links['mph']) + + ## -- Vehicle Miles Traveled and Vehicle Hours Traveled + + #vehicle types to be calculated + vehicle_cols = [ + 'sov', 'hov2', 'hov3', 'auto', 'bplate', 'ltruck', + 'mtruck', 'sush', 'htruck', 'bus', 'mtrucklh', 'htrucklh' + ] + + #vmt + for c in vehicle_cols: + links.eval(f'{c}_vmt = {c} * len', inplace=True) + links.eval('all_vmt = vehicles * len', inplace=True) + + #vht + for c in vehicle_cols: + links[f'{c}_vht'] = np.where((links['mph'] > 0), links[f'{c}_vmt']/links['mph'], 0) + links['all_vht'] = np.where((links['mph'] > 0), links['all_vmt']/links['mph'], 0) + + ## -- Setup MOVES variables + #create avgSpeedBinID by reclassifying mph + def speed_class(mph): + if mph < 2.5: + return 1 + elif mph < 7.5: + return 2 + elif mph < 12.5: + return 3 + elif mph < 17.5: + return 4 + elif mph < 22.5: + return 5 + elif mph < 27.5: + return 6 + elif mph < 32.5: + return 7 + elif mph < 37.5: + return 8 + elif mph < 42.5: + return 9 + elif mph < 47.5: + return 10 + elif mph < 52.5: + return 11 + elif mph < 57.5: + return 12 + elif mph < 62.5: + return 13 + elif mph < 67.5: + return 14 + elif mph < 72.5: + return 15 + else: + return 16 + links['avgSpeedBinID'] = links['mph'].map(speed_class) + + #create facility types + #for vdf = 1 or 6 + links.loc[(links['vdf'].isin([1,6]))&(links['atype']<9), 'roadTypeID']=5 #urban arterial + links.loc[(links['vdf'].isin([1,6]))&~(links['atype']<9), 'roadTypeID']=3 #rural arterial + # for vdf != 1 or 6 + links.loc[~(links['vdf'].isin([1,6]))&(links['atype']<9), 'roadTypeID']=4 #urban freeway + links.loc[~(links['vdf'].isin([1,6]))&~(links['atype']<9), 'roadTypeID']=2 #rural freeway + + return links + +def agg_links(groupcols, links): + """ This aggregates the link data to VMT/VHT by the group cols. Outputs the b dataset that is used by the tabs. + Expands dataset to include all combinations of group cols. + """ + + # Define TBM vehicle types + vtypes = ['auto','bplate','sush','mtrucklh','htrucklh','htruck','bus'] + aggsums = {f"{vtype}_{stat}": "sum" for vtype in vtypes for stat in ["vmt", "vht"]} + + # Aggregating to group cols + b1 = links.groupby(groupcols).agg(aggsums).reset_index() # non-destructive (does not alter links) + + # timeperiod = 1 is 10 hours, others are still fine + b1.loc[b1['timeperiod']==1, 'hours']=10 + + #changing values to be normalized by # hours in timeperiod + for c in list(aggsums.keys()): + b1.eval(f'{c} = {c} / hours', inplace=True) + + + # Define mapping for {time period: hour of day} + times = {1:[21,22,23,24,1,2,3,4,5,6], + 2:[7], + 3:[8,9], + 4:[10], + 5:[11,12,13,14], + 6:[15,16], + 7:[17,18], + 8:[19,20] + } + + # Create duplicates for each hour in time period + b1["hr"] = b1.apply(lambda x: times[x["timeperiod"]], axis=1) + b1 = b1.explode("hr") + + b1['hourDayID'] = b1['hr']*10+5 #'5' indicates a weekday + b1.sort_values(['imarea','roadTypeID','avgSpeedBinID','timeperiod','hourDayID'], inplace=True) + + #### Restructure the data from wide to long (VMT/VHT columns) and add sourceTypeID column for HPMS vehicle codes + mapping = { + "auto": [21, 31, 11], + "bplate": [32], + "sush": [52, 51], + "mtrucklh": [53, 54], + "htruck": [61], + "htrucklh": [62], + "bus": [42, 41, 43] + } + + ids = ['roadTypeID', 'timeperiod', 'avgSpeedBinID', 'hourDayID', 'imarea'] + + # Create subsets for each sourceTypeID and append together + dfs = [] + for vtype, source_type_lst in mapping.items(): + for stype in source_type_lst: + + # Filter for just ids and vehicle type columns, rename, and add source type code + b1_source_type = b1[ids+[col for col in b1.columns if col.startswith(f"{vtype}_")]].copy() + b1_source_type = b1_source_type.rename(columns={f'{vtype}_vmt':'vmt', f'{vtype}_vht':'vht'}) + b1_source_type['sourceTypeID'] = stype + + dfs.append(b1_source_type) + + b_temp = pd.concat(dfs) + + + #### Apply data to template (all ID combinations) + hrday = [(hr*10)+5 for hr in HOURS] + template_values = list(product(SOURCE_TYPES, ROAD_TYPES, hrday, SPEED_BINS, [0,1])) # [0,1] is for IM region + template = pd.DataFrame(template_values, columns=['sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID', 'imarea']) + template.sort_values(['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) + template.reset_index(drop=True, inplace=True) + + # Merge data with template + b = pd.merge(template, b_temp, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID']) + # b.fillna(0, inplace=True) #remove null values + b.drop(columns='timeperiod', inplace=True) + + #remove negative vmt/vht values, if they exist, or fill with zeroes + def replace_neg_w_zero(x): + return max(0,x) + b['vmt'] = b['vmt'].apply(replace_neg_w_zero) + b['vht'] = b['vht'].apply(replace_neg_w_zero) + + return b + +def get_initial_model_output(b, imarea): + """ Just filters to given imarea and excludes non-modeled source types""" + stypes_to_exclude = [11,41,43,51,54] + initial_model_output = b.loc[~(b["sourceTypeID"].isin(stypes_to_exclude)) & (b['imarea']==imarea)].copy(deep=True) + return initial_model_output + +def get_avg_speed_distribution(b,imarea): + + casecols = ['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID'] + + sumvht = b.groupby(casecols).agg({'vht':'sum'}) + sumvht.rename(columns={'vht':'allvht'}, inplace=True) + sumvht.reset_index(inplace=True) + share = pd.merge(b, sumvht, on=casecols, how='inner') + + #bus, pt 1: use roadTypeID 4 to replace missing values for roadTypeID 2 for sourceTypeID 41,42,43 for IM area + fb1_a = share.loc[(share['sourceTypeID']==42)&(share['roadTypeID']==4)&(share['imarea']==1)].copy(deep=True) + fb1_a['roadTypeID'] = 2 + fb1_b = fb1_a.copy() + fb1_b['sourceTypeID'] = 41 + fb1_c = fb1_a.copy() + fb1_c['sourceTypeID'] = 43 + fb1 = pd.concat([fb1_a, fb1_b, fb1_c]) + + #bus, pt2: use sourceTypeID 41,42,43 for IM area to replace missing values for non-IM area + fb2 = pd.concat([fb1, share.loc[(share['sourceTypeID'].isin([41,42,43]))&(share['imarea']==1)].copy(deep=True)]) + fb2['imarea']=0 + + #SU long-haul truck, pt1: use sourceTypeID 52 to replace missing values for sourceTypeID 53,54 for IM area + fb3 = share.loc[(share['sourceTypeID']==52)&(share['imarea']==1)].copy(deep=True) + fb3_a = fb3.copy() + fb3_a['sourceTypeID'] = 53 + fb3_b = fb3.copy() + fb3_b['sourceTypeID'] = 54 + fb3 = pd.concat([fb3_a, fb3_b]) + + #SU long-haul truck, pt2: use sourceTypeID 52,53,54 for IM area to replace missing values for non-IM area + fb4 = pd.concat([fb3, share.loc[(share['sourceTypeID']==52)&(share['imarea']==1)]], ignore_index=True) + fb4['imarea'] = 0 + + #MU long-haul truck pt1: use sourceTypeID 61 to replace missing values for sourceTypeID 62 for IM area + fb5 = share.loc[(share['sourceTypeID']==61)&(share['imarea']==1)].copy(deep=True) + fb5['sourceTypeID'] = 62 + + #MU long-haul truck pt2: use sourceTypeID 61, 62 for IM area to replace missing values for non-IM area + fb6 = pd.concat([fb5, share.loc[(share['sourceTypeID']==61)&(share['imarea']==1)].copy(deep=True)]) + fb6['imarea'] = 0 + + #combining this whole mess together + fallback = pd.concat([fb1, fb2, fb3, fb4, fb5, fb6], ignore_index=True) + fallback.rename(columns={'vht':'vht2', 'allvht':'allvht2'}, inplace=True) + fallback.drop(columns='vmt', inplace=True) + fallback.drop_duplicates(['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) + fallback.sort_values(['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) + + share = pd.merge(share, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID']) + share.loc[(share['allvht']==0)&~(share['allvht2'].isnull()), 'vht'] = share['vht2'] + share.loc[(share['allvht']==0)&~(share['allvht2'].isnull()), 'allvht'] = share['allvht2'] + share.eval('avgSpeedFraction = vht / allvht', inplace=True) + + avg_speed_dist = share[['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID','avgSpeedFraction']] + + return avg_speed_dist.loc[(avg_speed_dist['imarea']==imarea)].drop(columns='imarea') + +def get_road_type_distribution(b, imarea): + roadtype = b.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() + roadtype2 = b.groupby(['imarea','sourceTypeID']).agg({'vmt':'sum'}).rename(columns={'vmt':'sourceVMT'}).reset_index() + + roadtype = pd.merge(roadtype, roadtype2, how='left', on=['imarea','sourceTypeID']) + + #ensure correct datatypes + for f in ['sourceTypeID', 'roadTypeID', 'imarea']: + roadtype[f] = roadtype[f].astype('int') + for f in ['vmt','sourceVMT']: + roadtype[f] = roadtype[f].astype('float') + + #bus part1: use roadTypeID 4 to replace missing values for roadTypeID 2 for sourceTypeID 41,42,43 for IM area + fb1 = roadtype.loc[(roadtype['sourceTypeID']==42)&(roadtype['roadTypeID']==4)&(roadtype['imarea']==1)].copy(deep=True) + fb1_a = fb1.copy() + fb1_a['roadTypeID'] = 2 + fb1_b = fb1_a.copy() + fb1_b['sourceTypeID'] = 41 + fb1_c = fb1_b.copy() + fb1_c['sourceTypeID'] = 43 + fb1 = pd.concat([fb1_a, fb1_b, fb1_c], ignore_index=True) + + #bus part2: use sourcetypeID 41, 42, 43 for IM area to replace missing values for non-IM area + fb2 = pd.concat([fb1, roadtype.loc[(roadtype['sourceTypeID'].isin([41,42,43]))&(roadtype['imarea']==1)].copy(deep=True)], ignore_index=True) + fb2['imarea'] = 0 + + #SU long-haul truck part1: use sourcetypeID 52 to replace missing values for sourceTypeID 53,54 for IM area + fb3 = roadtype.loc[(roadtype['sourceTypeID']==52)&(roadtype['imarea']==1)].copy(deep=True) + fb3_a = fb3.copy() + fb3_a['sourceTypeID'] = 53 + fb3_b = fb3_a.copy() + fb3_b['sourceTypeID'] = 54 + fb3 = pd.concat([fb3_a, fb3_b], ignore_index=True) + + #SU long-hault truck part2: use sourcetypeID 52. 53. 54 for IM area to replace missing values for non-IM area + fb4 = pd.concat([fb3, roadtype.loc[(roadtype['sourceTypeID']==52)&roadtype['imarea']==1].copy(deep=True)]) + fb4['imarea']=0 + + #MU long-haul truck part1: use sourceTypeID 61 to replace missing values for sourcetypeID 62 for IM area + fb5 = roadtype.loc[(roadtype['sourceTypeID']==61)&(roadtype['imarea']==1)].copy(deep=True) + fb5['sourceTypeID'] = 62 + + #MU long-haul truck part2: use sourceTypeID 61,62 for IM area to replace missing values for non-IM area + fb6 = pd.concat([fb5, roadtype.loc[(roadtype['sourceTypeID']==61)&(roadtype['imarea']==1)].copy(deep=True)]) + fb6['imarea'] = 0 + + fallback = pd.concat([fb1,fb2,fb3,fb4,fb5,fb6]).rename(columns={'vmt':'vmt2', 'sourceVMT':'sourceVMT2'}).sort_values(['imarea','sourceTypeID','roadTypeID']).drop_duplicates(['imarea','sourceTypeID','roadTypeID']) + + roadtype = pd.merge(roadtype, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID']) + # roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), ['vmt', 'sourceVMT']] = roadtype[['vmt2', 'sourceVMT2']] + roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), 'vmt'] = roadtype['vmt2'] + roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), 'sourceVMT'] = roadtype['sourceVMT2'] + + #prevent division by zero + def abovezero(x): + return np.maximum(x,0.000001) + roadtype['sourceVMT'] = roadtype['sourceVMT'].apply(abovezero) + + roadtype.eval('roadTypeVMTFraction = vmt / sourceVMT', inplace=True) + roadtype['roadTypeVMTFraction'] = roadtype['roadTypeVMTFraction'].round(6) + + road_type_distribution = roadtype.loc[roadtype['imarea']==imarea,['sourceTypeID','roadTypeID','roadTypeVMTFraction']].copy() + + return road_type_distribution + +def get_ramp_fraction(links, imarea): + + rmp = links.loc[links['roadTypeID'].isin([2,4])].copy(deep=True) + rmp.eval('fwyvht = auto_vht + bplate_vht + sush_vht + mtrucklh_vht + htruck_vht + htrucklh_vht + bus_vht', inplace=True) + rmp.eval('fwyvmt = auto_vmt + bplate_vmt + sush_vmt + mtrucklh_vmt + htruck_vmt + htrucklh_vmt + bus_vmt', inplace=True) + rmp['rampvht'] = np.where(rmp['isramp']==1, rmp['fwyvht'], 0) + rmp['rampvmt'] = np.where(rmp['isramp']==1, rmp['fwyvmt'], 0) + + ramp = rmp.groupby(['imarea','roadTypeID']).agg({'fwyvht':'sum','rampvht':'sum','fwyvmt':'sum','rampvmt':'sum'}).reset_index() + ramp.eval('rampFraction = rampvht/fwyvht', inplace=True) + ramp['rampFraction'] = ramp['rampFraction'].round(6) + ramp.eval('vmtFraction = rampvmt/fwyvmt', inplace=True) + ramp['vmtFraction'] = ramp['vmtFraction'].round(6) + + # Output ramp fraction for im area + ramp_fraction = ramp.loc[ramp['imarea']==imarea,['roadTypeID','rampFraction']] + return ramp_fraction + +def get_hourly_vmt_fraction(b, imarea): + + # Apply data to template (all ID combinations) + roads = [1] + ROAD_TYPES # add off-network roads just for this function + dayID = [5] + template_values = list(product(SOURCE_TYPES, roads, HOURS, dayID, [0,1])) + template = pd.DataFrame(template_values, columns=['sourceTypeID', 'roadTypeID', 'hourID', 'dayID', 'imarea']) + template.sort_values(['imarea', 'sourceTypeID', 'roadTypeID', 'hourID'], inplace=True) + vmt = b.copy() + vmt['hourID'] = (vmt['hourDayID'] - 5)/10 + + hourvmt = vmt.groupby(['imarea','sourceTypeID','roadTypeID','hourID']).agg({'vmt':'sum'}).reset_index() + sumvmt = hourvmt.groupby(['imarea', 'sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() + sumvmt.rename(columns={'vmt':'allvmt'},inplace=True) -db_dir = Path(__file__).resolve().parents[1] -## ------ PARAMETERS ------ ## -#get model version and scenario year - for output filenames -with open(db_dir.joinpath('batch_file.yaml')) as f: - config = yaml.safe_load(f) -model = config['model_version'] # e.g., 'c23q4' -scenyear = config['scenario_code'] # e.g., '400' - -#bring in punch moves link data -linkdata = pd.read_csv(db_dir.joinpath('data', 'punchlink.csv')) - -#output excel worksheets -excel_file_IM = db_dir.joinpath('data', f'MOVES_{model}_scen{scenyear}_IM.xlsx') -excel_file_noIM = db_dir.joinpath('data', f'MOVES_{model}_scen{scenyear}_nonIM.xlsx') - -##create excel workbook to write worksheets to -xlsx_IM = pd.ExcelWriter(excel_file_IM) -xlsx_noIM = pd.ExcelWriter(excel_file_noIM) - - -## ------ CLEAN-UP DATASET ------ ## - -#clean up column names -collist = linkdata.columns.tolist() -cols_to_rename = [a for a in collist if a.startswith('@')] -coldict = dict([[a, a[1:]] for a in cols_to_rename]) -coldict['tmpl2'] = 'isramp' -linkdata.rename(columns=coldict, inplace=True) - -#column data types -for x in ['i_node', 'j_node', 'timeperiod', 'lan', 'vdf', 'zone', 'imarea', 'atype']: - linkdata[x] = linkdata[x].astype(int) -for x in ['len', 'emcap', 'timau', 'ftime', 'avauv', 'avh2v', 'avh3v', 'avbqv', 'avlqv', - 'avmqv', 'avhqv', 'atype', 'busveq']: - linkdata[x] = linkdata[x].astype(float) - -#flag ramp links -linkdata.loc[linkdata['vdf'].isin([3,5,8]),'isramp']=1 - -#include only non-attainment zones -na_zones = [ - list(range(1,2305)), - list(range(2309,2314)), - list(range(2317,2320)), - list(range(2326,2927)), - [2941,2943,2944,2949] -] - -na_zones = [item for sublist in na_zones for item in sublist] -links = linkdata.loc[linkdata['zone'].isin(na_zones)].copy() - - -## ------ LINK CALCULATIONS ------ ## - -# reset total mtruck/htruck veh equivalents to short-haul veh equivalents -links['m200'] = np.minimum(links['m200'], links['avmqv']) # m200 cannot exceed final MSA balanced volau -links['avmqv'] = np.maximum(links['avmqv']-links['m200'], 0) # now only short haul -links['h200'] = np.minimum(links['h200'], links['avhqv']) # h200 cannot exceed final MSA balanced volau -links['avhqv'] = np.maximum(links['avhqv']-links['h200'], 0) # now only short haul - -#total volume in vehicle equivalents -links.eval('volau = avauv + avh2v + avh3v + avbqv + avlqv + avmqv + m200 + avhqv + h200 + busveq', inplace=True) - -# volume in # vehicles (for VMT/VHT) -links['sov'] = np.maximum(links['avauv'],0) -links['hov2'] = np.maximum(links['avh2v'],0) -links['hov3'] = np.maximum(links['avh3v'],0) -links.eval('auto = sov + hov2 + hov3', inplace=True) -links['bplate'] = np.maximum(links['avbqv'],0) -links['ltruck'] = np.maximum(links['avlqv'],0) -links['mtruck'] = np.maximum(links['avmqv']/2,0) -links.eval('sush = ltruck + mtruck', inplace=True) -links['htruck'] = np.maximum(links['avhqv']/3,0) -links['bus'] = np.maximum(links['busveq']/3,0) -links['mtrucklh'] = np.maximum(links['m200']/2,0) -links['htrucklh'] = np.maximum(links['h200']/3,0) -links.eval('vehicles = auto + bplate + sush + mtrucklh + htruck + htrucklh + bus', inplace=True) - -##link capacity calculations - -# lines 230-234 -# number of hrs per time period (for capacity calcs) -hours = {1:5, 2:1, 3:2, 4:1, 5:4, 6:2, 7:2, 8:2} ## dict format => {'timeperiod': 'number of hours'} -links['hours'] = links['timeperiod'].map(hours) -links.eval('capacity = lan * emcap * hours', inplace=True) - -# lines 238-243 -# arterial speed adjustment due to LOS C used in VDF (for VHT calculations) -links['fmph'] = np.where((links['ftime'] > 0), (links['len']/(links['ftime']/60)), 20) -links['mph'] = np.where((links['timau'] > 0), (links['len']/(links['timau']/60)), 20) -## - NOTE: old SAS script used minimum of 0 mph. this has no difference computationally (already adjusted in model) - -# congested speed calc -#links.loc[(links['vdf'] == 1), 'mph'] = links['fmph'] * (1/((np.log(links['fmph']) * 0.249) + 0.153 * (links['volau'] / (links['capacity']*0.75))**3.98)) -links['mph'] = np.where(links['vdf']==1, links['fmph'] * (1/((np.log(links['fmph'])*0.249)+0.153*(links['volau']/(links['capacity']*0.75))**3.98)), links['mph']) - -## -- Vehicle Miles Traveled and Vehicle Hours Traveled - -#vehicle types to be calculated -vehicle_cols = [ - 'sov', 'hov2', 'hov3', 'auto', 'bplate', 'ltruck', - 'mtruck', 'sush', 'htruck', 'bus', 'mtrucklh', 'htrucklh' -] - -#vmt -for c in vehicle_cols: - links.eval(f'{c}_vmt = {c} * len', inplace=True) -links.eval('all_vmt = vehicles * len', inplace=True) - -#vht -for c in vehicle_cols: - links[f'{c}_vht'] = np.where((links['mph'] > 0), links[f'{c}_vmt']/links['mph'], 0) -links['all_vht'] = np.where((links['mph'] > 0), links['all_vmt']/links['mph'], 0) - - -## -- Setup MOVES variables -#create avgSpeedBinID by reclassifying mph -def speed_class(mph): - if mph < 2.5: - return 1 - elif mph < 7.5: - return 2 - elif mph < 12.5: - return 3 - elif mph < 17.5: - return 4 - elif mph < 22.5: - return 5 - elif mph < 27.5: - return 6 - elif mph < 32.5: - return 7 - elif mph < 37.5: - return 8 - elif mph < 42.5: - return 9 - elif mph < 47.5: - return 10 - elif mph < 52.5: - return 11 - elif mph < 57.5: - return 12 - elif mph < 62.5: - return 13 - elif mph < 67.5: - return 14 - elif mph < 72.5: - return 15 - else: - return 16 -links['avgSpeedBinID'] = links['mph'].map(speed_class) - -#create facility types -#for vdf = 1 or 6 -links.loc[(links['vdf'].isin([1,6]))&(links['atype']<9), 'roadTypeID']=5 #urban arterial -links.loc[(links['vdf'].isin([1,6]))&~(links['atype']<9), 'roadTypeID']=3 #rural arterial -# for vdf != 1 or 6 -links.loc[~(links['vdf'].isin([1,6]))&(links['atype']<9), 'roadTypeID']=4 #urban freeway -links.loc[~(links['vdf'].isin([1,6]))&~(links['atype']<9), 'roadTypeID']=2 #rural freeway - - -## ------ Create MOVES 'initial_model_output' Table ------ ## - -#line 305 -#grab columns we want to aggregate -b1_columns = [[f'{c}_vmt', f'{c}_vht'] for c in ['auto','bplate','sush','mtrucklh','htrucklh','htruck','bus']] -b1_columns = [a for sublist in b1_columns for a in sublist] -aggsums = {} -for a in b1_columns: - aggsums[a] = 'sum' - -groupcols = ['imarea', 'roadTypeID', 'timeperiod', 'avgSpeedBinID', 'hours'] - -b1 = links.groupby(groupcols).agg(aggsums).reset_index() - -# #vmt verification -# #line 308-313 - -# print('Totals Before') -# links.groupby(['imarea']).agg(aggsums) -#disaggregate to hourly data -#lines 316-324 - -#timeperiod = 1 is 10 hours, others are still fine -b1.loc[b1['timeperiod']==1, 'hours']=10 - -#changing values to be normalized by # hours in timeperiod -for c in b1_columns: - b1.eval(f'{c} = {c} / hours', inplace=True) - - -#we need to duplicate each row to include each hour-of-day value -#will do this by appending rows to a new dataframe using some dictionaries - -#this sets up hour of day, will call this below -times = {1:[21,22,23,24,1,2,3,4,5,6], - 2:[7], - 3:[8,9], - 4:[10], - 5:[11,12,13,14], - 6:[15,16], - 7:[17,18], - 8:[19,20] - } - -#create new df of each timeperiod -b1_dfs = [] -for tp in times: - b_tp = b1.loc[b1['timeperiod']==tp].copy(deep=True) - #create new df for each hour-of-day within each timeperiod, then append to b1_dfs as an item in list - for hour in times[tp]: - bb = b_tp.copy(deep=True) - bb['hr'] = hour - b1_dfs.append(bb) - -#concatenate all timeperiod dataframes in b1_dfs into one df -b1 = pd.concat(b1_dfs, ignore_index=True) -b1['hourDayID'] = b1['hr']*10+5 #'5' indicates a weekday' -b1.sort_values(['imarea','roadTypeID','avgSpeedBinID','timeperiod','hourDayID'], inplace=True) - -#need to make separate rows for vmt/vht of each vehicle class -#will do this by creating a separate df for each vehicle class, then recombine - -common_columns = ['roadTypeID', 'timeperiod', 'avgSpeedBinID', 'hourDayID', 'imarea'] -#passenger car - 21 -b2 = b1[common_columns + ['auto_vmt', 'auto_vht']].copy().rename(columns={'auto_vmt':'vmt', 'auto_vht':'vht'}) -b2['sourceTypeID'] = 21 -#passenger truck - 31 -b3 = b1[common_columns + ['auto_vmt', 'auto_vht']].copy().rename(columns={'auto_vmt':'vmt', 'auto_vht':'vht'}) -b3['sourceTypeID'] = 31 -#light commercial truck - 32 -b4 = b1[common_columns + ['bplate_vmt', 'bplate_vht']].copy().rename(columns={'bplate_vmt':'vmt', 'bplate_vht':'vht'}) -b4['sourceTypeID'] = 32 -#SU short haul truck - 52 -b5 = b1[common_columns + ['sush_vmt', 'sush_vht']].copy().rename(columns={'sush_vmt':'vmt', 'sush_vht':'vht'}) -b5['sourceTypeID'] = 52 -#SU long-haul truck - 53 -b6 = b1[common_columns + ['mtrucklh_vmt', 'mtrucklh_vht']].copy().rename(columns={'mtrucklh_vmt':'vmt', 'mtrucklh_vht':'vht'}) -b6['sourceTypeID'] = 53 -#MU short haul - 61 -b7 = b1[common_columns + ['htruck_vmt', 'htruck_vht']].copy().rename(columns={'htruck_vmt':'vmt', 'htruck_vht':'vht'}) -b7['sourceTypeID'] = 61 -#MU long haul - 62 -b8 = b1[common_columns + ['htrucklh_vmt', 'htrucklh_vht']].copy().rename(columns={'htrucklh_vmt':'vmt', 'htrucklh_vht':'vht'}) -b8['sourceTypeID'] = 62 -#transit bus - 42 -b9 = b1[common_columns + ['bus_vmt', 'bus_vht']].copy().rename(columns={'bus_vmt':'vmt', 'bus_vht':'vht'}) -b9['sourceTypeID'] = 42 -#intercity bus - 41 -- apply transit bus distribution to intercity bus -b10 = b9.copy() -b10['sourceTypeID'] = 41 -#school bus - 43 -- apply transit bus distribution to school bus -b11 = b9.copy() -b11['sourceTypeID'] = 43 -#motorcycle - 11 -- apply auto distribution to motorcycles -b12 = b2.copy() -b12['sourceTypeID'] = 11 -#refuse trucks - 51 -- apply single unit short-haul distribution to refuse trucks -b13 = b5.copy() -b13['sourceTypeID'] = 51 -#motor homes - 54 -- apply single unit long-haul distribution to motor homes -b14 = b6.copy() -b14['sourceTypeID'] = 54 - -b = pd.concat([b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14], ignore_index=True) -b.sort_values(['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) - - -#need to apply values onto a template that contains all possible combinations -#create template with all combinations -#line 369-374 - -#get unique values for each of the categories: sourceTypeID, roadTypeID, hourDayID, avgSpeedBinID, and imarea -veh = b['sourceTypeID'].unique().tolist() -road = b['roadTypeID'].unique().tolist() -hrday = b['hourDayID'].unique().tolist() -speed = b['avgSpeedBinID'].unique().tolist() -imcat = b['imarea'].unique().tolist() - -#create cartesian product of the lists listed above -template_values = list(product(veh, road, hrday, speed, imcat)) -template = pd.DataFrame(template_values, columns=['sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID', 'imarea']) -template.sort_values(['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) -template.reset_index(drop=True, inplace=True) - -#merge data with template -b = pd.merge(template, b, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID']) -# b.fillna(0, inplace=True) #remove null values -b.drop(columns='timeperiod', inplace=True) - -#remove negative vmt/vht values, if they exist, or fill with zeroes -def replace_neg_w_zero(x): - return max(0,x) -b['vmt'] = b['vmt'].apply(replace_neg_w_zero) -b['vht'] = b['vht'].apply(replace_neg_w_zero) - - -##################################### -## -- INIITIAL MODEL OUTPUT TAB -- ## -##################################### -#line 462-473 -#only include source types from actual modeled vehicle trips -- for QC - -#initial_model_output tab in excel file -#imarea -outIM_initialmodeloutput = b.loc[~(b['sourceTypeID'].astype('int').isin([11,41,43,51,54]))&(b['imarea']==1)].copy(deep=True) -outIM_initialmodeloutput.to_excel(xlsx_IM, sheet_name='initial_model_output', index=False) - -#non-imarea -outnoIM_initialmodeloutput = b.loc[~(b['sourceTypeID'].astype('int').isin([11,41,43,51,54]))&(b['imarea']==0)].copy(deep=True) -outnoIM_initialmodeloutput.to_excel(xlsx_noIM, sheet_name='initial_model_output', index=False) - - -################################## -## -- SPEED DISTRIBUTION TAB -- ## -################################## - -#lines 479-482 -#CALCULATE VHT SHARE BY SOURCETYPEID-ROADTYPEID-HOURDAYID -#then join back to table - -casecols = ['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID'] - -sumvht = b.groupby(casecols).agg({'vht':'sum'}) -sumvht.rename(columns={'vht':'allvht'}, inplace=True) -sumvht.reset_index(inplace=True) -share = pd.merge(b, sumvht, on=casecols, how='inner') - - -#lines 485-512 -# -- USE SURROGATES TO REPLACE MISSING VALUES -- - -#bus, pt 1: use roadTypeID 4 to replace missing values for roadTypeID 2 for sourceTypeID 41,42,43 for IM area -fb1_a = share.loc[(share['sourceTypeID']==42)&(share['roadTypeID']==4)&(share['imarea']==1)].copy(deep=True) -fb1_a['roadTypeID'] = 2 -fb1_b = fb1_a.copy() -fb1_b['sourceTypeID'] = 41 -fb1_c = fb1_a.copy() -fb1_c['sourceTypeID'] = 43 -fb1 = pd.concat([fb1_a, fb1_b, fb1_c]) - -#bus, pt2: use sourceTypeID 41,42,43 for IM area to replace missing values for non-IM area -fb2 = pd.concat([fb1, share.loc[(share['sourceTypeID'].isin([41,42,43]))&(share['imarea']==1)].copy(deep=True)]) -fb2['imarea']=0 - -#SU long-haul truck, pt1: use sourceTypeID 52 to replace missing values for sourceTypeID 53,54 for IM area -fb3 = share.loc[(share['sourceTypeID']==52)&(share['imarea']==1)].copy(deep=True) -fb3_a = fb3.copy() -fb3_a['sourceTypeID'] = 53 -fb3_b = fb3.copy() -fb3_b['sourceTypeID'] = 54 -fb3 = pd.concat([fb3_a, fb3_b]) - -#SU long-haul truck, pt2: use sourceTypeID 52,53,54 for IM area to replace missing values for non-IM area -fb4 = pd.concat([fb3, share.loc[(share['sourceTypeID']==52)&(share['imarea']==1)]], ignore_index=True) -fb4['imarea'] = 0 - -#MU long-haul truck pt1: use sourceTypeID 61 to replace missing values for sourceTypeID 62 for IM area -fb5 = share.loc[(share['sourceTypeID']==61)&(share['imarea']==1)].copy(deep=True) -fb5['sourceTypeID'] = 62 - -#MU long-haul truck pt2: use sourceTypeID 61, 62 for IM area to replace missing values for non-IM area -fb6 = pd.concat([fb5, share.loc[(share['sourceTypeID']==61)&(share['imarea']==1)].copy(deep=True)]) -fb6['imarea'] = 0 - -#combining this whole mess together -fallback = pd.concat([fb1, fb2, fb3, fb4, fb5, fb6], ignore_index=True) -fallback.rename(columns={'vht':'vht2', 'allvht':'allvht2'}, inplace=True) -fallback.drop(columns='vmt', inplace=True) -fallback.drop_duplicates(['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) -fallback.sort_values(['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) - -share = pd.merge(share, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID']) -share.loc[(share['allvht']==0)&~(share['allvht2'].isnull()), 'vht'] = share['vht2'] -share.loc[(share['allvht']==0)&~(share['allvht2'].isnull()), 'allvht'] = share['allvht2'] -share.eval('avgSpeedFraction = vht / allvht', inplace=True) - - -## -- AvgSpeedDistribution excel sheet -- ## - -avg_speed_dist = share[['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID','avgSpeedFraction']] - -outIM_avgspeeddistribution = avg_speed_dist.loc[(avg_speed_dist['imarea']==1)].drop(columns='imarea') -outIM_avgspeeddistribution.to_excel(xlsx_IM, sheet_name='AvgSpeedDistribution', index=False) - -outnoIM_avgspeeddistribution = avg_speed_dist.loc[(avg_speed_dist['imarea']==0)].drop(columns='imarea') -outnoIM_avgspeeddistribution.to_excel(xlsx_noIM, sheet_name='AvgSpeedDistribution', index=False) - - -###################################### -## -- road type distribution tab -- ## -###################################### - -roadtype = b.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() -roadtype2 = b.groupby(['imarea','sourceTypeID']).agg({'vmt':'sum'}).rename(columns={'vmt':'sourceVMT'}).reset_index() - -roadtype = pd.merge(roadtype, roadtype2, how='left', on=['imarea','sourceTypeID']) - -#ensure correct datatypes -for f in ['sourceTypeID', 'roadTypeID', 'imarea']: - roadtype[f] = roadtype[f].astype('int') -for f in ['vmt','sourceVMT']: - roadtype[f] = roadtype[f].astype('float') - - -# -- use surrogates to replace missing values if necessary - -#bus part1: use roadTypeID 4 to replace missing values for roadTypeID 2 for sourceTypeID 41,42,43 for IM area -fb1 = roadtype.loc[(roadtype['sourceTypeID']==42)&(roadtype['roadTypeID']==4)&(roadtype['imarea']==1)].copy(deep=True) -fb1_a = fb1.copy() -fb1_a['roadTypeID'] = 2 -fb1_b = fb1_a.copy() -fb1_b['sourceTypeID'] = 41 -fb1_c = fb1_b.copy() -fb1_c['sourceTypeID'] = 43 -fb1 = pd.concat([fb1_a, fb1_b, fb1_c], ignore_index=True) - -#bus part2: use sourcetypeID 41, 42, 43 for IM area to replace missing values for non-IM area -fb2 = pd.concat([fb1, roadtype.loc[(roadtype['sourceTypeID'].isin([41,42,43]))&(roadtype['imarea']==1)].copy(deep=True)], ignore_index=True) -fb2['imarea'] = 0 - -#SU long-haul truck part1: use sourcetypeID 52 to replace missing values for sourceTypeID 53,54 for IM area -fb3 = roadtype.loc[(roadtype['sourceTypeID']==52)&(roadtype['imarea']==1)].copy(deep=True) -fb3_a = fb3.copy() -fb3_a['sourceTypeID'] = 53 -fb3_b = fb3_a.copy() -fb3_b['sourceTypeID'] = 54 -fb3 = pd.concat([fb3_a, fb3_b], ignore_index=True) - -#SU long-hault truck part2: use sourcetypeID 52. 53. 54 for IM area to replace missing values for non-IM area -fb4 = pd.concat([fb3, roadtype.loc[(roadtype['sourceTypeID']==52)&roadtype['imarea']==1].copy(deep=True)]) -fb4['imarea']=0 - -#MU long-haul truck part1: use sourceTypeID 61 to replace missing values for sourcetypeID 62 for IM area -fb5 = roadtype.loc[(roadtype['sourceTypeID']==61)&(roadtype['imarea']==1)].copy(deep=True) -fb5['sourceTypeID'] = 62 - -#MU long-haul truck part2: use sourceTypeID 61,62 for IM area to replace missing values for non-IM area -fb6 = pd.concat([fb5, roadtype.loc[(roadtype['sourceTypeID']==61)&(roadtype['imarea']==1)].copy(deep=True)]) -fb6['imarea'] = 0 - -fallback = pd.concat([fb1,fb2,fb3,fb4,fb5,fb6]).rename(columns={'vmt':'vmt2', 'sourceVMT':'sourceVMT2'}).sort_values(['imarea','sourceTypeID','roadTypeID']).drop_duplicates(['imarea','sourceTypeID','roadTypeID']) - -roadtype = pd.merge(roadtype, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID']) -# roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), ['vmt', 'sourceVMT']] = roadtype[['vmt2', 'sourceVMT2']] -roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), 'vmt'] = roadtype['vmt2'] -roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), 'sourceVMT'] = roadtype['sourceVMT2'] - -#prevent division by zero -def abovezero(x): - return np.maximum(x,0.000001) -roadtype['sourceVMT'] = roadtype['sourceVMT'].apply(abovezero) - -roadtype.eval('roadTypeVMTFraction = vmt / sourceVMT', inplace=True) -roadtype['roadTypeVMTFraction'] = roadtype['roadTypeVMTFraction'].round(6) - - -## -- RoadTypeDistribution excel sheet -- ## -outIM_roadtypedistribution = roadtype.loc[roadtype['imarea']==1,['sourceTypeID','roadTypeID','roadTypeVMTFraction']].copy() -outIM_roadtypedistribution.to_excel(xlsx_IM, sheet_name='RoadTypeDistribution', index=False) - -outnoIM_roadtypedistribution = roadtype.loc[(roadtype['imarea']==0),['sourceTypeID', 'roadTypeID', 'roadTypeVMTFraction']].copy() -outnoIM_roadtypedistribution.to_excel(xlsx_noIM, sheet_name='RoadTypeDistribution', index=False) - - -############################# -## -- Ramp Fraction Tab -- ## -############################# - -rmp = links.loc[links['roadTypeID'].isin([2,4])].copy(deep=True) -rmp.eval('fwyvht = auto_vht + bplate_vht + sush_vht + mtrucklh_vht + htruck_vht + htrucklh_vht + bus_vht', inplace=True) -rmp.eval('fwyvmt = auto_vmt + bplate_vmt + sush_vmt + mtrucklh_vmt + htruck_vmt + htrucklh_vmt + bus_vmt', inplace=True) -rmp['rampvht'] = np.where(rmp['isramp']==1, rmp['fwyvht'], 0) -rmp['rampvmt'] = np.where(rmp['isramp']==1, rmp['fwyvmt'], 0) + vmtshare = pd.merge(hourvmt, sumvmt, how='left', on=['imarea','sourceTypeID','roadTypeID']) + vmtshare.sort_values(['imarea','sourceTypeID','roadTypeID','hourID'],inplace=True) -ramp = rmp.groupby(['imarea','roadTypeID']).agg({'fwyvht':'sum','rampvht':'sum','fwyvmt':'sum','rampvmt':'sum'}).reset_index() -ramp.eval('rampFraction = rampvht/fwyvht', inplace=True) -ramp['rampFraction'] = ramp['rampFraction'].round(6) -ramp.eval('vmtFraction = rampvmt/fwyvmt', inplace=True) -ramp['vmtFraction'] = ramp['vmtFraction'].round(6) + ## -- use surrogates to replace missing values, if necessary + #bus part 1: use sourcetypeid 42 to replace missing values for sourceTypeID 41,43 for IM area + fb1 = vmtshare.loc[(vmtshare['sourceTypeID']==42)&(vmtshare['imarea']==1)].copy() + fb1_a = fb1.copy() + fb1_a['sourceTypeID'] = 41 + fb1_b = fb1.copy() + fb1_b['sourceTypeID'] = 43 + fb1 = pd.concat([fb1_a, fb1_b], ignore_index=True) -#ramp fraction to excel -outIM_rampfraction = ramp.loc[ramp['imarea']==1,['roadTypeID','rampFraction']] -outIM_rampfraction.to_excel(xlsx_IM, sheet_name='RampFraction', index=False) + #bus part2: use sourcetypeID 41,42,43 for IM area to replace missing values for non-IM area + fb2 = pd.concat([fb1, vmtshare.loc[(vmtshare['sourceTypeID'].isin([41,42,43]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()], ignore_index=True) + fb2['imarea'] = 0 -outnoIM_rampfraction = ramp.loc[(ramp['imarea']==0),['roadTypeID','rampFraction']] -outnoIM_rampfraction.to_excel(xlsx_noIM, sheet_name='RampFraction', index=False) + #su long-haul truck part1: use sourceTypeID 52 to replace missing values for sourcetypeID 53,54 for im area + fb3 = vmtshare.loc[(vmtshare['sourceTypeID']==52)&(vmtshare['imarea']==1)].copy() + fb3_a = fb3.copy() + fb3_a['sourceTypeID'] = 53 + fb3_b = fb3.copy() + fb3_b['sourceTypeID'] = 54 + fb3 = pd.concat([fb3_a, fb3_b], ignore_index=True) + #su long haul truck part2: use sourceTypeID 52,53,54 for IM area to replace missing values for non-IM area + fb4 = pd.concat([fb3, vmtshare.loc[(vmtshare['sourceTypeID'].isin([52,53,54]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()], ignore_index=True) + fb4['imarea'] = 0 -################################### -## -- Hourly VMT Fraction Tab -- ## -################################### + #mu long-haul truck part 1: use sourcetypeID 61 to replace missing values for sourcetypeid 62 for im area + fb5 = vmtshare.loc[(vmtshare['sourceTypeID']==61)&(vmtshare['imarea']==1)].copy() + fb5['sourceTypeID'] = 62 -#create template of all combos -- sourceTypeID, roadTypeID, dayID, hourID, imarea - #the following exist further up the script: - # veh = b['sourceTypeID'].unique().tolist() -road = b['roadTypeID'].unique().tolist() - # hrday = b['hourDayID'].unique().tolist() - # imcat = b['imarea'].unique().tolist() + #mu long-haul truck part2: use sourcetypeid 61,62 for IM area to replace missing values for non-IM area + fb6 = pd.concat([fb5, vmtshare.loc[(vmtshare['sourceTypeID'].isin([61,62]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()],ignore_index=True) + fb6['imarea'] = 0 -#add roadtype 1: -road.append(1) + fallback = pd.concat([fb1, fb2, fb3, fb4, fb5, fb6], ignore_index=True).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) + fallback.rename(columns={'vmt':'vmt2', 'allvmt':'allvmt2'},inplace=True) + fallback.drop_duplicates(subset=['imarea','sourceTypeID','roadTypeID','hourID'], inplace=True) -#create separate hrID and dayID -hourID = [] -for item in hrday: - hourID.append((item - 5)/10) -dayID = [5] + vmtshare = pd.merge(vmtshare, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID', 'hourID']) -#cartesian product of the lists listed above -template_values = list(product(veh, road, hourID, dayID, imcat)) -template2 = pd.DataFrame(template_values, columns=['sourceTypeID', 'roadTypeID', 'hourID', 'dayID', 'imarea']) -template2.sort_values(['imarea', 'sourceTypeID', 'roadTypeID', 'hourID'], inplace=True) -vmt = b.copy() -vmt['hourID'] = (vmt['hourDayID'] - 5)/10 + #calculates hourvmtfraction based on original data + vmtshare['hourVMTFraction1'] = np.where(vmtshare['allvmt']>0.000001, vmtshare['vmt']/vmtshare['allvmt'], vmtshare['vmt']/0.000001) + #calculates hourvmtfraction based on fallback data + vmtshare.loc[~(vmtshare['vmt2'].isnull())&~(vmtshare['allvmt2'].isnull()), 'hourVMTFraction2'] = vmtshare['vmt2'] / vmtshare['allvmt2'] -hourvmt = vmt.groupby(['imarea','sourceTypeID','roadTypeID','hourID']).agg({'vmt':'sum'}).reset_index() -sumvmt = hourvmt.groupby(['imarea', 'sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() -sumvmt.rename(columns={'vmt':'allvmt'},inplace=True) -vmtshare = pd.merge(hourvmt, sumvmt, how='left', on=['imarea','sourceTypeID','roadTypeID']) -vmtshare.sort_values(['imarea','sourceTypeID','roadTypeID','hourID'],inplace=True) + #for sourcetypes 53,54 if there is any data + #then use both the non-zero vmt and the fallback data to arrive at the hourVMTFraction + truckpart = vmtshare.loc[(vmtshare['sourceTypeID'].isin([53,54]))&(vmtshare['vmt']>0)].copy() + vmtcount = truckpart.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'vmt':'count'}).reset_index() + vmtcount.rename(columns={'vmt':'vmtcount1'},inplace=True) -## -- use surrogates to replace missing values, if necessary -#bus part 1: use sourcetypeid 42 to replace missing values for sourceTypeID 41,43 for IM area -fb1 = vmtshare.loc[(vmtshare['sourceTypeID']==42)&(vmtshare['imarea']==1)].copy() -fb1_a = fb1.copy() -fb1_a['sourceTypeID'] = 41 -fb1_b = fb1.copy() -fb1_b['sourceTypeID'] = 43 -fb1 = pd.concat([fb1_a, fb1_b], ignore_index=True) + vmtweight = pd.merge(vmtshare, vmtcount, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID']) + vmtweight2 = vmtweight.copy() + #use fallback vmtfraction for 0 vmt hours + vmtweight2.loc[(vmtweight2['sourceTypeID'].isin([53,54]))&(vmtweight2['allvmt']>0)&(vmtweight2['vmt']==0), 'hourVMTFractionpre'] = vmtweight2['hourVMTFraction2'] -#bus part2: use sourcetypeID 41,42,43 for IM area to replace missing values for non-IM area -fb2 = pd.concat([fb1, vmtshare.loc[(vmtshare['sourceTypeID'].isin([41,42,43]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()], ignore_index=True) -fb2['imarea'] = 0 + #use average of the original and fallback vmtfraction otherwise + #original data is weighted by number of hours with data + vmtweight2.loc[(vmtweight2['sourceTypeID'].isin([53,54]))&(vmtweight2['allvmt']>0)&(vmtweight2['vmt']>0), 'hourVMTFractionpre'] = (((vmtweight2['vmtcount1']/24)*vmtweight2['hourVMTFraction1'])+vmtweight2['hourVMTFraction2'])/((vmtweight2['vmtcount1']+24)/24) -#su long-haul truck part1: use sourceTypeID 52 to replace missing values for sourcetypeID 53,54 for im area -fb3 = vmtshare.loc[(vmtshare['sourceTypeID']==52)&(vmtshare['imarea']==1)].copy() -fb3_a = fb3.copy() -fb3_a['sourceTypeID'] = 53 -fb3_b = fb3.copy() -fb3_b['sourceTypeID'] = 54 -fb3 = pd.concat([fb3_a, fb3_b], ignore_index=True) -#su long haul truck part2: use sourceTypeID 52,53,54 for IM area to replace missing values for non-IM area -fb4 = pd.concat([fb3, vmtshare.loc[(vmtshare['sourceTypeID'].isin([52,53,54]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()], ignore_index=True) -fb4['imarea'] = 0 + vmtpre = vmtweight2.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'hourVMTFractionpre':'sum'}).reset_index() + vmtpre.rename(columns={'hourVMTFractionpre':'vmtpresum'},inplace=True) -#mu long-haul truck part 1: use sourcetypeID 61 to replace missing values for sourcetypeid 62 for im area -fb5 = vmtshare.loc[(vmtshare['sourceTypeID']==61)&(vmtshare['imarea']==1)].copy() -fb5['sourceTypeID'] = 62 -#mu long-haul truck part2: use sourcetypeid 61,62 for IM area to replace missing values for non-IM area -fb6 = pd.concat([fb5, vmtshare.loc[(vmtshare['sourceTypeID'].isin([61,62]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()],ignore_index=True) -fb6['imarea'] = 0 + vmtshare = pd.merge(vmtweight2, vmtpre, how='left', on=['imarea','sourceTypeID','roadTypeID']).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) + vmtshare.loc[vmtshare['allvmt']==0, 'vmt3'] = vmtshare['vmt'] + vmtshare.loc[vmtshare['allvmt']==0, 'allvmt3'] = vmtshare['allvmt'] -fallback = pd.concat([fb1, fb2, fb3, fb4, fb5, fb6], ignore_index=True).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) -fallback.rename(columns={'vmt':'vmt2', 'allvmt':'allvmt2'},inplace=True) -fallback.drop_duplicates(subset=['imarea','sourceTypeID','roadTypeID','hourID'], inplace=True) + #substitution if no VMT for entire category + vmtshare.loc[(vmtshare['allvmt']==0)&(vmtshare['allvmt2']!=0), 'allvmt'] = vmtshare['allvmt2'] + vmtshare.loc[(vmtshare['vmt']==0)&(vmtshare['vmt2']!=0), 'vmt'] = vmtshare['vmt2'] + vmtshare.loc[((vmtshare['allvmt']==0)|(vmtshare['allvmt'].isnull()))&~(vmtshare['allvmt2'].isnull()), 'vmt'] = vmtshare['vmt2'] + vmtshare.loc[((vmtshare['allvmt']==0)|(vmtshare['allvmt'].isnull()))&~(vmtshare['allvmt2'].isnull()), 'allvmt'] = vmtshare['allvmt2'] -vmtshare = pd.merge(vmtshare, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID', 'hourID']) + #prevent division by zero + vmtshare['allvmt'] = np.maximum(vmtshare['allvmt'], 0.000001) + vmtshare.eval('hourVMTFraction = vmt / allvmt', inplace=True) + vmtshare['hourVMTFraction'] = vmtshare['hourVMTFraction'].round(6) + vmtshare.loc[(vmtshare['sourceTypeID'].isin([53,54]))&(vmtshare['vmtpresum']>0), 'hourVMTFraction'] = vmtshare['hourVMTFractionpre'] / vmtshare['vmtpresum'] + vmtshare['hourVMTFractionpre'] = vmtshare['hourVMTFractionpre'].round(6) -#calculates hourvmtfraction based on original data -vmtshare['hourVMTFraction1'] = np.where(vmtshare['allvmt']>0.000001, vmtshare['vmt']/vmtshare['allvmt'], vmtshare['vmt']/0.000001) -#calculates hourvmtfraction based on fallback data -vmtshare.loc[~(vmtshare['vmt2'].isnull())&~(vmtshare['allvmt2'].isnull()), 'hourVMTFraction2'] = vmtshare['vmt2'] / vmtshare['allvmt2'] + vmtshare.drop(columns=['vmtpresum','hourVMTFraction1','hourVMTFraction2','hourVMTFractionpre','vmtcount1'], inplace=True) + #apply urban arterial distribution to Off-Network type + vmtshare_b = vmtshare.copy() + vmtshare_b.loc[vmtshare_b['roadTypeID']==5, 'roadTypeID'] = 1 -#for sourcetypes 53,54 if there is any data -#then use both the non-zero vmt and the fallback data to arrive at the hourVMTFraction + vmtshare = pd.concat([vmtshare, vmtshare_b], ignore_index=True).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) -truckpart = vmtshare.loc[(vmtshare['sourceTypeID'].isin([53,54]))&(vmtshare['vmt']>0)].copy() -vmtcount = truckpart.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'vmt':'count'}).reset_index() -vmtcount.rename(columns={'vmt':'vmtcount1'},inplace=True) + vmtshare = pd.merge(template, vmtshare, how='left', on=['imarea','sourceTypeID','roadTypeID','hourID']) + vmtshare.drop_duplicates(['sourceTypeID','roadTypeID','dayID','hourID','imarea'], inplace=True) -vmtweight = pd.merge(vmtshare, vmtcount, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID']) -vmtweight2 = vmtweight.copy() -#use fallback vmtfraction for 0 vmt hours -vmtweight2.loc[(vmtweight2['sourceTypeID'].isin([53,54]))&(vmtweight2['allvmt']>0)&(vmtweight2['vmt']==0), 'hourVMTFractionpre'] = vmtweight2['hourVMTFraction2'] + hour_vmt_fraction = vmtshare.loc[vmtshare['imarea']==imarea, ['sourceTypeID','roadTypeID','dayID','hourID','hourVMTFraction']] -#use average of the original and fallback vmtfraction otherwise -#original data is weighted by number of hours with data -vmtweight2.loc[(vmtweight2['sourceTypeID'].isin([53,54]))&(vmtweight2['allvmt']>0)&(vmtweight2['vmt']>0), 'hourVMTFractionpre'] = (((vmtweight2['vmtcount1']/24)*vmtweight2['hourVMTFraction1'])+vmtweight2['hourVMTFraction2'])/((vmtweight2['vmtcount1']+24)/24) + return hour_vmt_fraction +def get_hpms_daily_vmt(b, imarea): + #modeled vehicle types only + hpms = b.loc[b['sourceTypeID'].isin([21,31,32,42,52,53,61,62])].copy() -vmtpre = vmtweight2.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'hourVMTFractionpre':'sum'}).reset_index() -vmtpre.rename(columns={'hourVMTFractionpre':'vmtpresum'},inplace=True) + # key = { 'sourceTypeID' : 'HPMSVtypeID' } + key = { + 21:25, + 32:25, + 42:40, #transit bus vmt only + 52:50, + 53:50, + 61:60, + 62:60 + } + hpms['HPMSVtypeID'] = hpms['sourceTypeID'].map(key) + hpms1 = hpms.groupby(['imarea', 'roadTypeID', 'HPMSVtypeID']).agg({'vmt':'sum'}).reset_index() + hpms1.rename(columns={'vmt':'HPMSDailyVMT'}, inplace=True) -vmtshare = pd.merge(vmtweight2, vmtpre, how='left', on=['imarea','sourceTypeID','roadTypeID']).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) -vmtshare.loc[vmtshare['allvmt']==0, 'vmt3'] = vmtshare['vmt'] -vmtshare.loc[vmtshare['allvmt']==0, 'allvmt3'] = vmtshare['allvmt'] + hpmsdailyvmt = hpms1.loc[hpms1['imarea']==imarea, ['roadTypeID','HPMSVtypeID','HPMSDailyVMT']] + hpmsdailyvmt['year'] = scenyear + return hpmsdailyvmt -#substitution if no VMT for entire category -vmtshare.loc[(vmtshare['allvmt']==0)&(vmtshare['allvmt2']!=0), 'allvmt'] = vmtshare['allvmt2'] -vmtshare.loc[(vmtshare['vmt']==0)&(vmtshare['vmt2']!=0), 'vmt'] = vmtshare['vmt2'] -vmtshare.loc[((vmtshare['allvmt']==0)|(vmtshare['allvmt'].isnull()))&~(vmtshare['allvmt2'].isnull()), 'vmt'] = vmtshare['vmt2'] -vmtshare.loc[((vmtshare['allvmt']==0)|(vmtshare['allvmt'].isnull()))&~(vmtshare['allvmt2'].isnull()), 'allvmt'] = vmtshare['allvmt2'] +def get_month_days(year): + """ Accounts for leap year """ + # Create dataframe of days per month + days_mo = {'month': ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', + 'September', 'October', 'November', 'December'], + 'days': [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]} + + # Check if year is a leap year, and if so increase days in February by 1 + check_leap = (year-2016)/4 + if check_leap.is_integer(): + # print(f" ---> {year} is a leap year.") + feb_ind = days_mo["month"].index("February") + days_mo['days'][feb_ind] +=1 + # else: + # print(f" ---> {year} is not a leap year.") -#prevent division by zero -vmtshare['allvmt'] = np.maximum(vmtshare['allvmt'], 0.000001) -vmtshare.eval('hourVMTFraction = vmt / allvmt', inplace=True) -vmtshare['hourVMTFraction'] = vmtshare['hourVMTFraction'].round(6) + days_mo_df =pd.DataFrame(days_mo) -vmtshare.loc[(vmtshare['sourceTypeID'].isin([53,54]))&(vmtshare['vmtpresum']>0), 'hourVMTFraction'] = vmtshare['hourVMTFractionpre'] / vmtshare['vmtpresum'] -vmtshare['hourVMTFractionpre'] = vmtshare['hourVMTFractionpre'].round(6) + return days_mo_df -vmtshare.drop(columns=['vmtpresum','hourVMTFraction1','hourVMTFraction2','hourVMTFractionpre','vmtcount1'], inplace=True) +def get_hpms_annual_vmt(hpms_daily_vmt, year): -#apply urban arterial distribution to Off-Network type -vmtshare_b = vmtshare.copy() -vmtshare_b.loc[vmtshare_b['roadTypeID']==5, 'roadTypeID'] = 1 + # Define weekdays + weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday"] -vmtshare = pd.concat([vmtshare, vmtshare_b], ignore_index=True).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) + # Get days in each month, account for leap years + in_days_mo = get_month_days(year) -vmtshare = pd.merge(template2, vmtshare, how='left', on=['imarea','sourceTypeID','roadTypeID','hourID']) + # Load in annual VMT adjustments - TO DO: move this outside the function + pth_seasonal = DB_DIR.joinpath('data', 'seasonal_VMT.xlsx') + in_weekFractions = pd.read_excel(pth_seasonal, sheet_name = 'weekday_to_weekly') + in_moFractions = pd.read_excel(pth_seasonal, sheet_name = 'monthly_fractions') + in_source25split = pd.read_excel(pth_seasonal, sheet_name = 'split25') -vmtshare.drop_duplicates(['sourceTypeID','roadTypeID','dayID','hourID','imarea'], inplace=True) + # STEP 1: Find average weekday rate + weekFractions = in_weekFractions.copy() + weekFractions['flag_weekday'] = np.where(weekFractions['day'].isin(weekdays), 1, 0) + weekFractions['mean_weekday'] = weekFractions.groupby(['roadType','roadTypeID', 'flag_weekday'])['IDOT_VMT_pct'].transform('mean') -#final vmt fraction to excel -outIM_hourvmtfraction = vmtshare.loc[vmtshare['imarea']==1, ['sourceTypeID','roadTypeID','dayID','hourID','hourVMTFraction']] -outIM_hourvmtfraction.to_excel(xlsx_IM, sheet_name='hourVMTFraction', index=False) + roadTypeweekday = weekFractions.loc[weekFractions['flag_weekday'] == 1].copy() + roadTypeweekday = roadTypeweekday[['roadType', 'roadTypeID','mean_weekday']].drop_duplicates() -outnoIM_hourvmtfraction = vmtshare.loc[vmtshare['imarea']==0, ['sourceTypeID','roadTypeID','dayID','hourID','hourVMTFraction']] -outnoIM_hourvmtfraction.to_excel(xlsx_noIM, sheet_name='hourVMTFraction', index=False) + roadTypePct = in_weekFractions.copy() + roadTypePct = roadTypePct.merge(roadTypeweekday, on=['roadType','roadTypeID']) + roadTypePct['AvWeekday'] = roadTypePct['IDOT_VMT_pct']/roadTypePct['mean_weekday'] + roadTypePct = roadTypePct.groupby(['roadType', 'roadTypeID'])['AvWeekday'].mean().reset_index() + + # STEP 2: Find adjustment factor for month + adjust_fractions = in_moFractions.merge(roadTypePct, on=['roadType', 'roadTypeID']) + adjust_fractions['adj_fraction'] = adjust_fractions['fraction']*adjust_fractions['AvWeekday'] + adjust_fractions = adjust_fractions[['roadType','roadTypeID', 'month', 'adj_fraction']].copy() + #STEP 3: Apply adjustment factor for each month to source type EMME VMT + emme_adj = hpms_daily_vmt.merge(adjust_fractions, on='roadTypeID') + emme_adj['adjTotal'] = emme_adj['HPMSDailyVMT']*emme_adj['adj_fraction'] + emme_adj = emme_adj.merge(in_days_mo, on='month') + emme_adj['final_adj'] = emme_adj['days']*emme_adj['adjTotal'] + emme_adj=emme_adj.groupby(['HPMSVtypeID', 'roadType', 'roadTypeID'])['final_adj'].sum().reset_index() + + # STEP 4: Adjustment to separate motorcycles and passenger and light cars + emme_adj = emme_adj.merge(in_source25split, on='roadTypeID') + emme_adj['final_VMT'] = np.where(emme_adj['HPMSVtypeID'] == 25, emme_adj['final_adj']*emme_adj['share'], emme_adj['final_adj']) + emme_adj['sourceTypeID'] = np.where(emme_adj['HPMSVtypeID'] == 25, emme_adj['source'], emme_adj['HPMSVtypeID']) + emme_adj = emme_adj[['sourceTypeID', 'roadTypeID', 'roadType', 'final_VMT']].drop_duplicates().copy() + emme_adj = emme_adj.groupby('sourceTypeID')['final_VMT'].sum().round().reset_index() -###################################################### -## -- VMT by road type and HPMS vehicle type tab -- ## -###################################################### + # Format for export + emme_adj.rename(columns={'sourceTypeID':'HPMSVtypeID', 'final_VMT':'HPMSBaseYearVMT'}, inplace=True) + emme_adj['yearID'] = scenyear + emme_adj=emme_adj[['HPMSVtypeID', 'yearID', 'HPMSBaseYearVMT']].copy() + + return emme_adj + +if __name__ == "__main__": + + # Get parameters from batch file + with open(DB_DIR.joinpath('batch_file.yaml')) as f: + config = yaml.safe_load(f) + model = config['model_version'] # e.g., 'c23q4' + scenyear = config['scenario_code'] # e.g., '400' + year = config['year'] + exportAs = config['exportAs'] # im or im_county + + # Load in punchlink for specific scenario year + linkdata = pd.read_csv(DB_DIR.joinpath('data', 'punchlink.csv')) + + # Merge in zone-county crosswalk + zone_county_cw = pd.read_csv(DB_DIR.joinpath('data', 'zone17_county_crosswalk.csv')) + linkdata = pd.merge(linkdata, zone_county_cw, left_on="zone", right_on="zone17", how = "left").drop("zone17", axis=1) + + # Get clean link data + links = clean_linkdata(linkdata) + + # If just IM/nonIM run, set counties to empty string. Otherwise, use all CMAP region counties. + if exportAs == "im": + counties = [""] + if exportAs == "im_county": + counties = ['COOK', 'DUPAGE', 'KANE', 'KENDALL', 'LAKE', 'MCHENRY', 'WILL','GRUNDY'] + + # Define IDs + groupcols = ['imarea', 'roadTypeID', 'timeperiod', 'avgSpeedBinID', 'hours'] + + # Loop over counties + for county in counties: + + # If im_county run, filter for just links in a given county + if county != "": + links_to_use = links.loc[links["county_name"] == county] + county_ext = f"_{county}" -#modeled vehicle types only -hpms = b.loc[b['sourceTypeID'].isin([21,31,32,42,52,53,61,62])].copy() + # Otherwise, use entire links dataset + else: + links_to_use = links.copy() + county_ext = "" -# key = { 'sourceTypeID' : 'HPMSVtypeID' } -key = { - 21:25, - 32:25, - 42:40, #transit bus vmt only - 52:50, - 53:50, - 61:60, - 62:60 -} + # Aggregate to VMT/VHT by group cols + b = agg_links(groupcols, links_to_use) + + # Loop over IM regions + for imarea_text, imarea in {"IM": 1, "nonIM": 0}.items(): -hpms['HPMSVtypeID'] = hpms['sourceTypeID'].map(key) -hpms1 = hpms.groupby(['imarea', 'roadTypeID', 'HPMSVtypeID']).agg({'vmt':'sum'}).reset_index() -hpms1.rename(columns={'vmt':'HPMSDailyVMT'}, inplace=True) -#final vmt fraction to excel -outIM_hpmsdailyvmt = hpms1.loc[hpms1['imarea']==1, ['roadTypeID','HPMSVtypeID','HPMSDailyVMT']] -outIM_hpmsdailyvmt['year'] = scenyear -outIM_hpmsdailyvmt.to_excel(xlsx_IM, sheet_name='HPMSDailyVMT', index=False) + # Tab 1: Initial Model Output + initial_model_output = get_initial_model_output(b, imarea) + + # If no data, don't output file + if (np.all(initial_model_output["vmt"]==0)) & (np.all(initial_model_output["vht"]==0)): + continue + + # Tab 2: Average Speed Distribution + avg_speed_dist = get_avg_speed_distribution(b,imarea) + + # Tab 3: Road Type Distribution + road_type_distribution = get_road_type_distribution(b, imarea) + + # Tab 4: Hourly VMT Fraction + hourly_vmt_fraction = get_hourly_vmt_fraction(b, imarea) -outnoIM_hpmsdailyvmt = hpms1.loc[hpms1['imarea']==0, ['roadTypeID','HPMSVtypeID','HPMSDailyVMT']] -outnoIM_hpmsdailyvmt['year'] = scenyear -outnoIM_hpmsdailyvmt.to_excel(xlsx_noIM, sheet_name='HPMSDailyVMT', index=False) + # Tab 5: HPMS Daily VMT + hpms_daily_vmt = get_hpms_daily_vmt(b, imarea) + + # Tab 6: HPMS Annual VMT + hpms_annual_vmt = get_hpms_annual_vmt(hpms_daily_vmt, year) + + # Create folder for outputs if it doesn't already exist + out_folder = DB_DIR.joinpath('data', f'MOVES_{model}_scen{scenyear}') + out_folder.mkdir(exist_ok=True) + + # Output to Excel Workbook + out_path = out_folder.joinpath(f'MOVES_{model}_scen{scenyear}_{imarea_text}{county_ext}.xlsx') + out_xlsx = pd.ExcelWriter(out_path) + initial_model_output.to_excel(out_xlsx, sheet_name='initial_model_output', index=False) + avg_speed_dist.to_excel(out_xlsx, sheet_name='AvgSpeedDistribution', index=False) + road_type_distribution.to_excel(out_xlsx, sheet_name='RoadTypeDistribution', index=False) + hourly_vmt_fraction.to_excel(out_xlsx, sheet_name='hourVMTFraction', index=False) + hpms_daily_vmt.to_excel(out_xlsx, sheet_name='HPMSDailyVMT', index=False) + hpms_annual_vmt.to_excel(out_xlsx, sheet_name='HPMSVtypeYear', index=False) + out_xlsx.close() + + print("Done!") -xlsx_IM.close() -xlsx_noIM.close() -print('Done!') ## ---------------- END CREATE MOVES INPUT FILE (SAS) ------------------ From 850574649ffb25507bb5e3e7ab71054038dd0125 Mon Sep 17 00:00:00 2001 From: Sarah Zebar Date: Thu, 6 Aug 2026 10:04:55 -0500 Subject: [PATCH 02/13] incorporating just county run (i.e. aggregated IM/nonIM) --- Database/post_macros/createMOVESinputfile.py | 59 +++++++++++++++----- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/Database/post_macros/createMOVESinputfile.py b/Database/post_macros/createMOVESinputfile.py index 64e77e1..c0c4af9 100644 --- a/Database/post_macros/createMOVESinputfile.py +++ b/Database/post_macros/createMOVESinputfile.py @@ -281,13 +281,19 @@ def replace_neg_w_zero(x): return b -def get_initial_model_output(b, imarea): +def get_initial_model_output(b, imarea=None): """ Just filters to given imarea and excludes non-modeled source types""" stypes_to_exclude = [11,41,43,51,54] - initial_model_output = b.loc[~(b["sourceTypeID"].isin(stypes_to_exclude)) & (b['imarea']==imarea)].copy(deep=True) + + if imarea is None: + initial_model_output = b.loc[~(b["sourceTypeID"].isin(stypes_to_exclude))].copy(deep=True) + + else: + initial_model_output = b.loc[~(b["sourceTypeID"].isin(stypes_to_exclude)) & (b['imarea']==imarea)].copy(deep=True) + return initial_model_output -def get_avg_speed_distribution(b,imarea): +def get_avg_speed_distribution(b,imarea=None): casecols = ['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID'] @@ -343,9 +349,13 @@ def get_avg_speed_distribution(b,imarea): avg_speed_dist = share[['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID','avgSpeedFraction']] - return avg_speed_dist.loc[(avg_speed_dist['imarea']==imarea)].drop(columns='imarea') + if imarea is None: + return avg_speed_dist + + else: + return avg_speed_dist.loc[(avg_speed_dist['imarea']==imarea)].drop(columns='imarea') -def get_road_type_distribution(b, imarea): +def get_road_type_distribution(b, imarea=None): roadtype = b.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() roadtype2 = b.groupby(['imarea','sourceTypeID']).agg({'vmt':'sum'}).rename(columns={'vmt':'sourceVMT'}).reset_index() @@ -406,11 +416,15 @@ def abovezero(x): roadtype.eval('roadTypeVMTFraction = vmt / sourceVMT', inplace=True) roadtype['roadTypeVMTFraction'] = roadtype['roadTypeVMTFraction'].round(6) - road_type_distribution = roadtype.loc[roadtype['imarea']==imarea,['sourceTypeID','roadTypeID','roadTypeVMTFraction']].copy() + if imarea is None: + road_type_distribution = roadtype[['sourceTypeID','roadTypeID','roadTypeVMTFraction','imarea']].copy() + + else: + road_type_distribution = roadtype.loc[roadtype['imarea']==imarea,['sourceTypeID','roadTypeID','roadTypeVMTFraction']].copy() return road_type_distribution -def get_ramp_fraction(links, imarea): +def get_ramp_fraction(links, imarea=None): rmp = links.loc[links['roadTypeID'].isin([2,4])].copy(deep=True) rmp.eval('fwyvht = auto_vht + bplate_vht + sush_vht + mtrucklh_vht + htruck_vht + htrucklh_vht + bus_vht', inplace=True) @@ -425,10 +439,13 @@ def get_ramp_fraction(links, imarea): ramp['vmtFraction'] = ramp['vmtFraction'].round(6) # Output ramp fraction for im area - ramp_fraction = ramp.loc[ramp['imarea']==imarea,['roadTypeID','rampFraction']] + if imarea is None: + ramp_fraction = ramp[['roadTypeID','rampFraction', 'imarea']] + else: + ramp_fraction = ramp.loc[ramp['imarea']==imarea,['roadTypeID','rampFraction']] return ramp_fraction -def get_hourly_vmt_fraction(b, imarea): +def get_hourly_vmt_fraction(b, imarea=None): # Apply data to template (all ID combinations) roads = [1] + ROAD_TYPES # add off-network roads just for this function @@ -544,11 +561,14 @@ def get_hourly_vmt_fraction(b, imarea): vmtshare.drop_duplicates(['sourceTypeID','roadTypeID','dayID','hourID','imarea'], inplace=True) - hour_vmt_fraction = vmtshare.loc[vmtshare['imarea']==imarea, ['sourceTypeID','roadTypeID','dayID','hourID','hourVMTFraction']] + if imarea is None: + hour_vmt_fraction = vmtshare[['sourceTypeID','roadTypeID','dayID','hourID','hourVMTFraction',"imarea"]] + else: + hour_vmt_fraction = vmtshare.loc[vmtshare['imarea']==imarea, ['sourceTypeID','roadTypeID','dayID','hourID','hourVMTFraction']] return hour_vmt_fraction -def get_hpms_daily_vmt(b, imarea): +def get_hpms_daily_vmt(b, imarea=None): #modeled vehicle types only hpms = b.loc[b['sourceTypeID'].isin([21,31,32,42,52,53,61,62])].copy() @@ -566,8 +586,14 @@ def get_hpms_daily_vmt(b, imarea): hpms['HPMSVtypeID'] = hpms['sourceTypeID'].map(key) hpms1 = hpms.groupby(['imarea', 'roadTypeID', 'HPMSVtypeID']).agg({'vmt':'sum'}).reset_index() hpms1.rename(columns={'vmt':'HPMSDailyVMT'}, inplace=True) + + + if imarea is None: + hpmsdailyvmt = hpms1[['roadTypeID','HPMSVtypeID','HPMSDailyVMT']] + + else: + hpmsdailyvmt = hpms1.loc[hpms1['imarea']==imarea, ['roadTypeID','HPMSVtypeID','HPMSDailyVMT']] - hpmsdailyvmt = hpms1.loc[hpms1['imarea']==imarea, ['roadTypeID','HPMSVtypeID','HPMSDailyVMT']] hpmsdailyvmt['year'] = scenyear return hpmsdailyvmt @@ -668,8 +694,15 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): # If just IM/nonIM run, set counties to empty string. Otherwise, use all CMAP region counties. if exportAs == "im": counties = [""] + im_regions = [("IM",1), ("nonIM", 0)] if exportAs == "im_county": counties = ['COOK', 'DUPAGE', 'KANE', 'KENDALL', 'LAKE', 'MCHENRY', 'WILL','GRUNDY'] + im_regions = [("IM",1), ("nonIM", 0)] + if exportAs == "county": + counties = ['COOK', 'DUPAGE', 'KANE', 'KENDALL', 'LAKE', 'MCHENRY', 'WILL','GRUNDY'] + im_regions = [("",None)] + + # Define IDs groupcols = ['imarea', 'roadTypeID', 'timeperiod', 'avgSpeedBinID', 'hours'] @@ -691,7 +724,7 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): b = agg_links(groupcols, links_to_use) # Loop over IM regions - for imarea_text, imarea in {"IM": 1, "nonIM": 0}.items(): + for imarea_text, imarea in im_regions: # Tab 1: Initial Model Output From fc752750cd86ee575a058cb02711e30f336cdfc1 Mon Sep 17 00:00:00 2001 From: Sarah Zebar Date: Thu, 6 Aug 2026 10:06:23 -0500 Subject: [PATCH 03/13] editing batch_file to include year and exportAs parameters --- Database/batch_file.yaml | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/Database/batch_file.yaml b/Database/batch_file.yaml index 76ebf8c..4cc2339 100644 --- a/Database/batch_file.yaml +++ b/Database/batch_file.yaml @@ -1,12 +1,30 @@ # Project details model_version: c26q2 -scenario_code: 100 +scenario_code: 600 +year: 2040 # make sure this matches scenario_code +#--- Scenario Code - Year Mapping ---# +# 100: 2019 +# 200: 2026 +# 300: 2030 +# 500: 2035 +# 600: 2040 +# 800: 2050 + +exportAs: "county" +# "im" to just output IM/nonIM Excel workbooks +# "im_county" to output IM/nonIM Excel workbooks for each county in the region +# "county" to output workbooks for each county (include both IM and nonIM regions) + +# ---------------- Work from home module inputs (trip generation) +validationfiles: N +usualwfhpct: 0.0510 +tc14pct: 0.1031 # ---------------- Select link analysis files: provide file name (ex: RSP32_links.txt [stored in Database\Select_Link\]) or use None # ---------------- Can submit up to 5, comma-separated, any order, no spaces, (ex: None,test4.txt,test1.txt,None,None) selectLinkFile: None,None,None,None,None # ---------------- Transaction file path: include the path to the transaction files that will build the scenario networks in double quotes (spaces OK), # ---------------- point to directory above highway\ and transit\, no ending backslash (ex: "M:\catslib\modelprod\c24q2" or "M:/catslib/modelprod/24q2") -transactionFilePath: "M:/proj1/nrf/Conformity/c25q4" +transactionFilePath: "M:/proj1/nrf/Conformity/c25q2" # ---------------- Run Transit Assignment at the end of the model run? Default is False. runTransitAsmt: False # ---------------- Transit select line analysis file: provide file name (ex: rsp57_line.txt [stored in Database\Select_Line\]) or use None @@ -17,6 +35,6 @@ util_files: False UrbanSim_file: False # ---------------- Is this an RSP evaluation run? Default is False. RSP: False -# ---------------- PUMA version used in Trip Generation. 2010 is the current option. -pumaVersion: 2010 - +# ---------------- sourceCode will force CMAP-TRIP2 to use the source code in this model setup if set to True. Default is True. +# ---------------- Set to False if this is the second of two simultaneous runs being submitted. +sourceCode: True \ No newline at end of file From a0f32ff08d46c5d5c0ae8521cffbd24ae28f3801 Mon Sep 17 00:00:00 2001 From: Sarah Zebar Date: Thu, 6 Aug 2026 10:08:00 -0500 Subject: [PATCH 04/13] adding MOVES_constants for createMOVESinputfile --- Database/post_macros/MOVES_constants.py | 45 +++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Database/post_macros/MOVES_constants.py diff --git a/Database/post_macros/MOVES_constants.py b/Database/post_macros/MOVES_constants.py new file mode 100644 index 0000000..6540485 --- /dev/null +++ b/Database/post_macros/MOVES_constants.py @@ -0,0 +1,45 @@ +### Defines constants for the createMOVESinputfile.py file + +SOURCE_TYPES = [ + 11, # Motorcycle + 21, # Passenger Car + 31, # Passenger Truck + 32, # Light Commercial Truck + 41, # Other Buses + 42, # Transit Bus + 43, # School Bus + 51, # Refuse Truck + 52, # Single Unit Short-haul Truck + 53, # Single Unit Long-haul Truck + 54, # Motor Homes + 61, # Combination Short-haul Truck + 62 # Combination Long-haul Truck + ] + +ROAD_TYPES = [ + 2, # Rural Restricted Access + 3, # Rural Unrestricted Access + 4, # Urban Restricted Access + 5 # Urban Unrestricted Access + ] # note: ROAD_TYPE 1 is off-network, and not included in all tabs except hourly VMT fraction + +SPEED_BINS = [ + 1, # <2.5 mph + 2, # 2.5 - 7.5 mph + 3, # 7.5 - 12.5 mph + 4, # 12.5 - 17.5 mph + 5, # 17.5 - 22.5 mph + 6, # 22.5 - 27.5 mph + 7, # 27.5 - 32.5 mph + 8, # 32.5 - 37.5 mph + 9, # 37.5 - 42.5 mph + 10, # 42.5 - 47.5 mph + 11, # 47.5 - 52.5 mph + 12, # 52.5 - 57.5 mph + 13, # 57.5 - 62.5 mph + 14, # 62.5 - 67.5 mph + 15, # 67.5 - 72.5 mph + 16 # >=72.5 +] + +HOURS = list(range(1,25)) # range end is exclusive \ No newline at end of file From edd697c3618e7ba87186f4a78937803cca49e3ab Mon Sep 17 00:00:00 2001 From: Sarah Zebar Date: Thu, 6 Aug 2026 10:10:48 -0500 Subject: [PATCH 05/13] adding zone-county crosswalk for county integration --- Database/data/zone17_county_crosswalk.csv | 3633 +++++++++++++++++++++ 1 file changed, 3633 insertions(+) create mode 100644 Database/data/zone17_county_crosswalk.csv diff --git a/Database/data/zone17_county_crosswalk.csv b/Database/data/zone17_county_crosswalk.csv new file mode 100644 index 0000000..f4003a5 --- /dev/null +++ b/Database/data/zone17_county_crosswalk.csv @@ -0,0 +1,3633 @@ +zone17,county_fips,county_name,state +1,17031,COOK,IL +2,17031,COOK,IL +3,17031,COOK,IL +4,17031,COOK,IL +5,17031,COOK,IL +6,17031,COOK,IL +7,17031,COOK,IL +8,17031,COOK,IL +9,17031,COOK,IL +10,17031,COOK,IL +11,17031,COOK,IL +12,17031,COOK,IL +13,17031,COOK,IL +14,17031,COOK,IL +15,17031,COOK,IL +16,17031,COOK,IL +17,17031,COOK,IL +18,17031,COOK,IL +19,17031,COOK,IL +20,17031,COOK,IL +21,17031,COOK,IL +22,17031,COOK,IL +23,17031,COOK,IL +24,17031,COOK,IL +25,17031,COOK,IL +26,17031,COOK,IL +27,17031,COOK,IL +28,17031,COOK,IL +29,17031,COOK,IL +30,17031,COOK,IL +31,17031,COOK,IL +32,17031,COOK,IL +33,17031,COOK,IL +34,17031,COOK,IL +35,17031,COOK,IL +36,17031,COOK,IL +37,17031,COOK,IL +38,17031,COOK,IL +39,17031,COOK,IL +40,17031,COOK,IL +41,17031,COOK,IL +42,17031,COOK,IL +43,17031,COOK,IL +44,17031,COOK,IL +45,17031,COOK,IL +46,17031,COOK,IL +47,17031,COOK,IL +48,17031,COOK,IL +49,17031,COOK,IL +50,17031,COOK,IL +51,17031,COOK,IL +52,17031,COOK,IL +53,17031,COOK,IL +54,17031,COOK,IL +55,17031,COOK,IL +56,17031,COOK,IL +57,17031,COOK,IL +58,17031,COOK,IL +59,17031,COOK,IL +60,17031,COOK,IL +61,17031,COOK,IL +62,17031,COOK,IL +63,17031,COOK,IL +64,17031,COOK,IL +65,17031,COOK,IL +66,17031,COOK,IL +67,17031,COOK,IL +68,17031,COOK,IL +69,17031,COOK,IL +70,17031,COOK,IL +71,17031,COOK,IL +72,17031,COOK,IL +73,17031,COOK,IL +74,17031,COOK,IL +75,17031,COOK,IL +76,17031,COOK,IL +77,17031,COOK,IL +78,17031,COOK,IL +79,17031,COOK,IL +80,17031,COOK,IL +81,17031,COOK,IL +82,17031,COOK,IL +83,17031,COOK,IL +84,17031,COOK,IL +85,17031,COOK,IL +86,17031,COOK,IL +87,17031,COOK,IL +88,17031,COOK,IL +89,17031,COOK,IL +90,17031,COOK,IL +91,17031,COOK,IL +92,17031,COOK,IL +93,17031,COOK,IL +94,17031,COOK,IL +95,17031,COOK,IL +96,17031,COOK,IL +97,17031,COOK,IL +98,17031,COOK,IL +99,17031,COOK,IL +100,17031,COOK,IL +101,17031,COOK,IL +102,17031,COOK,IL +103,17031,COOK,IL +104,17031,COOK,IL +105,17031,COOK,IL +106,17031,COOK,IL +107,17031,COOK,IL +108,17031,COOK,IL +109,17031,COOK,IL +110,17031,COOK,IL +111,17031,COOK,IL +112,17031,COOK,IL +113,17031,COOK,IL +114,17031,COOK,IL +115,17031,COOK,IL +116,17031,COOK,IL +117,17031,COOK,IL +118,17031,COOK,IL +119,17031,COOK,IL +120,17031,COOK,IL +121,17031,COOK,IL +122,17031,COOK,IL +123,17031,COOK,IL +124,17031,COOK,IL +125,17031,COOK,IL +126,17031,COOK,IL +127,17031,COOK,IL +128,17031,COOK,IL +129,17031,COOK,IL +130,17031,COOK,IL +131,17031,COOK,IL +132,17031,COOK,IL +133,17031,COOK,IL +134,17031,COOK,IL +135,17031,COOK,IL +136,17031,COOK,IL +137,17031,COOK,IL +138,17031,COOK,IL +139,17031,COOK,IL +140,17031,COOK,IL +141,17031,COOK,IL +142,17031,COOK,IL +143,17031,COOK,IL +144,17031,COOK,IL +145,17031,COOK,IL +146,17031,COOK,IL +147,17031,COOK,IL +148,17031,COOK,IL +149,17031,COOK,IL +150,17031,COOK,IL +151,17031,COOK,IL +152,17031,COOK,IL +153,17031,COOK,IL +154,17031,COOK,IL +155,17031,COOK,IL +156,17031,COOK,IL +157,17031,COOK,IL +158,17031,COOK,IL +159,17031,COOK,IL +1160,17031,COOK,IL +160,17031,COOK,IL +161,17031,COOK,IL +162,17031,COOK,IL +163,17031,COOK,IL +164,17031,COOK,IL +165,17031,COOK,IL +166,17031,COOK,IL +167,17031,COOK,IL +168,17031,COOK,IL +169,17031,COOK,IL +170,17031,COOK,IL +171,17031,COOK,IL +172,17031,COOK,IL +173,17031,COOK,IL +174,17031,COOK,IL +175,17031,COOK,IL +176,17031,COOK,IL +177,17031,COOK,IL +178,17031,COOK,IL +179,17031,COOK,IL +180,17031,COOK,IL +181,17031,COOK,IL +182,17031,COOK,IL +183,17031,COOK,IL +184,17031,COOK,IL +185,17031,COOK,IL +186,17031,COOK,IL +187,17031,COOK,IL +188,17031,COOK,IL +189,17031,COOK,IL +190,17031,COOK,IL +191,17031,COOK,IL +192,17031,COOK,IL +193,17031,COOK,IL +194,17031,COOK,IL +195,17031,COOK,IL +196,17031,COOK,IL +197,17031,COOK,IL +198,17031,COOK,IL +199,17031,COOK,IL +200,17031,COOK,IL +201,17031,COOK,IL +202,17031,COOK,IL +203,17031,COOK,IL +204,17031,COOK,IL +205,17031,COOK,IL +206,17031,COOK,IL +207,17031,COOK,IL +208,17031,COOK,IL +209,17031,COOK,IL +210,17031,COOK,IL +211,17031,COOK,IL +212,17031,COOK,IL +213,17031,COOK,IL +214,17031,COOK,IL +215,17031,COOK,IL +216,17031,COOK,IL +217,17031,COOK,IL +218,17031,COOK,IL +219,17031,COOK,IL +220,17031,COOK,IL +221,17031,COOK,IL +222,17031,COOK,IL +223,17031,COOK,IL +224,17031,COOK,IL +225,17031,COOK,IL +226,17031,COOK,IL +227,17031,COOK,IL +228,17031,COOK,IL +229,17031,COOK,IL +230,17031,COOK,IL +231,17031,COOK,IL +232,17031,COOK,IL +233,17031,COOK,IL +234,17031,COOK,IL +235,17031,COOK,IL +236,17031,COOK,IL +237,17031,COOK,IL +238,17031,COOK,IL +239,17031,COOK,IL +240,17031,COOK,IL +241,17031,COOK,IL +242,17031,COOK,IL +243,17031,COOK,IL +244,17031,COOK,IL +245,17031,COOK,IL +246,17031,COOK,IL +247,17031,COOK,IL +248,17031,COOK,IL +249,17031,COOK,IL +250,17031,COOK,IL +251,17031,COOK,IL +252,17031,COOK,IL +253,17031,COOK,IL +254,17031,COOK,IL +255,17031,COOK,IL +256,17031,COOK,IL +257,17031,COOK,IL +258,17031,COOK,IL +259,17031,COOK,IL +260,17031,COOK,IL +261,17031,COOK,IL +262,17031,COOK,IL +263,17031,COOK,IL +264,17031,COOK,IL +265,17031,COOK,IL +266,17031,COOK,IL +267,17031,COOK,IL +268,17031,COOK,IL +269,17031,COOK,IL +270,17031,COOK,IL +271,17031,COOK,IL +272,17031,COOK,IL +273,17031,COOK,IL +274,17031,COOK,IL +275,17031,COOK,IL +276,17031,COOK,IL +277,17031,COOK,IL +278,17031,COOK,IL +279,17031,COOK,IL +280,17031,COOK,IL +281,17031,COOK,IL +282,17031,COOK,IL +283,17031,COOK,IL +284,17031,COOK,IL +285,17031,COOK,IL +286,17031,COOK,IL +287,17031,COOK,IL +288,17031,COOK,IL +289,17031,COOK,IL +290,17031,COOK,IL +291,17031,COOK,IL +292,17031,COOK,IL +293,17031,COOK,IL +294,17031,COOK,IL +295,17031,COOK,IL +296,17031,COOK,IL +297,17031,COOK,IL +298,17031,COOK,IL +299,17031,COOK,IL +300,17031,COOK,IL +301,17031,COOK,IL +302,17031,COOK,IL +303,17031,COOK,IL +304,17031,COOK,IL +305,17031,COOK,IL +306,17031,COOK,IL +307,17031,COOK,IL +308,17031,COOK,IL +309,17031,COOK,IL +310,17031,COOK,IL +311,17031,COOK,IL +312,17031,COOK,IL +313,17031,COOK,IL +314,17031,COOK,IL +315,17031,COOK,IL +316,17031,COOK,IL +317,17031,COOK,IL +318,17031,COOK,IL +319,17031,COOK,IL +320,17031,COOK,IL +321,17031,COOK,IL +322,17031,COOK,IL +323,17031,COOK,IL +324,17031,COOK,IL +325,17031,COOK,IL +326,17031,COOK,IL +327,17031,COOK,IL +328,17031,COOK,IL +329,17031,COOK,IL +330,17031,COOK,IL +331,17031,COOK,IL +332,17031,COOK,IL +333,17031,COOK,IL +334,17031,COOK,IL +335,17031,COOK,IL +336,17031,COOK,IL +337,17031,COOK,IL +338,17031,COOK,IL +339,17031,COOK,IL +340,17031,COOK,IL +341,17031,COOK,IL +342,17031,COOK,IL +343,17031,COOK,IL +344,17031,COOK,IL +345,17031,COOK,IL +346,17031,COOK,IL +347,17031,COOK,IL +348,17031,COOK,IL +349,17031,COOK,IL +350,17031,COOK,IL +351,17031,COOK,IL +352,17031,COOK,IL +353,17031,COOK,IL +354,17031,COOK,IL +355,17031,COOK,IL +356,17031,COOK,IL +357,17031,COOK,IL +358,17031,COOK,IL +359,17031,COOK,IL +360,17031,COOK,IL +361,17031,COOK,IL +362,17031,COOK,IL +363,17031,COOK,IL +364,17031,COOK,IL +365,17031,COOK,IL +366,17031,COOK,IL +367,17031,COOK,IL +368,17031,COOK,IL +369,17031,COOK,IL +370,17031,COOK,IL +371,17031,COOK,IL +372,17031,COOK,IL +373,17031,COOK,IL +374,17031,COOK,IL +375,17031,COOK,IL +376,17031,COOK,IL +377,17031,COOK,IL +378,17031,COOK,IL +379,17031,COOK,IL +380,17031,COOK,IL +381,17031,COOK,IL +382,17031,COOK,IL +383,17031,COOK,IL +384,17031,COOK,IL +385,17031,COOK,IL +386,17031,COOK,IL +387,17031,COOK,IL +388,17031,COOK,IL +389,17031,COOK,IL +390,17031,COOK,IL +391,17031,COOK,IL +392,17031,COOK,IL +393,17031,COOK,IL +394,17031,COOK,IL +395,17031,COOK,IL +396,17031,COOK,IL +397,17031,COOK,IL +398,17031,COOK,IL +399,17031,COOK,IL +400,17031,COOK,IL +401,17031,COOK,IL +402,17031,COOK,IL +403,17031,COOK,IL +404,17031,COOK,IL +405,17031,COOK,IL +406,17031,COOK,IL +407,17031,COOK,IL +408,17031,COOK,IL +409,17031,COOK,IL +410,17031,COOK,IL +411,17031,COOK,IL +412,17031,COOK,IL +413,17031,COOK,IL +414,17031,COOK,IL +415,17031,COOK,IL +416,17031,COOK,IL +417,17031,COOK,IL +418,17031,COOK,IL +419,17031,COOK,IL +420,17031,COOK,IL +421,17031,COOK,IL +422,17031,COOK,IL +423,17031,COOK,IL +424,17031,COOK,IL +425,17031,COOK,IL +426,17031,COOK,IL +427,17031,COOK,IL +428,17031,COOK,IL +429,17031,COOK,IL +430,17031,COOK,IL +431,17031,COOK,IL +432,17031,COOK,IL +433,17031,COOK,IL +434,17031,COOK,IL +435,17031,COOK,IL +436,17031,COOK,IL +437,17031,COOK,IL +438,17031,COOK,IL +439,17031,COOK,IL +440,17031,COOK,IL +441,17031,COOK,IL +442,17031,COOK,IL +443,17031,COOK,IL +444,17031,COOK,IL +445,17031,COOK,IL +446,17031,COOK,IL +447,17031,COOK,IL +448,17031,COOK,IL +449,17031,COOK,IL +450,17031,COOK,IL +451,17031,COOK,IL +452,17031,COOK,IL +453,17031,COOK,IL +454,17031,COOK,IL +455,17031,COOK,IL +456,17031,COOK,IL +457,17031,COOK,IL +458,17031,COOK,IL +459,17031,COOK,IL +460,17031,COOK,IL +461,17031,COOK,IL +462,17031,COOK,IL +463,17031,COOK,IL +464,17031,COOK,IL +465,17031,COOK,IL +466,17031,COOK,IL +467,17031,COOK,IL +468,17031,COOK,IL +469,17031,COOK,IL +470,17031,COOK,IL +471,17031,COOK,IL +472,17031,COOK,IL +473,17031,COOK,IL +474,17031,COOK,IL +475,17031,COOK,IL +476,17031,COOK,IL +477,17031,COOK,IL +478,17031,COOK,IL +479,17031,COOK,IL +480,17031,COOK,IL +481,17031,COOK,IL +482,17031,COOK,IL +483,17031,COOK,IL +484,17031,COOK,IL +485,17031,COOK,IL +486,17031,COOK,IL +487,17031,COOK,IL +488,17031,COOK,IL +489,17031,COOK,IL +490,17031,COOK,IL +491,17031,COOK,IL +492,17031,COOK,IL +493,17031,COOK,IL +494,17031,COOK,IL +495,17031,COOK,IL +496,17031,COOK,IL +497,17031,COOK,IL +498,17031,COOK,IL +499,17031,COOK,IL +500,17031,COOK,IL +501,17031,COOK,IL +502,17031,COOK,IL +503,17031,COOK,IL +504,17031,COOK,IL +505,17031,COOK,IL +506,17031,COOK,IL +507,17031,COOK,IL +508,17031,COOK,IL +509,17031,COOK,IL +510,17031,COOK,IL +511,17031,COOK,IL +512,17031,COOK,IL +513,17031,COOK,IL +514,17031,COOK,IL +515,17031,COOK,IL +516,17031,COOK,IL +517,17031,COOK,IL +518,17031,COOK,IL +519,17031,COOK,IL +520,17031,COOK,IL +521,17031,COOK,IL +522,17031,COOK,IL +523,17031,COOK,IL +524,17031,COOK,IL +525,17031,COOK,IL +526,17031,COOK,IL +527,17031,COOK,IL +528,17031,COOK,IL +529,17031,COOK,IL +530,17031,COOK,IL +531,17031,COOK,IL +532,17031,COOK,IL +533,17031,COOK,IL +534,17031,COOK,IL +535,17031,COOK,IL +536,17031,COOK,IL +537,17031,COOK,IL +538,17031,COOK,IL +539,17031,COOK,IL +540,17031,COOK,IL +541,17031,COOK,IL +542,17031,COOK,IL +543,17031,COOK,IL +544,17031,COOK,IL +545,17031,COOK,IL +546,17031,COOK,IL +547,17031,COOK,IL +548,17031,COOK,IL +549,17031,COOK,IL +550,17031,COOK,IL +551,17031,COOK,IL +552,17031,COOK,IL +553,17031,COOK,IL +554,17031,COOK,IL +555,17031,COOK,IL +556,17031,COOK,IL +557,17031,COOK,IL +558,17031,COOK,IL +559,17031,COOK,IL +560,17031,COOK,IL +561,17031,COOK,IL +562,17031,COOK,IL +563,17031,COOK,IL +564,17031,COOK,IL +565,17031,COOK,IL +566,17031,COOK,IL +567,17031,COOK,IL +568,17031,COOK,IL +569,17031,COOK,IL +570,17031,COOK,IL +571,17031,COOK,IL +572,17031,COOK,IL +573,17031,COOK,IL +574,17031,COOK,IL +575,17031,COOK,IL +576,17031,COOK,IL +577,17031,COOK,IL +578,17031,COOK,IL +579,17031,COOK,IL +580,17031,COOK,IL +581,17031,COOK,IL +582,17031,COOK,IL +583,17031,COOK,IL +584,17031,COOK,IL +585,17031,COOK,IL +586,17031,COOK,IL +587,17031,COOK,IL +588,17031,COOK,IL +589,17031,COOK,IL +590,17031,COOK,IL +591,17031,COOK,IL +592,17031,COOK,IL +593,17031,COOK,IL +594,17031,COOK,IL +595,17031,COOK,IL +596,17031,COOK,IL +597,17031,COOK,IL +598,17031,COOK,IL +599,17031,COOK,IL +600,17031,COOK,IL +601,17031,COOK,IL +602,17031,COOK,IL +603,17031,COOK,IL +604,17031,COOK,IL +605,17031,COOK,IL +606,17031,COOK,IL +607,17031,COOK,IL +608,17031,COOK,IL +609,17031,COOK,IL +610,17031,COOK,IL +611,17031,COOK,IL +612,17031,COOK,IL +613,17031,COOK,IL +614,17031,COOK,IL +615,17031,COOK,IL +616,17031,COOK,IL +617,17031,COOK,IL +618,17031,COOK,IL +619,17031,COOK,IL +620,17031,COOK,IL +621,17031,COOK,IL +622,17031,COOK,IL +623,17031,COOK,IL +624,17031,COOK,IL +625,17031,COOK,IL +626,17031,COOK,IL +627,17031,COOK,IL +628,17031,COOK,IL +629,17031,COOK,IL +630,17031,COOK,IL +631,17031,COOK,IL +632,17031,COOK,IL +633,17031,COOK,IL +634,17031,COOK,IL +635,17031,COOK,IL +636,17031,COOK,IL +637,17031,COOK,IL +638,17031,COOK,IL +639,17031,COOK,IL +640,17031,COOK,IL +641,17031,COOK,IL +642,17031,COOK,IL +643,17031,COOK,IL +644,17031,COOK,IL +645,17031,COOK,IL +646,17031,COOK,IL +647,17031,COOK,IL +648,17031,COOK,IL +649,17031,COOK,IL +650,17031,COOK,IL +651,17031,COOK,IL +652,17031,COOK,IL +653,17031,COOK,IL +654,17031,COOK,IL +655,17031,COOK,IL +656,17031,COOK,IL +657,17031,COOK,IL +658,17031,COOK,IL +659,17031,COOK,IL +660,17031,COOK,IL +661,17031,COOK,IL +662,17031,COOK,IL +663,17031,COOK,IL +664,17031,COOK,IL +665,17031,COOK,IL +666,17031,COOK,IL +667,17031,COOK,IL +668,17031,COOK,IL +669,17031,COOK,IL +670,17031,COOK,IL +671,17031,COOK,IL +672,17031,COOK,IL +673,17031,COOK,IL +674,17031,COOK,IL +675,17031,COOK,IL +676,17031,COOK,IL +677,17031,COOK,IL +678,17031,COOK,IL +679,17031,COOK,IL +680,17031,COOK,IL +681,17031,COOK,IL +682,17031,COOK,IL +683,17031,COOK,IL +684,17031,COOK,IL +685,17031,COOK,IL +686,17031,COOK,IL +687,17031,COOK,IL +688,17031,COOK,IL +689,17031,COOK,IL +690,17031,COOK,IL +691,17031,COOK,IL +692,17031,COOK,IL +693,17031,COOK,IL +694,17031,COOK,IL +695,17031,COOK,IL +696,17031,COOK,IL +697,17031,COOK,IL +698,17031,COOK,IL +699,17031,COOK,IL +700,17031,COOK,IL +701,17031,COOK,IL +702,17031,COOK,IL +703,17031,COOK,IL +704,17031,COOK,IL +705,17031,COOK,IL +706,17031,COOK,IL +707,17031,COOK,IL +708,17031,COOK,IL +709,17031,COOK,IL +710,17031,COOK,IL +711,17031,COOK,IL +712,17031,COOK,IL +713,17031,COOK,IL +714,17031,COOK,IL +715,17031,COOK,IL +716,17031,COOK,IL +717,17031,COOK,IL +718,17031,COOK,IL +719,17031,COOK,IL +720,17031,COOK,IL +721,17031,COOK,IL +722,17031,COOK,IL +723,17031,COOK,IL +724,17031,COOK,IL +725,17031,COOK,IL +726,17031,COOK,IL +727,17031,COOK,IL +728,17031,COOK,IL +729,17031,COOK,IL +730,17031,COOK,IL +731,17031,COOK,IL +732,17031,COOK,IL +733,17031,COOK,IL +734,17031,COOK,IL +735,17031,COOK,IL +736,17031,COOK,IL +737,17031,COOK,IL +738,17031,COOK,IL +739,17031,COOK,IL +740,17031,COOK,IL +741,17031,COOK,IL +742,17031,COOK,IL +743,17031,COOK,IL +744,17031,COOK,IL +745,17031,COOK,IL +746,17031,COOK,IL +747,17031,COOK,IL +748,17031,COOK,IL +749,17031,COOK,IL +750,17031,COOK,IL +751,17031,COOK,IL +752,17031,COOK,IL +753,17031,COOK,IL +754,17031,COOK,IL +755,17031,COOK,IL +756,17031,COOK,IL +757,17031,COOK,IL +758,17031,COOK,IL +759,17031,COOK,IL +760,17031,COOK,IL +761,17031,COOK,IL +762,17031,COOK,IL +763,17031,COOK,IL +764,17031,COOK,IL +765,17031,COOK,IL +766,17031,COOK,IL +767,17031,COOK,IL +768,17031,COOK,IL +769,17031,COOK,IL +770,17031,COOK,IL +771,17031,COOK,IL +772,17031,COOK,IL +773,17031,COOK,IL +774,17031,COOK,IL +775,17031,COOK,IL +776,17031,COOK,IL +777,17031,COOK,IL +778,17031,COOK,IL +779,17031,COOK,IL +780,17031,COOK,IL +781,17031,COOK,IL +782,17031,COOK,IL +783,17031,COOK,IL +784,17031,COOK,IL +785,17031,COOK,IL +786,17031,COOK,IL +787,17031,COOK,IL +788,17031,COOK,IL +789,17031,COOK,IL +790,17031,COOK,IL +791,17031,COOK,IL +792,17031,COOK,IL +793,17031,COOK,IL +794,17031,COOK,IL +795,17031,COOK,IL +796,17031,COOK,IL +797,17031,COOK,IL +798,17031,COOK,IL +799,17031,COOK,IL +800,17031,COOK,IL +801,17031,COOK,IL +802,17031,COOK,IL +803,17031,COOK,IL +804,17031,COOK,IL +805,17031,COOK,IL +806,17031,COOK,IL +807,17031,COOK,IL +808,17031,COOK,IL +809,17031,COOK,IL +810,17031,COOK,IL +811,17031,COOK,IL +812,17031,COOK,IL +813,17031,COOK,IL +814,17031,COOK,IL +815,17031,COOK,IL +816,17031,COOK,IL +817,17031,COOK,IL +818,17031,COOK,IL +819,17031,COOK,IL +820,17031,COOK,IL +821,17031,COOK,IL +822,17031,COOK,IL +823,17031,COOK,IL +824,17031,COOK,IL +825,17031,COOK,IL +826,17031,COOK,IL +827,17031,COOK,IL +828,17031,COOK,IL +829,17031,COOK,IL +830,17031,COOK,IL +831,17031,COOK,IL +832,17031,COOK,IL +833,17031,COOK,IL +834,17031,COOK,IL +835,17031,COOK,IL +836,17031,COOK,IL +837,17031,COOK,IL +838,17031,COOK,IL +839,17031,COOK,IL +840,17031,COOK,IL +841,17031,COOK,IL +842,17031,COOK,IL +843,17031,COOK,IL +844,17031,COOK,IL +845,17031,COOK,IL +846,17031,COOK,IL +847,17031,COOK,IL +848,17031,COOK,IL +849,17031,COOK,IL +850,17031,COOK,IL +851,17031,COOK,IL +852,17031,COOK,IL +853,17031,COOK,IL +854,17031,COOK,IL +855,17031,COOK,IL +856,17031,COOK,IL +857,17031,COOK,IL +858,17031,COOK,IL +859,17031,COOK,IL +860,17031,COOK,IL +861,17031,COOK,IL +862,17031,COOK,IL +863,17031,COOK,IL +864,17031,COOK,IL +865,17031,COOK,IL +866,17031,COOK,IL +867,17031,COOK,IL +868,17031,COOK,IL +869,17031,COOK,IL +870,17031,COOK,IL +871,17031,COOK,IL +872,17031,COOK,IL +873,17031,COOK,IL +874,17031,COOK,IL +875,17031,COOK,IL +876,17031,COOK,IL +877,17031,COOK,IL +878,17031,COOK,IL +879,17031,COOK,IL +880,17031,COOK,IL +881,17031,COOK,IL +882,17031,COOK,IL +883,17031,COOK,IL +884,17031,COOK,IL +885,17031,COOK,IL +886,17031,COOK,IL +887,17031,COOK,IL +888,17031,COOK,IL +889,17031,COOK,IL +890,17031,COOK,IL +891,17031,COOK,IL +892,17031,COOK,IL +893,17031,COOK,IL +894,17031,COOK,IL +895,17031,COOK,IL +896,17031,COOK,IL +897,17031,COOK,IL +898,17031,COOK,IL +899,17031,COOK,IL +900,17031,COOK,IL +901,17031,COOK,IL +902,17031,COOK,IL +903,17031,COOK,IL +904,17031,COOK,IL +905,17031,COOK,IL +906,17031,COOK,IL +907,17031,COOK,IL +908,17031,COOK,IL +909,17031,COOK,IL +910,17031,COOK,IL +911,17031,COOK,IL +912,17031,COOK,IL +913,17031,COOK,IL +914,17031,COOK,IL +915,17031,COOK,IL +916,17031,COOK,IL +917,17031,COOK,IL +918,17031,COOK,IL +919,17031,COOK,IL +920,17031,COOK,IL +921,17031,COOK,IL +922,17031,COOK,IL +923,17031,COOK,IL +924,17031,COOK,IL +925,17031,COOK,IL +926,17031,COOK,IL +927,17031,COOK,IL +928,17031,COOK,IL +929,17031,COOK,IL +930,17031,COOK,IL +931,17031,COOK,IL +932,17031,COOK,IL +933,17031,COOK,IL +934,17031,COOK,IL +935,17031,COOK,IL +936,17031,COOK,IL +937,17031,COOK,IL +938,17031,COOK,IL +939,17031,COOK,IL +940,17031,COOK,IL +941,17031,COOK,IL +942,17031,COOK,IL +943,17031,COOK,IL +944,17031,COOK,IL +945,17031,COOK,IL +946,17031,COOK,IL +947,17031,COOK,IL +948,17031,COOK,IL +949,17031,COOK,IL +950,17031,COOK,IL +951,17031,COOK,IL +952,17031,COOK,IL +953,17031,COOK,IL +954,17031,COOK,IL +955,17031,COOK,IL +956,17031,COOK,IL +957,17031,COOK,IL +958,17031,COOK,IL +959,17031,COOK,IL +960,17031,COOK,IL +961,17031,COOK,IL +962,17031,COOK,IL +963,17031,COOK,IL +964,17031,COOK,IL +965,17031,COOK,IL +966,17031,COOK,IL +967,17031,COOK,IL +968,17031,COOK,IL +969,17031,COOK,IL +970,17031,COOK,IL +971,17031,COOK,IL +972,17031,COOK,IL +973,17031,COOK,IL +974,17031,COOK,IL +975,17031,COOK,IL +976,17031,COOK,IL +977,17031,COOK,IL +978,17031,COOK,IL +979,17031,COOK,IL +980,17031,COOK,IL +981,17031,COOK,IL +982,17031,COOK,IL +983,17031,COOK,IL +984,17031,COOK,IL +985,17031,COOK,IL +986,17031,COOK,IL +987,17031,COOK,IL +988,17031,COOK,IL +989,17031,COOK,IL +990,17031,COOK,IL +991,17031,COOK,IL +992,17031,COOK,IL +993,17031,COOK,IL +994,17031,COOK,IL +995,17031,COOK,IL +996,17031,COOK,IL +997,17031,COOK,IL +998,17031,COOK,IL +999,17031,COOK,IL +1000,17031,COOK,IL +1001,17031,COOK,IL +1002,17031,COOK,IL +1003,17031,COOK,IL +1004,17031,COOK,IL +1005,17031,COOK,IL +1006,17031,COOK,IL +1007,17031,COOK,IL +1008,17031,COOK,IL +1009,17031,COOK,IL +1010,17031,COOK,IL +1011,17031,COOK,IL +1012,17031,COOK,IL +1013,17031,COOK,IL +1014,17031,COOK,IL +1015,17031,COOK,IL +1016,17031,COOK,IL +1017,17031,COOK,IL +1018,17031,COOK,IL +1019,17031,COOK,IL +1020,17031,COOK,IL +1021,17031,COOK,IL +1022,17031,COOK,IL +1023,17031,COOK,IL +1024,17031,COOK,IL +1025,17031,COOK,IL +1026,17031,COOK,IL +1027,17031,COOK,IL +1028,17031,COOK,IL +1029,17031,COOK,IL +1030,17031,COOK,IL +1031,17031,COOK,IL +1032,17031,COOK,IL +1033,17031,COOK,IL +1034,17031,COOK,IL +1035,17031,COOK,IL +1036,17031,COOK,IL +1037,17031,COOK,IL +1038,17031,COOK,IL +1039,17031,COOK,IL +1040,17031,COOK,IL +1041,17031,COOK,IL +1042,17031,COOK,IL +1043,17031,COOK,IL +1044,17031,COOK,IL +1045,17031,COOK,IL +1046,17031,COOK,IL +1047,17031,COOK,IL +1048,17031,COOK,IL +1049,17031,COOK,IL +1050,17031,COOK,IL +1051,17031,COOK,IL +1052,17031,COOK,IL +1053,17031,COOK,IL +1054,17031,COOK,IL +1055,17031,COOK,IL +1056,17031,COOK,IL +1057,17031,COOK,IL +1058,17031,COOK,IL +1059,17031,COOK,IL +1060,17031,COOK,IL +1061,17031,COOK,IL +1062,17031,COOK,IL +1063,17031,COOK,IL +1064,17031,COOK,IL +1065,17031,COOK,IL +1066,17031,COOK,IL +1067,17031,COOK,IL +1068,17031,COOK,IL +1069,17031,COOK,IL +1070,17031,COOK,IL +1071,17031,COOK,IL +1072,17031,COOK,IL +1073,17031,COOK,IL +1074,17031,COOK,IL +1075,17031,COOK,IL +1076,17031,COOK,IL +1077,17031,COOK,IL +1078,17031,COOK,IL +1079,17031,COOK,IL +1080,17031,COOK,IL +1081,17031,COOK,IL +1082,17031,COOK,IL +1083,17031,COOK,IL +1084,17031,COOK,IL +1085,17031,COOK,IL +1086,17031,COOK,IL +1087,17031,COOK,IL +1088,17031,COOK,IL +1089,17031,COOK,IL +1090,17031,COOK,IL +1091,17031,COOK,IL +1092,17031,COOK,IL +1093,17031,COOK,IL +1094,17031,COOK,IL +1095,17031,COOK,IL +1096,17031,COOK,IL +1097,17031,COOK,IL +1098,17031,COOK,IL +1099,17031,COOK,IL +1100,17031,COOK,IL +1101,17031,COOK,IL +1102,17031,COOK,IL +1103,17031,COOK,IL +1104,17031,COOK,IL +1105,17031,COOK,IL +1106,17031,COOK,IL +1107,17031,COOK,IL +1108,17031,COOK,IL +1109,17031,COOK,IL +1110,17031,COOK,IL +1111,17031,COOK,IL +1112,17031,COOK,IL +1113,17031,COOK,IL +1114,17031,COOK,IL +1115,17031,COOK,IL +1116,17031,COOK,IL +1117,17031,COOK,IL +1118,17031,COOK,IL +1119,17031,COOK,IL +1120,17031,COOK,IL +1121,17031,COOK,IL +1122,17031,COOK,IL +1123,17031,COOK,IL +1124,17031,COOK,IL +1125,17031,COOK,IL +1126,17031,COOK,IL +1127,17031,COOK,IL +1128,17031,COOK,IL +1129,17031,COOK,IL +1130,17031,COOK,IL +1131,17031,COOK,IL +1132,17031,COOK,IL +1133,17031,COOK,IL +1134,17031,COOK,IL +1135,17031,COOK,IL +1136,17031,COOK,IL +1137,17031,COOK,IL +1138,17031,COOK,IL +1139,17031,COOK,IL +1140,17031,COOK,IL +1141,17031,COOK,IL +1142,17031,COOK,IL +1143,17031,COOK,IL +1144,17031,COOK,IL +1145,17031,COOK,IL +1146,17031,COOK,IL +1147,17031,COOK,IL +1148,17031,COOK,IL +1149,17031,COOK,IL +1150,17031,COOK,IL +1151,17031,COOK,IL +1152,17031,COOK,IL +1153,17031,COOK,IL +1154,17031,COOK,IL +1155,17031,COOK,IL +1156,17031,COOK,IL +1157,17031,COOK,IL +1158,17031,COOK,IL +1159,17031,COOK,IL +1161,17031,COOK,IL +1162,17031,COOK,IL +1163,17031,COOK,IL +1164,17031,COOK,IL +1165,17031,COOK,IL +1166,17031,COOK,IL +1167,17031,COOK,IL +1168,17031,COOK,IL +1169,17031,COOK,IL +1170,17031,COOK,IL +1171,17031,COOK,IL +1172,17031,COOK,IL +1173,17031,COOK,IL +1174,17031,COOK,IL +1175,17031,COOK,IL +1176,17031,COOK,IL +1177,17031,COOK,IL +1178,17031,COOK,IL +1179,17031,COOK,IL +1180,17031,COOK,IL +1181,17031,COOK,IL +1182,17031,COOK,IL +1183,17031,COOK,IL +1184,17031,COOK,IL +1185,17031,COOK,IL +1186,17031,COOK,IL +1187,17031,COOK,IL +1188,17031,COOK,IL +1189,17031,COOK,IL +1190,17031,COOK,IL +1191,17031,COOK,IL +1192,17031,COOK,IL +1193,17031,COOK,IL +1194,17031,COOK,IL +1195,17031,COOK,IL +1196,17031,COOK,IL +1197,17031,COOK,IL +1198,17031,COOK,IL +1199,17031,COOK,IL +1200,17031,COOK,IL +1201,17031,COOK,IL +1202,17031,COOK,IL +1203,17031,COOK,IL +1204,17031,COOK,IL +1205,17031,COOK,IL +1206,17031,COOK,IL +1207,17031,COOK,IL +1208,17031,COOK,IL +1209,17031,COOK,IL +1210,17031,COOK,IL +1211,17031,COOK,IL +1212,17031,COOK,IL +1213,17031,COOK,IL +1214,17031,COOK,IL +1215,17031,COOK,IL +1216,17031,COOK,IL +1217,17031,COOK,IL +1218,17031,COOK,IL +1219,17031,COOK,IL +1220,17031,COOK,IL +1221,17031,COOK,IL +1222,17031,COOK,IL +1223,17031,COOK,IL +1224,17031,COOK,IL +1225,17031,COOK,IL +1226,17031,COOK,IL +1227,17031,COOK,IL +1228,17031,COOK,IL +1229,17031,COOK,IL +1230,17031,COOK,IL +1231,17031,COOK,IL +1232,17031,COOK,IL +1233,17031,COOK,IL +1234,17031,COOK,IL +1235,17031,COOK,IL +1236,17031,COOK,IL +1237,17031,COOK,IL +1238,17031,COOK,IL +1239,17031,COOK,IL +1240,17031,COOK,IL +1241,17031,COOK,IL +1242,17031,COOK,IL +1243,17031,COOK,IL +1244,17031,COOK,IL +1245,17031,COOK,IL +1246,17031,COOK,IL +1247,17031,COOK,IL +1248,17031,COOK,IL +1249,17031,COOK,IL +1250,17031,COOK,IL +1251,17031,COOK,IL +1252,17031,COOK,IL +1253,17031,COOK,IL +1254,17031,COOK,IL +1255,17031,COOK,IL +1256,17031,COOK,IL +1257,17031,COOK,IL +1258,17031,COOK,IL +1259,17031,COOK,IL +1260,17031,COOK,IL +1261,17031,COOK,IL +1262,17031,COOK,IL +1263,17031,COOK,IL +1264,17031,COOK,IL +1265,17031,COOK,IL +1266,17031,COOK,IL +1267,17031,COOK,IL +1268,17031,COOK,IL +1269,17031,COOK,IL +1270,17031,COOK,IL +1271,17031,COOK,IL +1272,17031,COOK,IL +1273,17031,COOK,IL +1274,17031,COOK,IL +1275,17031,COOK,IL +1276,17031,COOK,IL +1277,17031,COOK,IL +1278,17031,COOK,IL +1279,17031,COOK,IL +1280,17031,COOK,IL +1281,17031,COOK,IL +1282,17031,COOK,IL +1283,17031,COOK,IL +1284,17031,COOK,IL +1285,17031,COOK,IL +1286,17031,COOK,IL +1287,17031,COOK,IL +1288,17031,COOK,IL +1289,17031,COOK,IL +1290,17031,COOK,IL +1291,17031,COOK,IL +1292,17031,COOK,IL +1293,17031,COOK,IL +1294,17031,COOK,IL +1295,17031,COOK,IL +1296,17031,COOK,IL +1297,17031,COOK,IL +1298,17031,COOK,IL +1299,17031,COOK,IL +1300,17031,COOK,IL +1301,17031,COOK,IL +1302,17031,COOK,IL +1303,17031,COOK,IL +1304,17031,COOK,IL +1305,17031,COOK,IL +1306,17031,COOK,IL +1307,17031,COOK,IL +1308,17031,COOK,IL +1309,17031,COOK,IL +1310,17031,COOK,IL +1311,17031,COOK,IL +1312,17031,COOK,IL +1313,17031,COOK,IL +1314,17031,COOK,IL +1315,17031,COOK,IL +1316,17031,COOK,IL +1317,17031,COOK,IL +1318,17031,COOK,IL +1319,17031,COOK,IL +1320,17031,COOK,IL +1321,17031,COOK,IL +1322,17031,COOK,IL +1323,17031,COOK,IL +1324,17031,COOK,IL +1325,17031,COOK,IL +1326,17031,COOK,IL +1327,17031,COOK,IL +1328,17031,COOK,IL +1329,17031,COOK,IL +1330,17031,COOK,IL +1331,17031,COOK,IL +1332,17031,COOK,IL +1333,17031,COOK,IL +1334,17031,COOK,IL +1335,17031,COOK,IL +1336,17031,COOK,IL +1337,17031,COOK,IL +1338,17031,COOK,IL +1339,17031,COOK,IL +1340,17031,COOK,IL +1341,17031,COOK,IL +1342,17031,COOK,IL +1343,17031,COOK,IL +1344,17031,COOK,IL +1345,17031,COOK,IL +1346,17031,COOK,IL +1347,17031,COOK,IL +1348,17031,COOK,IL +1349,17031,COOK,IL +1350,17031,COOK,IL +1351,17031,COOK,IL +1352,17031,COOK,IL +1353,17031,COOK,IL +1354,17031,COOK,IL +1355,17031,COOK,IL +1356,17031,COOK,IL +1357,17031,COOK,IL +1358,17031,COOK,IL +1359,17031,COOK,IL +1360,17031,COOK,IL +1361,17031,COOK,IL +1362,17031,COOK,IL +1363,17031,COOK,IL +1364,17031,COOK,IL +1365,17031,COOK,IL +1366,17031,COOK,IL +1367,17031,COOK,IL +1368,17031,COOK,IL +1369,17031,COOK,IL +1370,17031,COOK,IL +1371,17031,COOK,IL +1372,17031,COOK,IL +1373,17031,COOK,IL +1374,17031,COOK,IL +1375,17031,COOK,IL +1376,17031,COOK,IL +1377,17031,COOK,IL +1378,17031,COOK,IL +1379,17031,COOK,IL +1380,17031,COOK,IL +1381,17031,COOK,IL +1382,17031,COOK,IL +1383,17031,COOK,IL +1384,17031,COOK,IL +1385,17031,COOK,IL +1386,17031,COOK,IL +1387,17031,COOK,IL +1388,17031,COOK,IL +1389,17031,COOK,IL +1390,17031,COOK,IL +1391,17031,COOK,IL +1392,17031,COOK,IL +1393,17031,COOK,IL +1394,17031,COOK,IL +1395,17031,COOK,IL +1396,17031,COOK,IL +1397,17031,COOK,IL +1398,17031,COOK,IL +1399,17031,COOK,IL +1400,17031,COOK,IL +1401,17031,COOK,IL +1402,17031,COOK,IL +1403,17031,COOK,IL +1404,17031,COOK,IL +1405,17031,COOK,IL +1406,17031,COOK,IL +1407,17031,COOK,IL +1408,17031,COOK,IL +1409,17031,COOK,IL +1410,17031,COOK,IL +1411,17031,COOK,IL +1412,17031,COOK,IL +1413,17031,COOK,IL +1414,17031,COOK,IL +1415,17031,COOK,IL +1416,17031,COOK,IL +1417,17031,COOK,IL +1418,17031,COOK,IL +1419,17031,COOK,IL +1420,17031,COOK,IL +1421,17031,COOK,IL +1422,17031,COOK,IL +1423,17031,COOK,IL +1424,17031,COOK,IL +1425,17031,COOK,IL +1426,17031,COOK,IL +1427,17031,COOK,IL +1428,17031,COOK,IL +1429,17031,COOK,IL +1430,17031,COOK,IL +1431,17031,COOK,IL +1432,17031,COOK,IL +1433,17031,COOK,IL +1434,17031,COOK,IL +1435,17031,COOK,IL +1436,17031,COOK,IL +1437,17031,COOK,IL +1438,17031,COOK,IL +1439,17031,COOK,IL +1440,17031,COOK,IL +1441,17031,COOK,IL +1442,17031,COOK,IL +1443,17031,COOK,IL +1444,17031,COOK,IL +1445,17031,COOK,IL +1446,17031,COOK,IL +1447,17031,COOK,IL +1448,17031,COOK,IL +1449,17031,COOK,IL +1450,17031,COOK,IL +1451,17031,COOK,IL +1452,17031,COOK,IL +1453,17031,COOK,IL +1454,17031,COOK,IL +1455,17031,COOK,IL +1456,17031,COOK,IL +1457,17031,COOK,IL +1458,17031,COOK,IL +1459,17031,COOK,IL +1460,17031,COOK,IL +1461,17031,COOK,IL +1462,17031,COOK,IL +1463,17031,COOK,IL +1464,17031,COOK,IL +1465,17031,COOK,IL +1466,17031,COOK,IL +1467,17031,COOK,IL +1468,17031,COOK,IL +1469,17031,COOK,IL +1470,17031,COOK,IL +1471,17031,COOK,IL +1472,17031,COOK,IL +1473,17031,COOK,IL +1474,17031,COOK,IL +1475,17031,COOK,IL +1476,17031,COOK,IL +1477,17031,COOK,IL +1478,17031,COOK,IL +1479,17031,COOK,IL +1480,17031,COOK,IL +1481,17031,COOK,IL +1482,17031,COOK,IL +1483,17031,COOK,IL +1484,17031,COOK,IL +1485,17031,COOK,IL +1486,17031,COOK,IL +1487,17031,COOK,IL +1488,17031,COOK,IL +1489,17031,COOK,IL +1490,17031,COOK,IL +1491,17031,COOK,IL +1492,17031,COOK,IL +1493,17031,COOK,IL +1494,17031,COOK,IL +1495,17031,COOK,IL +1496,17031,COOK,IL +1497,17031,COOK,IL +1498,17031,COOK,IL +1499,17031,COOK,IL +1500,17031,COOK,IL +1501,17031,COOK,IL +1502,17031,COOK,IL +1503,17031,COOK,IL +1504,17031,COOK,IL +1505,17031,COOK,IL +1506,17031,COOK,IL +1507,17031,COOK,IL +1508,17031,COOK,IL +1509,17031,COOK,IL +1510,17031,COOK,IL +1511,17031,COOK,IL +1512,17031,COOK,IL +1513,17031,COOK,IL +1514,17031,COOK,IL +1515,17031,COOK,IL +1516,17031,COOK,IL +1517,17031,COOK,IL +1518,17031,COOK,IL +1519,17031,COOK,IL +1520,17031,COOK,IL +1521,17031,COOK,IL +1522,17031,COOK,IL +1523,17031,COOK,IL +1524,17031,COOK,IL +1525,17031,COOK,IL +1526,17031,COOK,IL +1527,17031,COOK,IL +1528,17031,COOK,IL +1529,17031,COOK,IL +1530,17031,COOK,IL +1531,17031,COOK,IL +1532,17031,COOK,IL +1533,17031,COOK,IL +1534,17031,COOK,IL +1535,17031,COOK,IL +1536,17031,COOK,IL +1537,17031,COOK,IL +1538,17031,COOK,IL +1539,17031,COOK,IL +1540,17031,COOK,IL +1541,17031,COOK,IL +1542,17031,COOK,IL +1543,17031,COOK,IL +1544,17031,COOK,IL +1545,17031,COOK,IL +1546,17031,COOK,IL +1547,17031,COOK,IL +1548,17031,COOK,IL +1549,17031,COOK,IL +1550,17031,COOK,IL +1551,17031,COOK,IL +1552,17031,COOK,IL +1553,17031,COOK,IL +1554,17031,COOK,IL +1555,17031,COOK,IL +1556,17031,COOK,IL +1557,17031,COOK,IL +1558,17031,COOK,IL +1559,17031,COOK,IL +1560,17031,COOK,IL +1561,17031,COOK,IL +1562,17031,COOK,IL +1563,17031,COOK,IL +1564,17031,COOK,IL +1565,17031,COOK,IL +1566,17031,COOK,IL +1567,17031,COOK,IL +1568,17031,COOK,IL +1569,17031,COOK,IL +1570,17031,COOK,IL +1571,17031,COOK,IL +1572,17031,COOK,IL +1573,17031,COOK,IL +1574,17031,COOK,IL +1575,17031,COOK,IL +1576,17031,COOK,IL +1577,17031,COOK,IL +1578,17031,COOK,IL +1579,17031,COOK,IL +1580,17031,COOK,IL +1581,17031,COOK,IL +1582,17031,COOK,IL +1583,17031,COOK,IL +1584,17031,COOK,IL +1585,17031,COOK,IL +1586,17031,COOK,IL +1587,17031,COOK,IL +1588,17031,COOK,IL +1589,17031,COOK,IL +1590,17031,COOK,IL +1591,17031,COOK,IL +1592,17031,COOK,IL +1593,17031,COOK,IL +1594,17031,COOK,IL +1595,17031,COOK,IL +1596,17031,COOK,IL +1597,17031,COOK,IL +1598,17031,COOK,IL +1599,17031,COOK,IL +1600,17031,COOK,IL +1601,17031,COOK,IL +1602,17031,COOK,IL +1603,17031,COOK,IL +1604,17031,COOK,IL +1605,17031,COOK,IL +1606,17031,COOK,IL +1607,17031,COOK,IL +1608,17031,COOK,IL +1609,17031,COOK,IL +1610,17031,COOK,IL +1611,17031,COOK,IL +1612,17031,COOK,IL +1613,17031,COOK,IL +1614,17031,COOK,IL +1615,17031,COOK,IL +1616,17031,COOK,IL +1617,17031,COOK,IL +1618,17031,COOK,IL +1619,17031,COOK,IL +1620,17031,COOK,IL +1621,17031,COOK,IL +1622,17031,COOK,IL +1623,17031,COOK,IL +1624,17031,COOK,IL +1625,17031,COOK,IL +1626,17031,COOK,IL +1627,17031,COOK,IL +1628,17031,COOK,IL +1629,17031,COOK,IL +1630,17031,COOK,IL +1631,17031,COOK,IL +1632,17031,COOK,IL +1633,17031,COOK,IL +1634,17031,COOK,IL +1635,17031,COOK,IL +1636,17031,COOK,IL +1637,17031,COOK,IL +1638,17031,COOK,IL +1639,17031,COOK,IL +1640,17031,COOK,IL +1641,17031,COOK,IL +1642,17031,COOK,IL +1643,17031,COOK,IL +1644,17031,COOK,IL +1645,17031,COOK,IL +1646,17031,COOK,IL +1647,17031,COOK,IL +1648,17031,COOK,IL +1649,17031,COOK,IL +1650,17031,COOK,IL +1651,17031,COOK,IL +1652,17031,COOK,IL +1653,17031,COOK,IL +1654,17031,COOK,IL +1655,17031,COOK,IL +1656,17031,COOK,IL +1657,17031,COOK,IL +1658,17031,COOK,IL +1659,17031,COOK,IL +1660,17031,COOK,IL +1661,17031,COOK,IL +1662,17031,COOK,IL +1663,17031,COOK,IL +1664,17031,COOK,IL +1665,17031,COOK,IL +1666,17031,COOK,IL +1667,17031,COOK,IL +1668,17031,COOK,IL +1669,17031,COOK,IL +1670,17031,COOK,IL +1671,17031,COOK,IL +1672,17031,COOK,IL +1673,17031,COOK,IL +1674,17031,COOK,IL +1675,17031,COOK,IL +1676,17031,COOK,IL +1677,17031,COOK,IL +1678,17031,COOK,IL +1679,17031,COOK,IL +1680,17031,COOK,IL +1681,17031,COOK,IL +1682,17031,COOK,IL +1683,17031,COOK,IL +1684,17031,COOK,IL +1685,17031,COOK,IL +1686,17031,COOK,IL +1687,17031,COOK,IL +1688,17031,COOK,IL +1689,17031,COOK,IL +1690,17031,COOK,IL +1691,17031,COOK,IL +1692,17031,COOK,IL +1693,17031,COOK,IL +1694,17031,COOK,IL +1695,17031,COOK,IL +1696,17031,COOK,IL +1697,17031,COOK,IL +1698,17031,COOK,IL +1699,17031,COOK,IL +1700,17031,COOK,IL +1701,17031,COOK,IL +1702,17031,COOK,IL +1703,17031,COOK,IL +1704,17031,COOK,IL +1705,17031,COOK,IL +1706,17031,COOK,IL +1707,17031,COOK,IL +1708,17031,COOK,IL +1709,17031,COOK,IL +1710,17031,COOK,IL +1711,17031,COOK,IL +1712,17031,COOK,IL +1713,17031,COOK,IL +1714,17031,COOK,IL +1715,17031,COOK,IL +1716,17031,COOK,IL +1717,17031,COOK,IL +1718,17031,COOK,IL +1719,17031,COOK,IL +1720,17031,COOK,IL +1721,17031,COOK,IL +1722,17031,COOK,IL +1723,17031,COOK,IL +1724,17031,COOK,IL +1725,17031,COOK,IL +1726,17031,COOK,IL +1727,17031,COOK,IL +1728,17031,COOK,IL +1729,17031,COOK,IL +1730,17031,COOK,IL +1731,17031,COOK,IL +1732,17031,COOK,IL +1733,17043,DUPAGE,IL +1734,17043,DUPAGE,IL +1735,17043,DUPAGE,IL +1736,17043,DUPAGE,IL +1737,17043,DUPAGE,IL +1738,17043,DUPAGE,IL +1739,17043,DUPAGE,IL +1740,17043,DUPAGE,IL +1741,17043,DUPAGE,IL +1742,17043,DUPAGE,IL +1743,17043,DUPAGE,IL +1744,17043,DUPAGE,IL +1745,17043,DUPAGE,IL +1746,17043,DUPAGE,IL +1747,17043,DUPAGE,IL +1748,17043,DUPAGE,IL +1749,17043,DUPAGE,IL +1750,17043,DUPAGE,IL +1751,17043,DUPAGE,IL +1752,17043,DUPAGE,IL +1753,17043,DUPAGE,IL +1754,17043,DUPAGE,IL +1755,17043,DUPAGE,IL +1756,17043,DUPAGE,IL +1757,17043,DUPAGE,IL +1758,17043,DUPAGE,IL +1759,17043,DUPAGE,IL +1760,17043,DUPAGE,IL +1761,17043,DUPAGE,IL +1762,17043,DUPAGE,IL +1763,17043,DUPAGE,IL +1764,17043,DUPAGE,IL +1765,17043,DUPAGE,IL +1766,17043,DUPAGE,IL +1767,17043,DUPAGE,IL +1768,17043,DUPAGE,IL +1769,17043,DUPAGE,IL +1770,17043,DUPAGE,IL +1771,17043,DUPAGE,IL +1772,17043,DUPAGE,IL +1773,17043,DUPAGE,IL +1774,17043,DUPAGE,IL +1775,17043,DUPAGE,IL +1776,17043,DUPAGE,IL +1777,17043,DUPAGE,IL +1778,17043,DUPAGE,IL +1779,17043,DUPAGE,IL +1780,17043,DUPAGE,IL +1781,17043,DUPAGE,IL +1782,17043,DUPAGE,IL +1783,17043,DUPAGE,IL +1784,17043,DUPAGE,IL +1785,17043,DUPAGE,IL +1786,17043,DUPAGE,IL +1787,17043,DUPAGE,IL +1788,17043,DUPAGE,IL +1789,17043,DUPAGE,IL +1790,17043,DUPAGE,IL +1791,17043,DUPAGE,IL +1792,17043,DUPAGE,IL +1793,17043,DUPAGE,IL +1794,17043,DUPAGE,IL +1795,17043,DUPAGE,IL +1796,17043,DUPAGE,IL +1797,17043,DUPAGE,IL +1798,17043,DUPAGE,IL +1799,17043,DUPAGE,IL +1800,17043,DUPAGE,IL +1801,17043,DUPAGE,IL +1802,17043,DUPAGE,IL +1803,17043,DUPAGE,IL +1804,17043,DUPAGE,IL +1805,17043,DUPAGE,IL +1806,17043,DUPAGE,IL +1807,17043,DUPAGE,IL +1808,17043,DUPAGE,IL +1809,17043,DUPAGE,IL +1810,17043,DUPAGE,IL +1811,17043,DUPAGE,IL +1812,17043,DUPAGE,IL +1813,17043,DUPAGE,IL +1814,17043,DUPAGE,IL +1815,17043,DUPAGE,IL +1816,17043,DUPAGE,IL +1817,17043,DUPAGE,IL +1818,17043,DUPAGE,IL +1819,17043,DUPAGE,IL +1820,17043,DUPAGE,IL +1821,17043,DUPAGE,IL +1822,17043,DUPAGE,IL +1823,17043,DUPAGE,IL +1824,17043,DUPAGE,IL +1825,17043,DUPAGE,IL +1826,17043,DUPAGE,IL +1827,17043,DUPAGE,IL +1828,17043,DUPAGE,IL +1829,17043,DUPAGE,IL +1830,17043,DUPAGE,IL +1831,17043,DUPAGE,IL +1832,17043,DUPAGE,IL +1833,17043,DUPAGE,IL +1834,17043,DUPAGE,IL +1835,17043,DUPAGE,IL +1836,17043,DUPAGE,IL +1837,17043,DUPAGE,IL +1838,17043,DUPAGE,IL +1839,17043,DUPAGE,IL +1840,17043,DUPAGE,IL +1841,17043,DUPAGE,IL +1842,17043,DUPAGE,IL +1843,17043,DUPAGE,IL +1844,17043,DUPAGE,IL +1845,17043,DUPAGE,IL +1846,17043,DUPAGE,IL +1847,17043,DUPAGE,IL +1848,17043,DUPAGE,IL +1849,17043,DUPAGE,IL +1850,17043,DUPAGE,IL +1851,17043,DUPAGE,IL +1852,17043,DUPAGE,IL +1853,17043,DUPAGE,IL +1854,17043,DUPAGE,IL +1855,17043,DUPAGE,IL +1856,17043,DUPAGE,IL +1857,17043,DUPAGE,IL +1858,17043,DUPAGE,IL +1859,17043,DUPAGE,IL +1860,17043,DUPAGE,IL +1861,17043,DUPAGE,IL +1862,17043,DUPAGE,IL +1863,17043,DUPAGE,IL +1864,17043,DUPAGE,IL +1865,17043,DUPAGE,IL +1866,17043,DUPAGE,IL +1867,17043,DUPAGE,IL +1868,17043,DUPAGE,IL +1869,17043,DUPAGE,IL +1870,17043,DUPAGE,IL +1871,17043,DUPAGE,IL +1872,17043,DUPAGE,IL +1873,17043,DUPAGE,IL +1874,17043,DUPAGE,IL +1875,17043,DUPAGE,IL +1876,17043,DUPAGE,IL +1877,17043,DUPAGE,IL +1878,17043,DUPAGE,IL +1879,17043,DUPAGE,IL +1880,17043,DUPAGE,IL +1881,17043,DUPAGE,IL +1882,17043,DUPAGE,IL +1883,17043,DUPAGE,IL +1884,17043,DUPAGE,IL +1885,17043,DUPAGE,IL +1886,17043,DUPAGE,IL +1887,17043,DUPAGE,IL +1888,17043,DUPAGE,IL +1889,17043,DUPAGE,IL +1890,17043,DUPAGE,IL +1891,17043,DUPAGE,IL +1892,17043,DUPAGE,IL +1893,17043,DUPAGE,IL +1894,17043,DUPAGE,IL +1895,17043,DUPAGE,IL +1896,17043,DUPAGE,IL +1897,17043,DUPAGE,IL +1898,17043,DUPAGE,IL +1899,17043,DUPAGE,IL +1900,17043,DUPAGE,IL +1901,17043,DUPAGE,IL +1902,17043,DUPAGE,IL +1903,17043,DUPAGE,IL +1904,17043,DUPAGE,IL +1905,17043,DUPAGE,IL +1906,17043,DUPAGE,IL +1907,17043,DUPAGE,IL +1908,17043,DUPAGE,IL +1909,17043,DUPAGE,IL +1910,17043,DUPAGE,IL +1911,17043,DUPAGE,IL +1912,17043,DUPAGE,IL +1913,17043,DUPAGE,IL +1914,17043,DUPAGE,IL +1915,17043,DUPAGE,IL +1916,17043,DUPAGE,IL +1917,17043,DUPAGE,IL +1918,17043,DUPAGE,IL +1919,17043,DUPAGE,IL +1920,17043,DUPAGE,IL +1921,17043,DUPAGE,IL +1922,17043,DUPAGE,IL +1923,17043,DUPAGE,IL +1924,17043,DUPAGE,IL +1925,17043,DUPAGE,IL +1926,17043,DUPAGE,IL +1927,17043,DUPAGE,IL +1928,17043,DUPAGE,IL +1929,17043,DUPAGE,IL +1930,17043,DUPAGE,IL +1931,17043,DUPAGE,IL +1932,17043,DUPAGE,IL +1933,17043,DUPAGE,IL +1934,17043,DUPAGE,IL +1935,17043,DUPAGE,IL +1936,17043,DUPAGE,IL +1937,17043,DUPAGE,IL +1938,17043,DUPAGE,IL +1939,17043,DUPAGE,IL +1940,17043,DUPAGE,IL +1941,17043,DUPAGE,IL +1942,17043,DUPAGE,IL +1943,17043,DUPAGE,IL +1944,17043,DUPAGE,IL +1945,17043,DUPAGE,IL +1946,17043,DUPAGE,IL +1947,17043,DUPAGE,IL +1948,17043,DUPAGE,IL +1949,17043,DUPAGE,IL +1950,17043,DUPAGE,IL +1951,17043,DUPAGE,IL +1952,17043,DUPAGE,IL +1953,17043,DUPAGE,IL +1954,17043,DUPAGE,IL +1955,17043,DUPAGE,IL +1956,17043,DUPAGE,IL +1957,17043,DUPAGE,IL +1958,17043,DUPAGE,IL +1959,17043,DUPAGE,IL +1960,17043,DUPAGE,IL +1961,17043,DUPAGE,IL +1962,17043,DUPAGE,IL +1963,17043,DUPAGE,IL +1964,17043,DUPAGE,IL +1965,17043,DUPAGE,IL +1966,17043,DUPAGE,IL +1967,17043,DUPAGE,IL +1968,17043,DUPAGE,IL +1969,17043,DUPAGE,IL +1970,17043,DUPAGE,IL +1971,17043,DUPAGE,IL +1972,17043,DUPAGE,IL +1973,17043,DUPAGE,IL +1974,17043,DUPAGE,IL +1975,17043,DUPAGE,IL +1976,17043,DUPAGE,IL +1977,17043,DUPAGE,IL +1978,17043,DUPAGE,IL +1979,17043,DUPAGE,IL +1980,17043,DUPAGE,IL +1981,17043,DUPAGE,IL +1982,17043,DUPAGE,IL +1983,17043,DUPAGE,IL +1984,17043,DUPAGE,IL +1985,17043,DUPAGE,IL +1986,17043,DUPAGE,IL +1987,17043,DUPAGE,IL +1988,17043,DUPAGE,IL +1989,17043,DUPAGE,IL +1990,17043,DUPAGE,IL +1991,17043,DUPAGE,IL +1992,17043,DUPAGE,IL +1993,17043,DUPAGE,IL +1994,17043,DUPAGE,IL +1995,17043,DUPAGE,IL +1996,17043,DUPAGE,IL +1997,17043,DUPAGE,IL +1998,17043,DUPAGE,IL +1999,17043,DUPAGE,IL +2000,17043,DUPAGE,IL +2001,17043,DUPAGE,IL +2002,17043,DUPAGE,IL +2003,17043,DUPAGE,IL +2004,17043,DUPAGE,IL +2005,17043,DUPAGE,IL +2006,17043,DUPAGE,IL +2007,17043,DUPAGE,IL +2008,17043,DUPAGE,IL +2009,17043,DUPAGE,IL +2010,17043,DUPAGE,IL +2011,17043,DUPAGE,IL +2012,17043,DUPAGE,IL +2013,17043,DUPAGE,IL +2014,17043,DUPAGE,IL +2015,17043,DUPAGE,IL +2016,17043,DUPAGE,IL +2017,17043,DUPAGE,IL +2018,17043,DUPAGE,IL +2019,17043,DUPAGE,IL +2020,17043,DUPAGE,IL +2021,17043,DUPAGE,IL +2022,17043,DUPAGE,IL +2023,17043,DUPAGE,IL +2024,17043,DUPAGE,IL +2025,17043,DUPAGE,IL +2026,17043,DUPAGE,IL +2027,17043,DUPAGE,IL +2028,17043,DUPAGE,IL +2029,17043,DUPAGE,IL +2030,17043,DUPAGE,IL +2031,17043,DUPAGE,IL +2032,17043,DUPAGE,IL +2033,17043,DUPAGE,IL +2034,17043,DUPAGE,IL +2035,17043,DUPAGE,IL +2036,17043,DUPAGE,IL +2037,17043,DUPAGE,IL +2038,17043,DUPAGE,IL +2039,17043,DUPAGE,IL +2040,17043,DUPAGE,IL +2041,17043,DUPAGE,IL +2042,17043,DUPAGE,IL +2043,17043,DUPAGE,IL +2044,17043,DUPAGE,IL +2045,17043,DUPAGE,IL +2046,17043,DUPAGE,IL +2047,17043,DUPAGE,IL +2048,17043,DUPAGE,IL +2049,17043,DUPAGE,IL +2050,17043,DUPAGE,IL +2051,17043,DUPAGE,IL +2052,17043,DUPAGE,IL +2053,17043,DUPAGE,IL +2054,17043,DUPAGE,IL +2055,17043,DUPAGE,IL +2056,17043,DUPAGE,IL +2057,17043,DUPAGE,IL +2058,17043,DUPAGE,IL +2059,17043,DUPAGE,IL +2060,17043,DUPAGE,IL +2061,17043,DUPAGE,IL +2062,17043,DUPAGE,IL +2063,17043,DUPAGE,IL +2064,17043,DUPAGE,IL +2065,17043,DUPAGE,IL +2066,17043,DUPAGE,IL +2067,17043,DUPAGE,IL +2068,17043,DUPAGE,IL +2069,17043,DUPAGE,IL +2070,17043,DUPAGE,IL +2071,17043,DUPAGE,IL +2072,17043,DUPAGE,IL +2073,17043,DUPAGE,IL +2074,17043,DUPAGE,IL +2075,17043,DUPAGE,IL +2076,17043,DUPAGE,IL +2077,17043,DUPAGE,IL +2078,17043,DUPAGE,IL +2079,17043,DUPAGE,IL +2080,17043,DUPAGE,IL +2081,17043,DUPAGE,IL +2082,17043,DUPAGE,IL +2083,17043,DUPAGE,IL +2084,17043,DUPAGE,IL +2085,17043,DUPAGE,IL +2086,17043,DUPAGE,IL +2087,17043,DUPAGE,IL +2088,17043,DUPAGE,IL +2089,17043,DUPAGE,IL +2090,17043,DUPAGE,IL +2091,17043,DUPAGE,IL +2092,17043,DUPAGE,IL +2093,17043,DUPAGE,IL +2094,17043,DUPAGE,IL +2095,17043,DUPAGE,IL +2096,17043,DUPAGE,IL +2097,17043,DUPAGE,IL +2098,17043,DUPAGE,IL +2099,17043,DUPAGE,IL +2100,17043,DUPAGE,IL +2101,17043,DUPAGE,IL +2102,17043,DUPAGE,IL +2103,17043,DUPAGE,IL +2104,17043,DUPAGE,IL +2105,17043,DUPAGE,IL +2106,17043,DUPAGE,IL +2107,17043,DUPAGE,IL +2108,17043,DUPAGE,IL +2109,17043,DUPAGE,IL +2110,17043,DUPAGE,IL +2111,17043,DUPAGE,IL +2112,17089,KANE,IL +2113,17089,KANE,IL +2114,17089,KANE,IL +2115,17089,KANE,IL +2116,17089,KANE,IL +2117,17089,KANE,IL +2118,17089,KANE,IL +2119,17089,KANE,IL +2120,17089,KANE,IL +2121,17089,KANE,IL +2122,17089,KANE,IL +2123,17089,KANE,IL +2124,17089,KANE,IL +2125,17089,KANE,IL +2126,17089,KANE,IL +2127,17089,KANE,IL +2128,17089,KANE,IL +2129,17089,KANE,IL +2130,17089,KANE,IL +2131,17089,KANE,IL +2132,17089,KANE,IL +2133,17089,KANE,IL +2134,17089,KANE,IL +2135,17089,KANE,IL +2136,17089,KANE,IL +2137,17089,KANE,IL +2138,17089,KANE,IL +2139,17089,KANE,IL +2140,17089,KANE,IL +2141,17089,KANE,IL +2142,17089,KANE,IL +2143,17089,KANE,IL +2144,17089,KANE,IL +2145,17089,KANE,IL +2146,17089,KANE,IL +2147,17089,KANE,IL +2148,17089,KANE,IL +2149,17089,KANE,IL +2150,17089,KANE,IL +2151,17089,KANE,IL +2152,17089,KANE,IL +2153,17089,KANE,IL +2154,17089,KANE,IL +2155,17089,KANE,IL +2156,17089,KANE,IL +2157,17089,KANE,IL +2158,17089,KANE,IL +2159,17089,KANE,IL +2160,17089,KANE,IL +2161,17089,KANE,IL +2162,17089,KANE,IL +2163,17089,KANE,IL +2164,17089,KANE,IL +2165,17089,KANE,IL +2166,17089,KANE,IL +2167,17089,KANE,IL +2168,17089,KANE,IL +2169,17089,KANE,IL +2170,17089,KANE,IL +2171,17089,KANE,IL +2172,17089,KANE,IL +2173,17089,KANE,IL +2174,17089,KANE,IL +2175,17089,KANE,IL +2176,17089,KANE,IL +2177,17089,KANE,IL +2178,17089,KANE,IL +2179,17089,KANE,IL +2180,17089,KANE,IL +2181,17089,KANE,IL +2182,17089,KANE,IL +2183,17089,KANE,IL +2184,17089,KANE,IL +2185,17089,KANE,IL +2186,17089,KANE,IL +2187,17089,KANE,IL +2188,17089,KANE,IL +2189,17089,KANE,IL +2190,17089,KANE,IL +2191,17089,KANE,IL +2192,17089,KANE,IL +2193,17089,KANE,IL +2194,17089,KANE,IL +2195,17089,KANE,IL +2196,17089,KANE,IL +2197,17089,KANE,IL +2198,17089,KANE,IL +2199,17089,KANE,IL +2200,17089,KANE,IL +2201,17089,KANE,IL +2202,17089,KANE,IL +2203,17089,KANE,IL +2204,17089,KANE,IL +2205,17089,KANE,IL +2206,17089,KANE,IL +2207,17089,KANE,IL +2208,17089,KANE,IL +2209,17089,KANE,IL +2210,17089,KANE,IL +2211,17089,KANE,IL +2212,17089,KANE,IL +2213,17089,KANE,IL +2214,17089,KANE,IL +2215,17089,KANE,IL +2216,17089,KANE,IL +2217,17089,KANE,IL +2218,17089,KANE,IL +2219,17089,KANE,IL +2220,17089,KANE,IL +2221,17089,KANE,IL +2222,17089,KANE,IL +2223,17089,KANE,IL +2224,17089,KANE,IL +2225,17089,KANE,IL +2226,17089,KANE,IL +2227,17089,KANE,IL +2228,17089,KANE,IL +2229,17089,KANE,IL +2230,17089,KANE,IL +2231,17089,KANE,IL +2232,17089,KANE,IL +2233,17089,KANE,IL +2234,17089,KANE,IL +2235,17089,KANE,IL +2236,17089,KANE,IL +2237,17089,KANE,IL +2238,17089,KANE,IL +2239,17089,KANE,IL +2240,17089,KANE,IL +2241,17089,KANE,IL +2242,17089,KANE,IL +2243,17089,KANE,IL +2244,17089,KANE,IL +2245,17089,KANE,IL +2246,17089,KANE,IL +2247,17089,KANE,IL +2248,17089,KANE,IL +2249,17089,KANE,IL +2250,17089,KANE,IL +2251,17089,KANE,IL +2252,17089,KANE,IL +2253,17089,KANE,IL +2254,17089,KANE,IL +2255,17089,KANE,IL +2256,17089,KANE,IL +2257,17089,KANE,IL +2258,17089,KANE,IL +2259,17089,KANE,IL +2260,17089,KANE,IL +2261,17089,KANE,IL +2262,17089,KANE,IL +2263,17089,KANE,IL +2264,17089,KANE,IL +2265,17089,KANE,IL +2266,17089,KANE,IL +2267,17089,KANE,IL +2268,17089,KANE,IL +2269,17089,KANE,IL +2270,17089,KANE,IL +2271,17089,KANE,IL +2272,17089,KANE,IL +2273,17089,KANE,IL +2274,17089,KANE,IL +2275,17089,KANE,IL +2276,17089,KANE,IL +2277,17089,KANE,IL +2278,17089,KANE,IL +2279,17089,KANE,IL +2280,17089,KANE,IL +2281,17089,KANE,IL +2282,17089,KANE,IL +2283,17089,KANE,IL +2284,17089,KANE,IL +2285,17089,KANE,IL +2286,17089,KANE,IL +2287,17089,KANE,IL +2288,17089,KANE,IL +2289,17089,KANE,IL +2290,17089,KANE,IL +2291,17089,KANE,IL +2292,17089,KANE,IL +2293,17089,KANE,IL +2294,17089,KANE,IL +2295,17089,KANE,IL +2296,17089,KANE,IL +2297,17089,KANE,IL +2298,17089,KANE,IL +2299,17089,KANE,IL +2300,17089,KANE,IL +2301,17089,KANE,IL +2302,17089,KANE,IL +2303,17089,KANE,IL +2304,17089,KANE,IL +2305,17093,KENDALL,IL +2306,17093,KENDALL,IL +2307,17093,KENDALL,IL +2308,17093,KENDALL,IL +2309,17093,KENDALL,IL +2310,17093,KENDALL,IL +2311,17093,KENDALL,IL +2312,17093,KENDALL,IL +2313,17093,KENDALL,IL +2314,17093,KENDALL,IL +2315,17093,KENDALL,IL +2316,17093,KENDALL,IL +2317,17093,KENDALL,IL +2318,17093,KENDALL,IL +2319,17093,KENDALL,IL +2320,17093,KENDALL,IL +2321,17093,KENDALL,IL +2322,17093,KENDALL,IL +2323,17093,KENDALL,IL +2324,17093,KENDALL,IL +2325,17093,KENDALL,IL +2326,17097,LAKE,IL +2327,17097,LAKE,IL +2328,17097,LAKE,IL +2329,17097,LAKE,IL +2330,17097,LAKE,IL +2331,17097,LAKE,IL +2332,17097,LAKE,IL +2333,17097,LAKE,IL +2334,17097,LAKE,IL +2335,17097,LAKE,IL +2336,17097,LAKE,IL +2337,17097,LAKE,IL +2338,17097,LAKE,IL +2339,17097,LAKE,IL +2340,17097,LAKE,IL +2341,17097,LAKE,IL +2342,17097,LAKE,IL +2343,17097,LAKE,IL +2344,17097,LAKE,IL +2345,17097,LAKE,IL +2346,17097,LAKE,IL +2347,17097,LAKE,IL +2348,17097,LAKE,IL +2349,17097,LAKE,IL +2350,17097,LAKE,IL +2351,17097,LAKE,IL +2352,17097,LAKE,IL +2353,17097,LAKE,IL +2354,17097,LAKE,IL +2355,17097,LAKE,IL +2356,17097,LAKE,IL +2357,17097,LAKE,IL +2358,17097,LAKE,IL +2359,17097,LAKE,IL +2360,17097,LAKE,IL +2361,17097,LAKE,IL +2362,17097,LAKE,IL +2363,17097,LAKE,IL +2364,17097,LAKE,IL +2365,17097,LAKE,IL +2366,17097,LAKE,IL +2367,17097,LAKE,IL +2368,17097,LAKE,IL +2369,17097,LAKE,IL +2370,17097,LAKE,IL +2371,17097,LAKE,IL +2372,17097,LAKE,IL +2373,17097,LAKE,IL +2374,17097,LAKE,IL +2375,17097,LAKE,IL +2376,17097,LAKE,IL +2377,17097,LAKE,IL +2378,17097,LAKE,IL +2379,17097,LAKE,IL +2380,17097,LAKE,IL +2381,17097,LAKE,IL +2382,17097,LAKE,IL +2383,17097,LAKE,IL +2384,17097,LAKE,IL +2385,17097,LAKE,IL +2386,17097,LAKE,IL +2387,17097,LAKE,IL +2388,17097,LAKE,IL +2389,17097,LAKE,IL +2390,17097,LAKE,IL +2391,17097,LAKE,IL +2392,17097,LAKE,IL +2393,17097,LAKE,IL +2394,17097,LAKE,IL +2395,17097,LAKE,IL +2396,17097,LAKE,IL +2397,17097,LAKE,IL +2398,17097,LAKE,IL +2399,17097,LAKE,IL +2400,17097,LAKE,IL +2401,17097,LAKE,IL +2402,17097,LAKE,IL +2403,17097,LAKE,IL +2404,17097,LAKE,IL +2405,17097,LAKE,IL +2406,17097,LAKE,IL +2407,17097,LAKE,IL +2408,17097,LAKE,IL +2409,17097,LAKE,IL +2410,17097,LAKE,IL +2411,17097,LAKE,IL +2412,17097,LAKE,IL +2413,17097,LAKE,IL +2414,17097,LAKE,IL +2415,17097,LAKE,IL +2416,17097,LAKE,IL +2417,17097,LAKE,IL +2418,17097,LAKE,IL +2419,17097,LAKE,IL +2420,17097,LAKE,IL +2421,17097,LAKE,IL +2422,17097,LAKE,IL +2423,17097,LAKE,IL +2424,17097,LAKE,IL +2425,17097,LAKE,IL +2426,17097,LAKE,IL +2427,17097,LAKE,IL +2428,17097,LAKE,IL +2429,17097,LAKE,IL +2430,17097,LAKE,IL +2431,17097,LAKE,IL +2432,17097,LAKE,IL +2433,17097,LAKE,IL +2434,17097,LAKE,IL +2435,17097,LAKE,IL +2436,17097,LAKE,IL +2437,17097,LAKE,IL +2438,17097,LAKE,IL +2439,17097,LAKE,IL +2440,17097,LAKE,IL +2441,17097,LAKE,IL +2442,17097,LAKE,IL +2443,17097,LAKE,IL +2444,17097,LAKE,IL +2445,17097,LAKE,IL +2446,17097,LAKE,IL +2447,17097,LAKE,IL +2448,17097,LAKE,IL +2449,17097,LAKE,IL +2450,17097,LAKE,IL +2451,17097,LAKE,IL +2452,17097,LAKE,IL +2453,17097,LAKE,IL +2454,17097,LAKE,IL +2455,17097,LAKE,IL +2456,17097,LAKE,IL +2457,17097,LAKE,IL +2458,17097,LAKE,IL +2459,17097,LAKE,IL +2460,17097,LAKE,IL +2461,17097,LAKE,IL +2462,17097,LAKE,IL +2463,17097,LAKE,IL +2464,17097,LAKE,IL +2465,17097,LAKE,IL +2466,17097,LAKE,IL +2467,17097,LAKE,IL +2468,17097,LAKE,IL +2469,17097,LAKE,IL +2470,17097,LAKE,IL +2471,17097,LAKE,IL +2472,17097,LAKE,IL +2473,17097,LAKE,IL +2474,17097,LAKE,IL +2475,17097,LAKE,IL +2476,17097,LAKE,IL +2477,17097,LAKE,IL +2478,17097,LAKE,IL +2479,17097,LAKE,IL +2480,17097,LAKE,IL +2481,17097,LAKE,IL +2482,17097,LAKE,IL +2483,17097,LAKE,IL +2484,17097,LAKE,IL +2485,17097,LAKE,IL +2486,17097,LAKE,IL +2487,17097,LAKE,IL +2488,17097,LAKE,IL +2489,17097,LAKE,IL +2490,17097,LAKE,IL +2491,17097,LAKE,IL +2492,17097,LAKE,IL +2493,17097,LAKE,IL +2494,17097,LAKE,IL +2495,17097,LAKE,IL +2496,17097,LAKE,IL +2497,17097,LAKE,IL +2498,17097,LAKE,IL +2499,17097,LAKE,IL +2500,17097,LAKE,IL +2501,17097,LAKE,IL +2502,17097,LAKE,IL +2503,17097,LAKE,IL +2504,17097,LAKE,IL +2505,17097,LAKE,IL +2506,17097,LAKE,IL +2507,17097,LAKE,IL +2508,17097,LAKE,IL +2509,17097,LAKE,IL +2510,17097,LAKE,IL +2511,17097,LAKE,IL +2512,17097,LAKE,IL +2513,17097,LAKE,IL +2514,17097,LAKE,IL +2515,17097,LAKE,IL +2516,17097,LAKE,IL +2517,17097,LAKE,IL +2518,17097,LAKE,IL +2519,17097,LAKE,IL +2520,17097,LAKE,IL +2521,17097,LAKE,IL +2522,17097,LAKE,IL +2523,17097,LAKE,IL +2524,17097,LAKE,IL +2525,17097,LAKE,IL +2526,17097,LAKE,IL +2527,17097,LAKE,IL +2528,17097,LAKE,IL +2529,17097,LAKE,IL +2530,17097,LAKE,IL +2531,17097,LAKE,IL +2532,17097,LAKE,IL +2533,17097,LAKE,IL +2534,17097,LAKE,IL +2535,17097,LAKE,IL +2536,17097,LAKE,IL +2537,17097,LAKE,IL +2538,17097,LAKE,IL +2539,17097,LAKE,IL +2540,17097,LAKE,IL +2541,17097,LAKE,IL +2542,17097,LAKE,IL +2543,17097,LAKE,IL +2544,17097,LAKE,IL +2545,17097,LAKE,IL +2546,17097,LAKE,IL +2547,17097,LAKE,IL +2548,17097,LAKE,IL +2549,17097,LAKE,IL +2550,17097,LAKE,IL +2551,17097,LAKE,IL +2552,17097,LAKE,IL +2553,17097,LAKE,IL +2554,17097,LAKE,IL +2555,17097,LAKE,IL +2556,17097,LAKE,IL +2557,17097,LAKE,IL +2558,17097,LAKE,IL +2559,17097,LAKE,IL +2560,17097,LAKE,IL +2561,17097,LAKE,IL +2562,17097,LAKE,IL +2563,17097,LAKE,IL +2564,17097,LAKE,IL +2565,17097,LAKE,IL +2566,17097,LAKE,IL +2567,17097,LAKE,IL +2568,17097,LAKE,IL +2569,17097,LAKE,IL +2570,17097,LAKE,IL +2571,17097,LAKE,IL +2572,17097,LAKE,IL +2573,17097,LAKE,IL +2574,17097,LAKE,IL +2575,17097,LAKE,IL +2576,17097,LAKE,IL +2577,17097,LAKE,IL +2578,17097,LAKE,IL +2579,17097,LAKE,IL +2580,17097,LAKE,IL +2581,17097,LAKE,IL +2582,17097,LAKE,IL +2583,17097,LAKE,IL +2584,17111,MCHENRY,IL +2585,17111,MCHENRY,IL +2586,17111,MCHENRY,IL +2587,17111,MCHENRY,IL +2588,17111,MCHENRY,IL +2589,17111,MCHENRY,IL +2590,17111,MCHENRY,IL +2591,17111,MCHENRY,IL +2592,17111,MCHENRY,IL +2593,17111,MCHENRY,IL +2594,17111,MCHENRY,IL +2595,17111,MCHENRY,IL +2596,17111,MCHENRY,IL +2597,17111,MCHENRY,IL +2598,17111,MCHENRY,IL +2599,17111,MCHENRY,IL +2600,17111,MCHENRY,IL +2601,17111,MCHENRY,IL +2602,17111,MCHENRY,IL +2603,17111,MCHENRY,IL +2604,17111,MCHENRY,IL +2605,17111,MCHENRY,IL +2606,17111,MCHENRY,IL +2607,17111,MCHENRY,IL +2608,17111,MCHENRY,IL +2609,17111,MCHENRY,IL +2610,17111,MCHENRY,IL +2611,17111,MCHENRY,IL +2612,17111,MCHENRY,IL +2613,17111,MCHENRY,IL +2614,17111,MCHENRY,IL +2615,17111,MCHENRY,IL +2616,17111,MCHENRY,IL +2617,17111,MCHENRY,IL +2618,17111,MCHENRY,IL +2619,17111,MCHENRY,IL +2620,17111,MCHENRY,IL +2621,17111,MCHENRY,IL +2622,17111,MCHENRY,IL +2623,17111,MCHENRY,IL +2624,17111,MCHENRY,IL +2625,17111,MCHENRY,IL +2626,17111,MCHENRY,IL +2627,17111,MCHENRY,IL +2628,17111,MCHENRY,IL +2629,17111,MCHENRY,IL +2630,17111,MCHENRY,IL +2631,17111,MCHENRY,IL +2632,17111,MCHENRY,IL +2633,17111,MCHENRY,IL +2634,17111,MCHENRY,IL +2635,17111,MCHENRY,IL +2636,17111,MCHENRY,IL +2637,17111,MCHENRY,IL +2638,17111,MCHENRY,IL +2639,17111,MCHENRY,IL +2640,17111,MCHENRY,IL +2641,17111,MCHENRY,IL +2642,17111,MCHENRY,IL +2643,17111,MCHENRY,IL +2644,17111,MCHENRY,IL +2645,17111,MCHENRY,IL +2646,17111,MCHENRY,IL +2647,17111,MCHENRY,IL +2648,17111,MCHENRY,IL +2649,17111,MCHENRY,IL +2650,17111,MCHENRY,IL +2651,17111,MCHENRY,IL +2652,17111,MCHENRY,IL +2653,17111,MCHENRY,IL +2654,17111,MCHENRY,IL +2655,17111,MCHENRY,IL +2656,17111,MCHENRY,IL +2657,17111,MCHENRY,IL +2658,17111,MCHENRY,IL +2659,17111,MCHENRY,IL +2660,17111,MCHENRY,IL +2661,17111,MCHENRY,IL +2662,17111,MCHENRY,IL +2663,17111,MCHENRY,IL +2664,17111,MCHENRY,IL +2665,17111,MCHENRY,IL +2666,17111,MCHENRY,IL +2667,17111,MCHENRY,IL +2668,17111,MCHENRY,IL +2669,17111,MCHENRY,IL +2670,17111,MCHENRY,IL +2671,17111,MCHENRY,IL +2672,17111,MCHENRY,IL +2673,17111,MCHENRY,IL +2674,17111,MCHENRY,IL +2675,17111,MCHENRY,IL +2676,17111,MCHENRY,IL +2677,17111,MCHENRY,IL +2678,17111,MCHENRY,IL +2679,17111,MCHENRY,IL +2680,17111,MCHENRY,IL +2681,17111,MCHENRY,IL +2682,17111,MCHENRY,IL +2683,17111,MCHENRY,IL +2684,17111,MCHENRY,IL +2685,17111,MCHENRY,IL +2686,17111,MCHENRY,IL +2687,17111,MCHENRY,IL +2688,17111,MCHENRY,IL +2689,17111,MCHENRY,IL +2690,17111,MCHENRY,IL +2691,17111,MCHENRY,IL +2692,17111,MCHENRY,IL +2693,17111,MCHENRY,IL +2694,17111,MCHENRY,IL +2695,17111,MCHENRY,IL +2696,17111,MCHENRY,IL +2697,17111,MCHENRY,IL +2698,17111,MCHENRY,IL +2699,17111,MCHENRY,IL +2700,17111,MCHENRY,IL +2701,17111,MCHENRY,IL +2702,17111,MCHENRY,IL +2703,17197,WILL,IL +2704,17197,WILL,IL +2705,17197,WILL,IL +2706,17197,WILL,IL +2707,17197,WILL,IL +2708,17197,WILL,IL +2709,17197,WILL,IL +2710,17197,WILL,IL +2711,17197,WILL,IL +2712,17197,WILL,IL +2713,17197,WILL,IL +2714,17197,WILL,IL +2715,17197,WILL,IL +2716,17197,WILL,IL +2717,17197,WILL,IL +2718,17197,WILL,IL +2719,17197,WILL,IL +2720,17197,WILL,IL +2721,17197,WILL,IL +2722,17197,WILL,IL +2723,17197,WILL,IL +2724,17197,WILL,IL +2725,17197,WILL,IL +2726,17197,WILL,IL +2727,17197,WILL,IL +2728,17197,WILL,IL +2729,17197,WILL,IL +2730,17197,WILL,IL +2731,17197,WILL,IL +2732,17197,WILL,IL +2733,17197,WILL,IL +2734,17197,WILL,IL +2735,17197,WILL,IL +2736,17197,WILL,IL +2737,17197,WILL,IL +2738,17197,WILL,IL +2739,17197,WILL,IL +2740,17197,WILL,IL +2741,17197,WILL,IL +2742,17197,WILL,IL +2743,17197,WILL,IL +2744,17197,WILL,IL +2745,17197,WILL,IL +2746,17197,WILL,IL +2747,17197,WILL,IL +2748,17197,WILL,IL +2749,17197,WILL,IL +2750,17197,WILL,IL +2751,17197,WILL,IL +2752,17197,WILL,IL +2753,17197,WILL,IL +2754,17197,WILL,IL +2755,17197,WILL,IL +2756,17197,WILL,IL +2757,17197,WILL,IL +2758,17197,WILL,IL +2759,17197,WILL,IL +2760,17197,WILL,IL +2761,17197,WILL,IL +2762,17197,WILL,IL +2763,17197,WILL,IL +2764,17197,WILL,IL +2765,17197,WILL,IL +2766,17197,WILL,IL +2767,17197,WILL,IL +2768,17197,WILL,IL +2769,17197,WILL,IL +2770,17197,WILL,IL +2771,17197,WILL,IL +2772,17197,WILL,IL +2773,17197,WILL,IL +2774,17197,WILL,IL +2775,17197,WILL,IL +2776,17197,WILL,IL +2777,17197,WILL,IL +2778,17197,WILL,IL +2779,17197,WILL,IL +2780,17197,WILL,IL +2781,17197,WILL,IL +2782,17197,WILL,IL +2783,17197,WILL,IL +2784,17197,WILL,IL +2785,17197,WILL,IL +2786,17197,WILL,IL +2787,17197,WILL,IL +2788,17197,WILL,IL +2789,17197,WILL,IL +2790,17197,WILL,IL +2791,17197,WILL,IL +2792,17197,WILL,IL +2793,17197,WILL,IL +2794,17197,WILL,IL +2795,17197,WILL,IL +2796,17197,WILL,IL +2797,17197,WILL,IL +2798,17197,WILL,IL +2799,17197,WILL,IL +2800,17197,WILL,IL +2801,17197,WILL,IL +2802,17197,WILL,IL +2803,17197,WILL,IL +2804,17197,WILL,IL +2805,17197,WILL,IL +2806,17197,WILL,IL +2807,17197,WILL,IL +2808,17197,WILL,IL +2809,17197,WILL,IL +2810,17197,WILL,IL +2811,17197,WILL,IL +2812,17197,WILL,IL +2813,17197,WILL,IL +2814,17197,WILL,IL +2815,17197,WILL,IL +2816,17197,WILL,IL +2817,17197,WILL,IL +2818,17197,WILL,IL +2819,17197,WILL,IL +2820,17197,WILL,IL +2821,17197,WILL,IL +2822,17197,WILL,IL +2823,17197,WILL,IL +2824,17197,WILL,IL +2825,17197,WILL,IL +2826,17197,WILL,IL +2827,17197,WILL,IL +2828,17197,WILL,IL +2829,17197,WILL,IL +2830,17197,WILL,IL +2831,17197,WILL,IL +2832,17197,WILL,IL +2833,17197,WILL,IL +2834,17197,WILL,IL +2835,17197,WILL,IL +2836,17197,WILL,IL +2837,17197,WILL,IL +2838,17197,WILL,IL +2839,17197,WILL,IL +2840,17197,WILL,IL +2841,17197,WILL,IL +2842,17197,WILL,IL +2843,17197,WILL,IL +2844,17197,WILL,IL +2845,17197,WILL,IL +2846,17197,WILL,IL +2847,17197,WILL,IL +2848,17197,WILL,IL +2849,17197,WILL,IL +2850,17197,WILL,IL +2851,17197,WILL,IL +2852,17197,WILL,IL +2853,17197,WILL,IL +2854,17197,WILL,IL +2855,17197,WILL,IL +2856,17197,WILL,IL +2857,17197,WILL,IL +2858,17197,WILL,IL +2859,17197,WILL,IL +2860,17197,WILL,IL +2861,17197,WILL,IL +2862,17197,WILL,IL +2863,17197,WILL,IL +2864,17197,WILL,IL +2865,17197,WILL,IL +2866,17197,WILL,IL +2867,17197,WILL,IL +2868,17197,WILL,IL +2869,17197,WILL,IL +2870,17197,WILL,IL +2871,17197,WILL,IL +2872,17197,WILL,IL +2873,17197,WILL,IL +2874,17197,WILL,IL +2875,17197,WILL,IL +2876,17197,WILL,IL +2877,17197,WILL,IL +2878,17197,WILL,IL +2879,17197,WILL,IL +2880,17197,WILL,IL +2881,17197,WILL,IL +2882,17197,WILL,IL +2883,17197,WILL,IL +2884,17197,WILL,IL +2885,17197,WILL,IL +2886,17197,WILL,IL +2887,17197,WILL,IL +2888,17197,WILL,IL +2889,17197,WILL,IL +2890,17197,WILL,IL +2891,17197,WILL,IL +2892,17197,WILL,IL +2893,17197,WILL,IL +2894,17197,WILL,IL +2895,17197,WILL,IL +2896,17197,WILL,IL +2897,17197,WILL,IL +2898,17197,WILL,IL +2899,17197,WILL,IL +2900,17197,WILL,IL +2901,17197,WILL,IL +2902,17197,WILL,IL +2903,17197,WILL,IL +2904,17197,WILL,IL +2905,17197,WILL,IL +2906,17197,WILL,IL +2907,17197,WILL,IL +2908,17197,WILL,IL +2909,17197,WILL,IL +2910,17197,WILL,IL +2911,17197,WILL,IL +2912,17197,WILL,IL +2913,17197,WILL,IL +2914,17197,WILL,IL +2915,17197,WILL,IL +2916,17197,WILL,IL +2917,17197,WILL,IL +2918,17197,WILL,IL +2919,17197,WILL,IL +2920,17197,WILL,IL +2921,17197,WILL,IL +2922,17197,WILL,IL +2923,17197,WILL,IL +2924,17197,WILL,IL +2925,17197,WILL,IL +2926,17197,WILL,IL +2927,17063,GRUNDY,IL +2928,17063,GRUNDY,IL +2929,17063,GRUNDY,IL +2930,17063,GRUNDY,IL +2931,17063,GRUNDY,IL +2932,17063,GRUNDY,IL +2933,17063,GRUNDY,IL +2934,17063,GRUNDY,IL +2935,17063,GRUNDY,IL +2936,17063,GRUNDY,IL +2937,17063,GRUNDY,IL +2938,17063,GRUNDY,IL +2939,17063,GRUNDY,IL +2940,17063,GRUNDY,IL +2941,17063,GRUNDY,IL +2942,17063,GRUNDY,IL +2943,17063,GRUNDY,IL +2944,17063,GRUNDY,IL +2945,17063,GRUNDY,IL +2946,17063,GRUNDY,IL +2947,17063,GRUNDY,IL +2948,17063,GRUNDY,IL +2949,17063,GRUNDY,IL +2950,17063,GRUNDY,IL +2951,17007,BOONE,IL +2952,17007,BOONE,IL +2953,17007,BOONE,IL +2954,17007,BOONE,IL +2955,17007,BOONE,IL +2956,17007,BOONE,IL +2957,17007,BOONE,IL +2958,17007,BOONE,IL +2959,17007,BOONE,IL +2960,17007,BOONE,IL +2961,17007,BOONE,IL +2962,17007,BOONE,IL +2963,17007,BOONE,IL +2964,17007,BOONE,IL +2965,17007,BOONE,IL +2966,17007,BOONE,IL +2967,17007,BOONE,IL +2968,17007,BOONE,IL +2969,17007,BOONE,IL +2970,17007,BOONE,IL +2971,17007,BOONE,IL +2972,17007,BOONE,IL +2973,17007,BOONE,IL +2974,17007,BOONE,IL +2975,17007,BOONE,IL +2976,17037,DEKALB,IL +2977,17037,DEKALB,IL +2978,17037,DEKALB,IL +2979,17037,DEKALB,IL +2980,17037,DEKALB,IL +2981,17037,DEKALB,IL +2982,17037,DEKALB,IL +2983,17037,DEKALB,IL +2984,17037,DEKALB,IL +2985,17037,DEKALB,IL +2986,17037,DEKALB,IL +2987,17037,DEKALB,IL +2988,17037,DEKALB,IL +2989,17037,DEKALB,IL +2990,17037,DEKALB,IL +2991,17037,DEKALB,IL +2992,17037,DEKALB,IL +2993,17037,DEKALB,IL +2994,17037,DEKALB,IL +2995,17037,DEKALB,IL +2996,17037,DEKALB,IL +2997,17037,DEKALB,IL +2998,17037,DEKALB,IL +2999,17037,DEKALB,IL +3000,17037,DEKALB,IL +3001,17037,DEKALB,IL +3002,17037,DEKALB,IL +3003,17037,DEKALB,IL +3004,17037,DEKALB,IL +3005,17037,DEKALB,IL +3006,17037,DEKALB,IL +3007,17037,DEKALB,IL +3008,17037,DEKALB,IL +3009,17037,DEKALB,IL +3010,17037,DEKALB,IL +3011,17037,DEKALB,IL +3012,17037,DEKALB,IL +3013,17037,DEKALB,IL +3014,17037,DEKALB,IL +3015,17037,DEKALB,IL +3016,17037,DEKALB,IL +3017,17037,DEKALB,IL +3018,17037,DEKALB,IL +3019,17037,DEKALB,IL +3020,17037,DEKALB,IL +3021,17037,DEKALB,IL +3022,17091,KANKAKEE,IL +3023,17091,KANKAKEE,IL +3024,17091,KANKAKEE,IL +3025,17091,KANKAKEE,IL +3026,17091,KANKAKEE,IL +3027,17091,KANKAKEE,IL +3028,17091,KANKAKEE,IL +3029,17091,KANKAKEE,IL +3030,17091,KANKAKEE,IL +3031,17091,KANKAKEE,IL +3032,17091,KANKAKEE,IL +3033,17091,KANKAKEE,IL +3034,17091,KANKAKEE,IL +3035,17091,KANKAKEE,IL +3036,17091,KANKAKEE,IL +3037,17091,KANKAKEE,IL +3038,17091,KANKAKEE,IL +3039,17091,KANKAKEE,IL +3040,17091,KANKAKEE,IL +3041,17091,KANKAKEE,IL +3042,17091,KANKAKEE,IL +3043,17091,KANKAKEE,IL +3044,17091,KANKAKEE,IL +3045,17091,KANKAKEE,IL +3046,17091,KANKAKEE,IL +3047,17091,KANKAKEE,IL +3048,17091,KANKAKEE,IL +3049,17091,KANKAKEE,IL +3050,17091,KANKAKEE,IL +3051,17091,KANKAKEE,IL +3052,17091,KANKAKEE,IL +3053,17091,KANKAKEE,IL +3054,17091,KANKAKEE,IL +3055,17091,KANKAKEE,IL +3056,17091,KANKAKEE,IL +3057,17091,KANKAKEE,IL +3058,17091,KANKAKEE,IL +3059,17091,KANKAKEE,IL +3060,17091,KANKAKEE,IL +3061,17091,KANKAKEE,IL +3062,17091,KANKAKEE,IL +3063,17091,KANKAKEE,IL +3064,17091,KANKAKEE,IL +3065,17091,KANKAKEE,IL +3066,17091,KANKAKEE,IL +3067,17091,KANKAKEE,IL +3068,17091,KANKAKEE,IL +3069,17091,KANKAKEE,IL +3070,17091,KANKAKEE,IL +3071,17091,KANKAKEE,IL +3072,17091,KANKAKEE,IL +3073,17091,KANKAKEE,IL +3074,17099,LASALLE,IL +3075,17099,LASALLE,IL +3076,17099,LASALLE,IL +3077,17099,LASALLE,IL +3078,17099,LASALLE,IL +3079,17099,LASALLE,IL +3080,17099,LASALLE,IL +3081,17099,LASALLE,IL +3082,17099,LASALLE,IL +3083,17099,LASALLE,IL +3084,17099,LASALLE,IL +3085,17099,LASALLE,IL +3086,17099,LASALLE,IL +3087,17099,LASALLE,IL +3088,17099,LASALLE,IL +3089,17099,LASALLE,IL +3090,17099,LASALLE,IL +3091,17099,LASALLE,IL +3092,17099,LASALLE,IL +3093,17099,LASALLE,IL +3094,17099,LASALLE,IL +3095,17099,LASALLE,IL +3096,17099,LASALLE,IL +3097,17099,LASALLE,IL +3098,17099,LASALLE,IL +3099,17099,LASALLE,IL +3100,17099,LASALLE,IL +3101,17099,LASALLE,IL +3102,17099,LASALLE,IL +3103,17099,LASALLE,IL +3104,17099,LASALLE,IL +3105,17099,LASALLE,IL +3106,17099,LASALLE,IL +3107,17099,LASALLE,IL +3108,17099,LASALLE,IL +3109,17099,LASALLE,IL +3110,17099,LASALLE,IL +3111,17099,LASALLE,IL +3112,17099,LASALLE,IL +3113,17099,LASALLE,IL +3114,17099,LASALLE,IL +3115,17099,LASALLE,IL +3116,17099,LASALLE,IL +3117,17099,LASALLE,IL +3118,17099,LASALLE,IL +3119,17099,LASALLE,IL +3120,17099,LASALLE,IL +3121,17099,LASALLE,IL +3122,17099,LASALLE,IL +3123,17099,LASALLE,IL +3124,17099,LASALLE,IL +3125,17099,LASALLE,IL +3126,17099,LASALLE,IL +3127,17099,LASALLE,IL +3128,17099,LASALLE,IL +3129,17099,LASALLE,IL +3130,17099,LASALLE,IL +3131,17099,LASALLE,IL +3132,17099,LASALLE,IL +3133,17099,LASALLE,IL +3134,17099,LASALLE,IL +3135,17099,LASALLE,IL +3136,17099,LASALLE,IL +3137,17099,LASALLE,IL +3138,17099,LASALLE,IL +3139,17099,LASALLE,IL +3140,17099,LASALLE,IL +3141,17099,LASALLE,IL +3142,17099,LASALLE,IL +3143,17099,LASALLE,IL +3144,17099,LASALLE,IL +3145,17099,LASALLE,IL +3146,17103,LEE,IL +3147,17103,LEE,IL +3148,17103,LEE,IL +3149,17103,LEE,IL +3150,17103,LEE,IL +3151,17103,LEE,IL +3152,17141,OGLE,IL +3153,17141,OGLE,IL +3154,17141,OGLE,IL +3155,17141,OGLE,IL +3156,17141,OGLE,IL +3157,17141,OGLE,IL +3158,17141,OGLE,IL +3159,17141,OGLE,IL +3160,17141,OGLE,IL +3161,17141,OGLE,IL +3162,17141,OGLE,IL +3163,17141,OGLE,IL +3164,17141,OGLE,IL +3165,17141,OGLE,IL +3166,17141,OGLE,IL +3167,17141,OGLE,IL +3168,17141,OGLE,IL +3169,17201,WINNEBAGO,IL +3170,17201,WINNEBAGO,IL +3171,17201,WINNEBAGO,IL +3172,17201,WINNEBAGO,IL +3173,17201,WINNEBAGO,IL +3174,17201,WINNEBAGO,IL +3175,17201,WINNEBAGO,IL +3176,17201,WINNEBAGO,IL +3177,17201,WINNEBAGO,IL +3178,17201,WINNEBAGO,IL +3179,17201,WINNEBAGO,IL +3180,17201,WINNEBAGO,IL +3181,17201,WINNEBAGO,IL +3182,17201,WINNEBAGO,IL +3183,17201,WINNEBAGO,IL +3184,17201,WINNEBAGO,IL +3185,17201,WINNEBAGO,IL +3186,17201,WINNEBAGO,IL +3187,17201,WINNEBAGO,IL +3188,17201,WINNEBAGO,IL +3189,17201,WINNEBAGO,IL +3190,17201,WINNEBAGO,IL +3191,17201,WINNEBAGO,IL +3192,17201,WINNEBAGO,IL +3193,17201,WINNEBAGO,IL +3194,17201,WINNEBAGO,IL +3195,17201,WINNEBAGO,IL +3196,17201,WINNEBAGO,IL +3197,17201,WINNEBAGO,IL +3198,17201,WINNEBAGO,IL +3199,17201,WINNEBAGO,IL +3200,17201,WINNEBAGO,IL +3201,17201,WINNEBAGO,IL +3202,17201,WINNEBAGO,IL +3203,17201,WINNEBAGO,IL +3204,17201,WINNEBAGO,IL +3205,17201,WINNEBAGO,IL +3206,17201,WINNEBAGO,IL +3207,17201,WINNEBAGO,IL +3208,17201,WINNEBAGO,IL +3209,17201,WINNEBAGO,IL +3210,17201,WINNEBAGO,IL +3211,17201,WINNEBAGO,IL +3212,17201,WINNEBAGO,IL +3213,17201,WINNEBAGO,IL +3214,17201,WINNEBAGO,IL +3215,17201,WINNEBAGO,IL +3216,17201,WINNEBAGO,IL +3217,17201,WINNEBAGO,IL +3218,17201,WINNEBAGO,IL +3219,17201,WINNEBAGO,IL +3220,17201,WINNEBAGO,IL +3221,17201,WINNEBAGO,IL +3222,17201,WINNEBAGO,IL +3223,17201,WINNEBAGO,IL +3224,17201,WINNEBAGO,IL +3225,17201,WINNEBAGO,IL +3226,17201,WINNEBAGO,IL +3227,17201,WINNEBAGO,IL +3228,17201,WINNEBAGO,IL +3229,17201,WINNEBAGO,IL +3230,17201,WINNEBAGO,IL +3231,17201,WINNEBAGO,IL +3232,17201,WINNEBAGO,IL +3233,17201,WINNEBAGO,IL +3234,17201,WINNEBAGO,IL +3235,17201,WINNEBAGO,IL +3236,17201,WINNEBAGO,IL +3237,17201,WINNEBAGO,IL +3238,17201,WINNEBAGO,IL +3239,17201,WINNEBAGO,IL +3240,17201,WINNEBAGO,IL +3241,17201,WINNEBAGO,IL +3242,17201,WINNEBAGO,IL +3243,17201,WINNEBAGO,IL +3244,17201,WINNEBAGO,IL +3245,17201,WINNEBAGO,IL +3246,17201,WINNEBAGO,IL +3247,17201,WINNEBAGO,IL +3248,18089,LAKE,IN +3249,18089,LAKE,IN +3250,18089,LAKE,IN +3251,18089,LAKE,IN +3252,18089,LAKE,IN +3253,18089,LAKE,IN +3254,18089,LAKE,IN +3255,18089,LAKE,IN +3256,18089,LAKE,IN +3257,18089,LAKE,IN +3258,18089,LAKE,IN +3259,18089,LAKE,IN +3260,18089,LAKE,IN +3261,18089,LAKE,IN +3262,18089,LAKE,IN +3263,18089,LAKE,IN +3264,18089,LAKE,IN +3265,18089,LAKE,IN +3266,18089,LAKE,IN +3267,18089,LAKE,IN +3268,18089,LAKE,IN +3269,18089,LAKE,IN +3270,18089,LAKE,IN +3271,18089,LAKE,IN +3272,18089,LAKE,IN +3273,18089,LAKE,IN +3274,18089,LAKE,IN +3275,18089,LAKE,IN +3276,18089,LAKE,IN +3277,18089,LAKE,IN +3278,18089,LAKE,IN +3279,18089,LAKE,IN +3280,18089,LAKE,IN +3281,18089,LAKE,IN +3282,18089,LAKE,IN +3283,18089,LAKE,IN +3284,18089,LAKE,IN +3285,18089,LAKE,IN +3286,18089,LAKE,IN +3287,18089,LAKE,IN +3288,18089,LAKE,IN +3289,18089,LAKE,IN +3290,18089,LAKE,IN +3291,18089,LAKE,IN +3292,18089,LAKE,IN +3293,18089,LAKE,IN +3294,18089,LAKE,IN +3295,18089,LAKE,IN +3296,18089,LAKE,IN +3297,18089,LAKE,IN +3298,18089,LAKE,IN +3299,18089,LAKE,IN +3300,18089,LAKE,IN +3301,18089,LAKE,IN +3302,18089,LAKE,IN +3303,18089,LAKE,IN +3304,18089,LAKE,IN +3305,18089,LAKE,IN +3306,18089,LAKE,IN +3307,18089,LAKE,IN +3308,18089,LAKE,IN +3309,18089,LAKE,IN +3310,18089,LAKE,IN +3311,18089,LAKE,IN +3312,18089,LAKE,IN +3313,18089,LAKE,IN +3314,18089,LAKE,IN +3315,18089,LAKE,IN +3316,18089,LAKE,IN +3317,18089,LAKE,IN +3318,18089,LAKE,IN +3319,18089,LAKE,IN +3320,18089,LAKE,IN +3321,18089,LAKE,IN +3322,18089,LAKE,IN +3323,18089,LAKE,IN +3324,18089,LAKE,IN +3325,18089,LAKE,IN +3326,18089,LAKE,IN +3327,18089,LAKE,IN +3328,18089,LAKE,IN +3329,18089,LAKE,IN +3330,18089,LAKE,IN +3331,18089,LAKE,IN +3332,18089,LAKE,IN +3333,18089,LAKE,IN +3334,18089,LAKE,IN +3335,18089,LAKE,IN +3336,18089,LAKE,IN +3337,18089,LAKE,IN +3338,18089,LAKE,IN +3339,18089,LAKE,IN +3340,18089,LAKE,IN +3341,18089,LAKE,IN +3342,18089,LAKE,IN +3343,18089,LAKE,IN +3344,18089,LAKE,IN +3345,18091,LAPORTE,IN +3346,18091,LAPORTE,IN +3347,18091,LAPORTE,IN +3348,18091,LAPORTE,IN +3349,18091,LAPORTE,IN +3350,18091,LAPORTE,IN +3351,18091,LAPORTE,IN +3352,18091,LAPORTE,IN +3353,18091,LAPORTE,IN +3354,18091,LAPORTE,IN +3355,18091,LAPORTE,IN +3356,18091,LAPORTE,IN +3357,18091,LAPORTE,IN +3358,18091,LAPORTE,IN +3359,18091,LAPORTE,IN +3360,18091,LAPORTE,IN +3361,18091,LAPORTE,IN +3362,18091,LAPORTE,IN +3363,18091,LAPORTE,IN +3364,18091,LAPORTE,IN +3365,18091,LAPORTE,IN +3366,18091,LAPORTE,IN +3367,18091,LAPORTE,IN +3368,18091,LAPORTE,IN +3369,18091,LAPORTE,IN +3370,18091,LAPORTE,IN +3371,18091,LAPORTE,IN +3372,18091,LAPORTE,IN +3373,18091,LAPORTE,IN +3374,18091,LAPORTE,IN +3375,18091,LAPORTE,IN +3376,18091,LAPORTE,IN +3377,18091,LAPORTE,IN +3378,18091,LAPORTE,IN +3379,18091,LAPORTE,IN +3380,18091,LAPORTE,IN +3381,18091,LAPORTE,IN +3382,18091,LAPORTE,IN +3383,18091,LAPORTE,IN +3384,18091,LAPORTE,IN +3385,18091,LAPORTE,IN +3386,18091,LAPORTE,IN +3387,18091,LAPORTE,IN +3388,18091,LAPORTE,IN +3389,18091,LAPORTE,IN +3390,18091,LAPORTE,IN +3391,18091,LAPORTE,IN +3392,18091,LAPORTE,IN +3393,18091,LAPORTE,IN +3394,18091,LAPORTE,IN +3395,18091,LAPORTE,IN +3396,18091,LAPORTE,IN +3397,18091,LAPORTE,IN +3398,18091,LAPORTE,IN +3399,18091,LAPORTE,IN +3400,18091,LAPORTE,IN +3401,18127,PORTER,IN +3402,18127,PORTER,IN +3403,18127,PORTER,IN +3404,18127,PORTER,IN +3405,18127,PORTER,IN +3406,18127,PORTER,IN +3407,18127,PORTER,IN +3408,18127,PORTER,IN +3409,18127,PORTER,IN +3410,18127,PORTER,IN +3411,18127,PORTER,IN +3412,18127,PORTER,IN +3413,18127,PORTER,IN +3414,18127,PORTER,IN +3415,18127,PORTER,IN +3416,18127,PORTER,IN +3417,18127,PORTER,IN +3418,18127,PORTER,IN +3419,18127,PORTER,IN +3420,18127,PORTER,IN +3421,18127,PORTER,IN +3422,18127,PORTER,IN +3423,18127,PORTER,IN +3424,18127,PORTER,IN +3425,18127,PORTER,IN +3426,18127,PORTER,IN +3427,18127,PORTER,IN +3428,18127,PORTER,IN +3429,18127,PORTER,IN +3430,18127,PORTER,IN +3431,18127,PORTER,IN +3432,18127,PORTER,IN +3433,18127,PORTER,IN +3434,18127,PORTER,IN +3435,18127,PORTER,IN +3436,18127,PORTER,IN +3437,18127,PORTER,IN +3438,18127,PORTER,IN +3439,18127,PORTER,IN +3440,18127,PORTER,IN +3441,18127,PORTER,IN +3442,18127,PORTER,IN +3443,18127,PORTER,IN +3444,18127,PORTER,IN +3445,18127,PORTER,IN +3446,18127,PORTER,IN +3447,18127,PORTER,IN +3448,18127,PORTER,IN +3449,18127,PORTER,IN +3450,18127,PORTER,IN +3451,18127,PORTER,IN +3452,18127,PORTER,IN +3453,18127,PORTER,IN +3454,18127,PORTER,IN +3455,18127,PORTER,IN +3456,18127,PORTER,IN +3457,18127,PORTER,IN +3458,18127,PORTER,IN +3459,18127,PORTER,IN +3460,18127,PORTER,IN +3461,18127,PORTER,IN +3462,18127,PORTER,IN +3463,18127,PORTER,IN +3464,18127,PORTER,IN +3465,18127,PORTER,IN +3466,18127,PORTER,IN +3467,18127,PORTER,IN +3468,55059,KENOSHA,WI +3469,55059,KENOSHA,WI +3470,55059,KENOSHA,WI +3471,55059,KENOSHA,WI +3472,55059,KENOSHA,WI +3473,55059,KENOSHA,WI +3474,55059,KENOSHA,WI +3475,55059,KENOSHA,WI +3476,55059,KENOSHA,WI +3477,55059,KENOSHA,WI +3478,55059,KENOSHA,WI +3479,55059,KENOSHA,WI +3480,55059,KENOSHA,WI +3481,55059,KENOSHA,WI +3482,55059,KENOSHA,WI +3483,55059,KENOSHA,WI +3484,55059,KENOSHA,WI +3485,55059,KENOSHA,WI +3486,55059,KENOSHA,WI +3487,55059,KENOSHA,WI +3488,55059,KENOSHA,WI +3489,55059,KENOSHA,WI +3490,55059,KENOSHA,WI +3491,55059,KENOSHA,WI +3492,55059,KENOSHA,WI +3493,55059,KENOSHA,WI +3494,55059,KENOSHA,WI +3495,55059,KENOSHA,WI +3496,55059,KENOSHA,WI +3497,55059,KENOSHA,WI +3498,55059,KENOSHA,WI +3499,55059,KENOSHA,WI +3500,55059,KENOSHA,WI +3501,55059,KENOSHA,WI +3502,55059,KENOSHA,WI +3503,55059,KENOSHA,WI +3504,55059,KENOSHA,WI +3505,55059,KENOSHA,WI +3506,55059,KENOSHA,WI +3507,55059,KENOSHA,WI +3508,55059,KENOSHA,WI +3509,55059,KENOSHA,WI +3510,55059,KENOSHA,WI +3511,55059,KENOSHA,WI +3512,55059,KENOSHA,WI +3513,55101,RACINE,WI +3514,55101,RACINE,WI +3515,55101,RACINE,WI +3516,55101,RACINE,WI +3517,55101,RACINE,WI +3518,55101,RACINE,WI +3519,55101,RACINE,WI +3520,55101,RACINE,WI +3521,55101,RACINE,WI +3522,55101,RACINE,WI +3523,55101,RACINE,WI +3524,55101,RACINE,WI +3525,55101,RACINE,WI +3526,55101,RACINE,WI +3527,55101,RACINE,WI +3528,55101,RACINE,WI +3529,55101,RACINE,WI +3530,55101,RACINE,WI +3531,55101,RACINE,WI +3532,55101,RACINE,WI +3533,55101,RACINE,WI +3534,55101,RACINE,WI +3535,55101,RACINE,WI +3536,55101,RACINE,WI +3537,55101,RACINE,WI +3538,55101,RACINE,WI +3539,55101,RACINE,WI +3540,55101,RACINE,WI +3541,55101,RACINE,WI +3542,55101,RACINE,WI +3543,55101,RACINE,WI +3544,55101,RACINE,WI +3545,55101,RACINE,WI +3546,55101,RACINE,WI +3547,55101,RACINE,WI +3548,55101,RACINE,WI +3549,55101,RACINE,WI +3550,55101,RACINE,WI +3551,55101,RACINE,WI +3552,55101,RACINE,WI +3553,55101,RACINE,WI +3554,55101,RACINE,WI +3555,55101,RACINE,WI +3556,55101,RACINE,WI +3557,55101,RACINE,WI +3558,55101,RACINE,WI +3559,55101,RACINE,WI +3560,55101,RACINE,WI +3561,55101,RACINE,WI +3562,55101,RACINE,WI +3563,55101,RACINE,WI +3564,55101,RACINE,WI +3565,55101,RACINE,WI +3566,55101,RACINE,WI +3567,55101,RACINE,WI +3568,55101,RACINE,WI +3569,55127,WALWORTH,WI +3570,55127,WALWORTH,WI +3571,55127,WALWORTH,WI +3572,55127,WALWORTH,WI +3573,55127,WALWORTH,WI +3574,55127,WALWORTH,WI +3575,55127,WALWORTH,WI +3576,55127,WALWORTH,WI +3577,55127,WALWORTH,WI +3578,55127,WALWORTH,WI +3579,55127,WALWORTH,WI +3580,55127,WALWORTH,WI +3581,55127,WALWORTH,WI +3582,55127,WALWORTH,WI +3583,55127,WALWORTH,WI +3584,55127,WALWORTH,WI +3585,55127,WALWORTH,WI +3586,55127,WALWORTH,WI +3587,55127,WALWORTH,WI +3588,55127,WALWORTH,WI +3589,55127,WALWORTH,WI +3590,55127,WALWORTH,WI +3591,55127,WALWORTH,WI +3592,55127,WALWORTH,WI +3593,55127,WALWORTH,WI +3594,55127,WALWORTH,WI +3595,55127,WALWORTH,WI +3596,55127,WALWORTH,WI +3597,55127,WALWORTH,WI +3598,55127,WALWORTH,WI +3599,55127,WALWORTH,WI +3600,55127,WALWORTH,WI +3601,55127,WALWORTH,WI +3602,55127,WALWORTH,WI +3603,55127,WALWORTH,WI +3604,55127,WALWORTH,WI +3605,55127,WALWORTH,WI +3606,55127,WALWORTH,WI +3607,55127,WALWORTH,WI +3608,55127,WALWORTH,WI +3609,55127,WALWORTH,WI +3610,55127,WALWORTH,WI +3611,55127,WALWORTH,WI +3612,55127,WALWORTH,WI +3613,55127,WALWORTH,WI +3614,55127,WALWORTH,WI +3615,55127,WALWORTH,WI +3616,55127,WALWORTH,WI +3617,55127,WALWORTH,WI +3618,55127,WALWORTH,WI +3619,55127,WALWORTH,WI +3620,55127,WALWORTH,WI +3621,55127,WALWORTH,WI +3622,55127,WALWORTH,WI +3623,55127,WALWORTH,WI +3624,55127,WALWORTH,WI +3625,55127,WALWORTH,WI +3626,55127,WALWORTH,WI +3627,55127,WALWORTH,WI +3628,55127,WALWORTH,WI +3629,55127,WALWORTH,WI +3630,55127,WALWORTH,WI +3631,55127,WALWORTH,WI +3632,55127,WALWORTH,WI From aac14c665f5717b6be9064d68eeee53979a981f6 Mon Sep 17 00:00:00 2001 From: Sarah Zebar Date: Thu, 6 Aug 2026 10:12:12 -0500 Subject: [PATCH 06/13] adding seasonal VMT file for annual VMT calculations --- Database/data/seasonal_VMT.xlsx | Bin 0 -> 14711 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Database/data/seasonal_VMT.xlsx diff --git a/Database/data/seasonal_VMT.xlsx b/Database/data/seasonal_VMT.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..7f5f4c4bd8c5fb2cbc828605473a49051e406577 GIT binary patch literal 14711 zcmeHu1w$O$vhD=e;7+jM?(XiA;O_2DaCf)h?k)qtgS$Hf2oT&Ig1t%3y>IW6yYDZ! zr)Q=|y6c-W*?r#8qA}9a=4FChCC1PjmY+~!I zr|e;G;-o|GZevZ94*^D*3jhP1|DWyuum;AGb*y?A(L>IlACbtKd&SqVjnq4q26xEE zp8aUKfc;+aXjw0hS>o@EoFgd5GD6t7&K|Gh+Hs;%#LeJg)OoaOb=OUB)DM(xN+3OR zc->CbLzL9X8XFXAF^KRG85p1vlcC2-R}8z$v7h<&C}|kMoc6kBWDf#R;&pqIJc-Q= z;o3J&)*TP5A@F$WruBQf-zOPX8{IY*PFf`Za5Zjgb(h>RWZi45s7T^3gH^h;x$#0X zsb_I3Eo0S!y4@>8SgxA8i%*j^(JUdC)r0Oy5Dd*_%kzh+Qc*|bu<=GlMd<$E#ZE?FV=^vV%;$f1!@|C(5jCo13*Uo_*92am9&!gj+8EXcyeL3UjH%w{I z`W$I-g{{wb;zG`OO$47ZYuvIu(r!%a3)~BkJzY^##9#w5O=sIwdt{!!e1S$ubQF(1 zmhAB-u`WNVxM7K=-pO0K;g6`?$`7I^d-cP1kx=aq;A_#g;8ag`#MZo)Mk*)MPTqMJ zvVp5O&e}gA3B%(Ap3i^Z{?N|OAy;ED`pIs%=sitbvFJpc#(mtf@Zl9(zG_|(X?Ly9 z$U)f1BZ(0>0fpvs&iwo?uWo9vAE1JOpfKRXh021g7cWVYWJ4Y)+J3Fgi{;g8Qz^;H3 z`PpaY8M@C6j$9CiS|=FLDm`94V!Fyl_2Gx#$4bDib%~TM@b!6sl+>bud#4o(2(`L> z;mKkbvZ}CJKBo(dl{B9hV@s>^-etg1vn%N5qJ`ysD>-SklXiW2(9al{=h?Nht~Fb1 zJvwYHi|@IZdAgFz5XDsW0m|y%YD4B~8;sj~P>Y}X(Ge*)u^@@-spVGdc^i5f7w!na ze4>$>v}dCFXtmS|Q#>g$lhnbyl%~X;*UOJ_-7t15T#Sq>Ex+~$q$r$9RR>|mwXLVa~ZPO>ed`P2qsp=CZ z=Sn6;y5W~y4#~vy!_ecHPEV;_ZJ=G99d9ehB;=AMy6gRbs%s=AUYSA!1i#ixRyp!i zW<;)IC-$wPqEO@^BF+VWKLOT`9IKAGlAfB!4`-?e$(R}5H4Jv8A=@WiZ(1Coz{>f) zp|WRO+i?XOo>r2-MqPeHBZ^G*O5-g<1544?X#G8sW`7!7GVJE^$EB_=Bn-w)p^`y~ zVK(=!SVAHSy>l9480R=bxO;*R-zU3xC@34S!8M)I%iYz2gD!LK%V`&++pSZ?hR9g77zP7pC;~YNN?%(=Q7MFMNDb=G;c$bzn zc^A7(u;APlV%bRo`+S38<4GcOBvKw7S)tg;P+JN%U=D->f^;#ve(jA`x*@f$bFdn~28m zVcTZje&dgj2+zp=O8s*bsY!mrS^KBt-$-TP;G^uboRmNQ`Ln%et+-LNoeBm`J}~VRa?)Kh2S{*rlqxs zr7LsGBlJJHMSra?!|))tXaE5K-~wRYfH?jy&-izy|F@TX0}5wB=l*}ANBTNq^b^j_ry1csPwi>2z zt;|zF6mE!Y?xZ%?^x@pW%iA4FsM016&rC@u7NYI=#r82Ide=T&b}b%;It3kj_f$-J z1hFZdWHAphdFDaY3C5d@Co9J}m^peo`r4O`2+txyB=0L>1V)(A2ISr=5EO`Uo$C15 zPG2IzKkPh(BalEVozNIVrlJq$)klCa4XrXNIQ7I$6GXb*<}Ery;ue+Y&jj-%%6F5( z_mX~O%+MI@^F~W~sb^&E`*<7cwBqD0?e0P-%$1o)r_R6|dt)c^W8Y}V2V?>NGs3#9 z4bg%C4TprV0RYhRzukqCxrvFh6T|N}reA&|Q+?TXn;qSoVagZznjj;RGC?SzyDvKz zQZtvbm6xVI6UIoZx{x+7|8-qt8c&L)mRxcxm{%<{HFYnp{o%S(m#ju*b$)!8y$CIV ze7@Kk^Je#e{rM_3lqQ*6N6#9wzkFG_`JlO6MqusvzIR+}*5@R_>FMybBeruj~+Vi7p<`SF^Pu7lN6TM3 zJRZx+bFw`vbFC8$YKt|iu{L&9)beF7&S5zWMoojU?{g}x8onu-^gr4}Xm`y=zTj-^ zvr_4`c51wKJQ_kb0Dd?CzPljhqKPM?6ZU*H_uF(q8r`ZbGvPAU*S+pvlUr>kE0v!* zX$sajy5?q=jGAzMj_SmA4bALYSMp);79$wd*?zWoPhq<~CS+>6{mlYBbbtz*z?>ul zYgTmQ{rI7vx*J{W0r9vENqEGEQ`s8ONT7PW40Yk328PBv-k1# zs3tCXgBfd__b?6JcOxj}gNbCPj5N4Jqj$Ai)2BG(Sp{US(R*T?EYU29LrRmBeiqgu#(3(^G8*U1jzyBraEKr+>VT{-|PBmM#35!qN$z ziHoe3Q$E~S*5ARHPiUW^IHD7}d~CMBlTVS)a+9&Q;UmnA%82l_r~`4MpQm||NA*r> zh0#lvX3-L+F8%X9eo3U_0Ge0lF6`jJInWXs7cK=R#VqK{OuuVEj1 zmN`p6--?e?|H#klM0f~XD^H!=g}g=dVchyk1Wd$@aUBE24D$3cz~QNQY4 zbw^Q&3WKOXrNLM)3&Er1Ll?o$m=nQX0&)q*mW8BYS+OggfuS+^M|C7!lCx>c`%gH1 zb>EfoyqH$~5%ef=8vSAO^S&x|8a+jEpQ4`wZ_&?Pv>B)B14|sr8Vf(jREuHOY%mpz zzl(&s*Ng@Ixhi()a(JD^9Qd~IhY2Hjrh&yVi@iY0T6Ttd%&2F*#88u-h3YiQ;bnJ)o|@In`;D$wi$s~~mUYua619R+x?i5%&U+uIH~ z(;M_6Kw&NK)+&`S4HiEgij_7zfbJ>%L~w|qL{qAE+=E_Sd3*`mjU_Ag0Wl_ap_Esg z1sdIYe5!SnL1l{Z=_AhDxVnNcQt_GI_0aD-1EOz~HlE7|0v2rAZ?CI;}$;Onij=zcW?oyZWM78P?(VUIkt z7`~2`QD!vP1m-!A9OL}g9luksB7M)u`j#q@R<+H@E1IhlvlfW?TN?@Qyy(oPnCK<5 z_gGtJ2JUfBsRYWkt(4wqL8I?4buV(VAHeMZMk4e%4s;fmGGsjMn(4C3^&)S})}4pp zQVVtoP+68%Dn>T>s^voM>Z}Pe2<~DY6(+xw*VreT+0rMP%w9ht?YdsuKlt7W{G;cP z(l(dp0Oi#@$^Tc+!Tj5Er0dwNa^eP`VSRqpzvpkdCj+?-l5j0qH`h+?wJfW7CDekZ zo%qbce#6&Cg7o?^r0J$&b3BP39xkFCTUQAS^KEt&JNv-O3^8CQL825pLGqEuO|80s zPVDRRLvJu{Y`RUI4`s@HYde82L&im02H}gtjq1E!#$Nrm7-WMr?bw{=)$twYm9d;r zm1)^>xfbzJBbAy6I-jbX;_+ho$j~fvVCD?%Xi0@(9lJ1lD`QTuGd#1`&s!GfH z3Xw|-ZPWP%F9Z8H|B9uL{1+7^U+-n@v5I*p;!fI>$dfyrsS9(quBZFP>cg#3)WzrM zb3^{0s@n|x0!;$rr|!t z;htYkeYZ0zLLpCUTgsJm_;q9LhIh=W2WK-Xbikg?lsefa_Tq;J8B}iOS-tu^n1jqm zOt?7Gn5fUUf$a>bqemC-g0psObd;}fh)Z;2@2>b?LUrE0s>TwG3~rgUJS%rRtJ7y^ zH@oZK2W_v&I%@NKeYCaJ{wTdLeJm0YpWxR0+ zeG*CS2O>4|jaSKjrt64jR%-&0mZ|ES5^6IX1CPg#!!JVp+xDF*&hlCq9jZF8NKo_C z`YO9z?-RCft@_EhuCK(|2n{i^W>v3rE2>E)Pt#QVR+6mBlD}()X_MJ@;Txi7&5E1U zD5*KRtGcobk5TKhnzblKnc)n+QZp46?{YrI3-2|4oIjdN#z&pv2EuX9vrdwYe;z5? zD&w6O$;@|JDLZvJlva)_0bNyuB^~7Fa*yh_ELo{V5Khm2;e;Ktswkt##F-z*sko;N zbenruEGM!7LyU?Zval$A>K#6O?P5vw`PU7=w(3}(9H0q!ZnHuIuhD>g$noXJ9K92}Do1bLh@G7ap0&$Vgd7J6$ z6k2cm-n9Ua5eHL1z_`NOwrSi4ri`W$9LYlvhXE&rTCrB~TBE?BDjK*^;>=E$41dc| zXu4!r`g!@*n_SEmpjX7VRuWW9ktMR_)$wlv;f9H=vOE@dlrzZX91c1t;i~8FW+yWG z#!h9_@N=#`(Jf%+j}|e+*hFZUWhNTPbq<+N3iVRuNu{A9O90?^y9l9GIrf3Zv8=&m zm~4SygoTAYE%d%DW-v3QG9^pZ{U41NxAo1NMQ~NK5-bKBtIMQq_os*@S+bD8F`|DT z#t4Q4C(#7U;b|55EUv@bUtsls{!6jleqoQFWF^HKCm^WtBR=re>99jsjs@G(Vp!n6qq@r4eaR#$tx>1E`D%a4`c!EsF zv~nTcp5Imt*fAEZd*+)v-?7f(XK<)11XyZHS*wsAzsgOU*&WRvBsZCeLb!LT z=1N%lP+$=Z~Piw|MkRP>6S;I`9hm6)iSLK*zQ?6(WTJaoY z3#NO+4s_DhQ)Q3jMEvlSn`M49wq@0P1P(PC(uT(xZAiP+nf0rqFmJZ@xPB&dbk z^^D0d77UiJocb~`tT@+1uRRg|(=c^*SqGgJl+}Cy1swm&FqP$Zu#ut_yTXkgyg_p# zAnHMJL579*W*z~7+q+cx=BIVQ8><9PARiPrl$l>XE)$8ll5cf2_Sd|u6Oip36fb4n~9-q0B9mj`O7<^5h z7>)^-URL0|IC~FyYa-oPWurw>gMV-9^z2`|Qc_kr`X+VXc=Hph~uH=XM7z9Kyj-I48| zr+ryz-kSQfjoDYEY~R0frLAqQW+IsT7Y81jrXz7?B?sbYPr&Bv8Ed}8P!tpepxstP zL}^EFfgi1RXI6Fv zP8hBq?a+osClK08Jo*v|&sdfhN)zaehrJo3ue$4?Y*RHmK55os2DfoKY}yk(JhUGQ z!wk;eg!Tg4C(<>^Upm;ISKf64bqa|O?^&0j$SUnt+j;15c{@+)!^h>#CiOOvN)TU? zh*>Q$E_<`TbgvDOnx7Eag1UVZl}dY(3QWP7uojJtBHo;!Hdt$wue}D(jRd5w@*`ALjU9+*ySIXgDCmy z8oxQ6XPRUh!zhW57Eq91f16t7u1m=Y(x_Mv2WsEEL!TH8B9BDH=2?5_JoMZV=Gjkv ztU!F~kDEI3nv7P}Yz`OZ?}sevoEJ9u73!<_5|w{x3{p{mrx_x!4Rw(7a3X zPeR&_aDTyip|26-crHlE<>e=9OyKHoWNr3jR9-!y6^F_Xh&5p&nVNFa+;~NvylgEU zA#4gQ(GJJ8rE@W;Q*F|w2sfH1(8vZZ+4q2!#CceZ*Idu{#Qanp92kCNlIC*4G*)e4 zOz)}9zoeDD)zqd+vi;IuMxS=TdhW$JH#g?C25I%h`am-5`aOaQ`iHOL;UeHw?}%|N zZJB&N4o_%XM7u*Q+II*z$0*8$hGkV2bs#88Mf+e+-(N8HV(U_W$}a1#FtpOn{B2^bn<*uAsuTftM|pcOcWYZ> z=C619xRE|qAxB}%rQ4r>j(&c}#O@ESgobqWlM(4|-Cg1Jd;lS;&b2*=K|8gctuVxJ zs-aLcHen5CMb)Ka#6)sfUZW!YsImtNI;wLLK$TR#D3!BwkQ)C2`A(o^0%je)A_Gc76mV~Ob8_tZ;;zlwn^}=bl z2`{IKX$~x%c4vm-2^4uQ1F6+2-O?{_V6Es#k*zl9mt9v1($;0X)n%Bs7Pm9)K z1zN*gMT3lv{k(hJ6j!5zKA$CxdLfL5>FGOVer=$VF(UoWo|Q~N#SPWPM7KztoQwZH z;fs8Lp}nU!H<{5fLXnJ{+fKW}COe8Ydz8f|A|0b%VFQX#mGJK}1T%A7!i^`w0%)$h zeRn}eihYp0=4}`^dns-VDbw<{qWzd!gkj&0xc9o0X27dK3|ew@7O$Zfc-0VrE< z{fzdRLRxr12Sg7t&O}9?&Ym^3@(B!D<{r;%wJq+?S3v1r>1}-fcCj=0l}2%QWA!T% z6tUl0;$wq%rCf7wFM>5h9|)lw=bGX<~}*PDzY!$CEWp z6w7*jAFk$-BVbm#B^y%O{a`oD6TI;G<%hK!*A%)dDul8HJY6r(4~Bd76bSgZJ?@>> zn;lJ-bcBXwn>`A$keZg>Cr zP(#7V3@XA6$Yrbt*JA4`VL485r^ZV zqJ*iVs^hRP>l;yml=148yH1>OfYGg?v9hG?m|>bjNK9-!?l^Q15jOOpl*OOE-o=Gk zlOm-Ys1M$>_{mN(n#lVGa5XP$D;TtE&eR0-EX{T*q}GMYLUJ`ed=rT}7$V?7c#l3= zl_`aKu%vKLoJ8qp%V-dI#&U%ie-{UxWG#1R6As zC5Epd$rE>_r`5#7lsoWAE?2=^%mY{+RetRm_TN!mz3Di{2Q(>%ZH140bS14Fsg|8+ zG5w^)Sf=}?HbPxRF#aIrN2`mwqq9a?hj=j}s%A?XX(Myg6vW_ z^or)Z+-dX9SZx^;t|CO%>ErCGUh-xm?AadsSScVT zSQdp<=Qhg1sZw>G1(oI%7h?8#g&(5wBR!zhNLq^vP8XP_PA{261UW=F(}!Viv&_~S zN-S}>Bj9;y&oE`R1;UY=wTWqA+)xdvfo$6yRW7Z9?Pp$WfG|#Nvqr+_J+QItnW0y{rWq) zyAY&WSr7vfRe+eDYfR=aR6EI?Xs37(jahs`lV{hKTYK$pXp!{nS!#Q$8Wr2Ke8=3y z^C#e$8cm1o$s1W(l86eQ+i4R3w32h0?1V*L=RNVS87(xbz+VGb_PwhSvMdOa8G=lH^R|08^=+QqU^-6^}2088wY z_FR$!4y~dPwF;MZ@si~`Zlp^Sgecy`SYAwI-F~Y(yMIh=J~B|UK7(Q)1JLX%;=g>D zle34liPNvZr%*);R6&96qi69NxZ`F?Bq#+DC5=`n%~Fv(6TdtECQGtEd|K=NyX1=ng`N0zNO|cM^CoC{!$WfhTvvP zm#m#B?y`?A(o7*RoOdfPg&!L~eoU~DR$ZFYWGr@PlVXrKbFd$?Yz}MSRsN9r*EhMk$dWdWS7mca8l;Cg> z+QP0~_c{I!?8bVB2z{Ax>DsccoR|93F*qZ&Oi&v78)hZ+M;0E;L+n!0CtisButuH~Q%OB2B z!xlTRd&E8%`MX@omoT5rD(F%otR5Bky8S$QY2`7y>#}~Y%j&UhpEg!w7CuFp#q6$2 zzA-u;st|sTP@3ydnkrS|?U>W$o9Z!1k}cLHYq@(%FV|5Cg!DbpjApt#9s(Ow;4bMT zLmXMuY_OT>w|33YWc&|x0TOXK%_IM^EW-_Yp-Z_$PY8heHX zHK5bEYl&Hiod9oHyBXesy=;I(2J9lnrrvA89ktx^#K=)(!;%hGU2M&Tcftl3VUf71 zUL(=zB81IQk-e>N62C}RAH#IY^V^ix?|K*gz;`j_HZQFas5cb6p!Nubyv=?(oCRx* zkXhl_RzrY)i)Z?!B4TZJPsF4akyaS*#^uIE4?pHY->=y2zBa7}i1ctoYqQuJ=H~yy ze83Cw8cB9rff!Vl`45fnH`VGO18RITP)CUZDnc=~Gg5T4vv*=JvU4=~)lq^fH2+h3 z0%C<%f}T|`5qkeG26W$v${i4rN*UmJYZ^>NMR#&_*!1SZ9;V!`PLkTB%+yJoalP>F z8P@ZbGv7lQMM{^1i9rXScb;*d1i<*4zS7yUj z^F!p7(jq@Zf0tQ-GoXqu=z!-Ddb?H49Kqwu>Z$E?F?{D|By6hgzn#DnqouEoB@X-}O#h8>U$P;NHdQr3JuXH;JpT+E0-jijyae(hOmXePJeK(C6SZ9%5n&!;p z55)Pn&ay2>Ra00CC>Wc zFg6r5&2#}agz9z0Ru9Sv{(}Wl*eto!f-KMtWS_`?w?G4X`~MgqNM--EWhTnmt^O*0 z0>33hSi@`4P(|>s%$MZ3t~GqKJb^mb>cJ;A4i}I0wwf5IJ(W~L*{UZ6|VaGyba+_gX34|m#2ZxFsGF4Kf@7 zq>%&6-in8{sv{eWp*{UEqIldAr^Fbd#@C!3Rmh)y?ranU*y8Ibdq`jF6xXt!I+1KR zB(id?&PwaoIuWGrDg^M%KN#>L(slXlpWCNyw6FHmE^$s~z_NGRCLI|XMfhO5^$n8W zHAj5kG2aubt5EhMS@+;RR7SqL(Cxk@&ya2bM`uXCi+%~`i++{V)uo$Zu<+t*NdI0V zApY`?{VWvQ>G5}vm8XDQFlf=r-}+e>CucjG{}}pzn>hf`m@E^y%7`9(7yJUfePd2L z{7Id7n9&0P!Ffb*hQ1ZH-Z=}~aCu33Me*lG#WjZZ{y;yTe;nt}i5+`Z@B0t$3RoI- zG}<&|PaW|6S%7qFKA65s{CTu7+%;MAgDc&%oq|{bV;h}molP#_RSbEN0YOKm7u}Dh z38YzEf<6)Tz4_WXI+k$sumdTON)@3CIzGBTePrL;0= zbnYBHEx=B_e#$(dVk9%1(7v>8jm}3H#q4X+p>!MjE0>e@;0!nmr79dcJk!ObADQ4v z$g6e#9Nm3zxs%_s|0Xq-6p%@h`+>L^TdW0xsviH61ibe{;>m*io zc;F}r;ePUqmT+jn2b+o-2GJ?OY$Ny7GA3ovCI%HnX>mtDGI0_Yh3>snYNRJd?ZNri z62EFYB?(a@vv4**9cAu2$PVR^6GS5+-lZb;GQtRx=7UihT9C)>ejuV^nnc7Bt#{Z$ zmv&Jvp|#o*aiN#?JppRPepezX2r;z1=?s-P*GXCzGa!2fld~lpdEx;z@xP+aH(+$2 zNb{f9bNyup|N8U~tGg6s{vF`o*O&Yqpbo^vzpXa;Q}E9!`@ckgfN1(h&HbOk|6acP zmnZ-*1ovC`e<|ku6X(y`&A*V)K%>_Gx`_W#$@wSBpLINcp~!*qxBr0hyQ=3;ls_lv z{z7TR`$v@D({+EM{5kpX7YZpT1o($*`8^f!C(55G=)X{miGQQ~nUMYy;Lq{@UjUSp zzXATr2K*`d=aA?xQAL`6iT*i2`V-;b Date: Thu, 6 Aug 2026 10:15:24 -0500 Subject: [PATCH 07/13] Adding script for validating createMOVESinputfile results --- .../post_macros/QC_createMOVESinputfile.py | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 Database/post_macros/QC_createMOVESinputfile.py diff --git a/Database/post_macros/QC_createMOVESinputfile.py b/Database/post_macros/QC_createMOVESinputfile.py new file mode 100644 index 0000000..cd8d1d9 --- /dev/null +++ b/Database/post_macros/QC_createMOVESinputfile.py @@ -0,0 +1,90 @@ +import pandas as pd, numpy as np +from pathlib import Path +from functools import reduce + +## This file runs two quality checks for createMOVESinputfile.py +## (1) check_im(): Checks if all tabs in two comparison workbooks match for a given imregion and scenario +## (2) check_im_county(): Checks if the VHT/VMT in initial_model_output for each county in a given imregion +## sum up to the correct aggregated values + +### TO RUN: specify the scenario year and model ################################################################### +### This set-up assumes the files are in data/MOVES_cXXqX_scenXXX. The files you want to compare to must have +### the suffix "_old", for example MOVES_c26q2_scen100_IM_old.xlsx and MOVES_c26q2_scen100_nonIM_old.xlsx +SCEN = "600" +MODEL = "c26q2" +################################################################################################################## + +DB_DIR = Path(__file__).resolve().parents[1] +FOLDER_PATH = DB_DIR.joinpath("data",f"MOVES_{MODEL}_scen{SCEN}") + +def check_im(scen, imregion): + """" + Compares the new and old Excel workbooks for a specific IM region and scenario, + ex. MOVES_c26q2_scen100_IM.xlsx and MOVES_c26q2_scen100_IM_old.xlsx + Prints True if all cells match, False otherwise. + """ + # Get paths of new and old files + new_file_path = FOLDER_PATH.joinpath(f"MOVES_{MODEL}_scen{scen}_{imregion}.xlsx") + old_file_path = FOLDER_PATH.joinpath(f"MOVES_{MODEL}_scen{scen}_{imregion}_old.xlsx") + + tab_names = ["initial_model_output","AvgSpeedDistribution", "RoadTypeDistribution","hourVMTFraction", "HPMSDailyVMT"] + + print("check_im()") + print(f"... Comparing MOVES_{MODEL}_scen{scen}_{imregion}.xlsx and MOVES_{MODEL}_scen{scen}_{imregion}_old.xlsx") + + # Check equality of each tab + for tab in tab_names: + old_data = pd.read_excel(old_file_path,sheet_name=tab) + new_data = pd.read_excel(new_file_path,sheet_name=tab) + + print(f"--> {tab} equality: {old_data.equals(new_data)}") + + +def check_im_county(scen, imregion): + """ + Checks to see if the VMT/VHT in the initial_model_output tab from each county sum up to the aggregated VMT/VHT. + For VMT and VHT, prints True if they match, False otherwise. + """ + # Specify counties for given IM region + if imregion == "IM": + counties = ['COOK', 'DUPAGE', 'KANE', 'KENDALL', 'LAKE', 'MCHENRY', 'WILL'] + if imregion == "nonIM": + counties = ['KANE', 'KENDALL', 'LAKE', 'MCHENRY', 'WILL','GRUNDY'] + + # Merge all county initial_model_output datasets together for given imregion + dfs = [] + for county in counties: + county_file_path = FOLDER_PATH.joinpath(f"MOVES_{MODEL}_scen{scen}_{imregion}_{county}.xlsx") + + # get initial_model_output tab from county file + initial_model_output = pd.read_excel(county_file_path,sheet_name="initial_model_output") + initial_model_output = initial_model_output.rename(columns={"vmt": f"vmt_{county}", "vht": f"vht_{county}"}) + + dfs.append(initial_model_output) + + ids = ["sourceTypeID","roadTypeID","hourDayID","avgSpeedBinID","imarea"] + merged_df = reduce(lambda left, right: pd.merge(left, right, on=ids, how='outer'), dfs) + + # Create totals for VMT/VHT + merged_df["vmt_TOTAL"] = sum([merged_df[f"vmt_{county}"] for county in counties]) + merged_df["vht_TOTAL"] = sum([merged_df[f"vht_{county}"] for county in counties]) + + # Use OLD aggregated file for given im region + aggregated_file_path = FOLDER_PATH.joinpath(f"MOVES_{MODEL}_scen{scen}_{imregion}_old.xlsx") + agg_initial_model_output = pd.read_excel(aggregated_file_path,sheet_name="initial_model_output") + + # Check for approximate equality (necessary because floats, tolerance = 1e-8) + print() + print("check_im_county()") + print(f"... Aggregating {counties}") + print(f"... Comparing to MOVES_{MODEL}_scen{scen}_{imregion}_old.xlsx") + print("--> VMT Equality:", np.all(np.isclose(merged_df["vmt_TOTAL"], agg_initial_model_output["vmt"]))) + print("--> VHT Equality:", np.all(np.isclose(merged_df["vht_TOTAL"], agg_initial_model_output["vht"]))) + print() + + +if __name__ == "__main__": + for imregion in ["nonIM", "IM"]: + print(f"** SCENARIO YEAR: {SCEN}, REGION: {imregion} **") + check_im(SCEN, imregion) + check_im_county(SCEN, imregion) \ No newline at end of file From f28fad26cea7ac2858e6b5f4d68cd3ae64096471 Mon Sep 17 00:00:00 2001 From: Sarah Zebar Date: Thu, 6 Aug 2026 15:36:38 -0500 Subject: [PATCH 08/13] Added county and full_region exportAs options --- Database/batch_file.yaml | 3 +- Database/post_macros/createMOVESinputfile.py | 606 +++++++++++-------- 2 files changed, 360 insertions(+), 249 deletions(-) diff --git a/Database/batch_file.yaml b/Database/batch_file.yaml index 4cc2339..9877e1f 100644 --- a/Database/batch_file.yaml +++ b/Database/batch_file.yaml @@ -10,10 +10,11 @@ year: 2040 # make sure this matches scenario_code # 600: 2040 # 800: 2050 -exportAs: "county" +exportAs: "full_region" # "im" to just output IM/nonIM Excel workbooks # "im_county" to output IM/nonIM Excel workbooks for each county in the region # "county" to output workbooks for each county (include both IM and nonIM regions) +# "full_region" for the entire CMAP region # ---------------- Work from home module inputs (trip generation) validationfiles: N diff --git a/Database/post_macros/createMOVESinputfile.py b/Database/post_macros/createMOVESinputfile.py index c0c4af9..c6d9dfc 100644 --- a/Database/post_macros/createMOVESinputfile.py +++ b/Database/post_macros/createMOVESinputfile.py @@ -195,12 +195,14 @@ def speed_class(mph): return links -def agg_links(groupcols, links): - """ This aggregates the link data to VMT/VHT by the group cols. Outputs the b dataset that is used by the tabs. - Expands dataset to include all combinations of group cols. - """ +def agg_links(links, imarea=None): - # Define TBM vehicle types + if imarea is None: + groupcols = ['roadTypeID', 'timeperiod', 'avgSpeedBinID', 'hours'] + else: + groupcols = ['roadTypeID', 'timeperiod', 'avgSpeedBinID', 'hours', 'imarea'] + + # Define TBM vehicle types vtypes = ['auto','bplate','sush','mtrucklh','htrucklh','htruck','bus'] aggsums = {f"{vtype}_{stat}": "sum" for vtype in vtypes for stat in ["vmt", "vht"]} @@ -230,8 +232,9 @@ def agg_links(groupcols, links): b1["hr"] = b1.apply(lambda x: times[x["timeperiod"]], axis=1) b1 = b1.explode("hr") + b1['hourDayID'] = b1['hr']*10+5 #'5' indicates a weekday - b1.sort_values(['imarea','roadTypeID','avgSpeedBinID','timeperiod','hourDayID'], inplace=True) + # b1.sort_values(['imarea','roadTypeID','avgSpeedBinID','timeperiod','hourDayID'], inplace=True) #### Restructure the data from wide to long (VMT/VHT columns) and add sourceTypeID column for HPMS vehicle codes mapping = { @@ -244,7 +247,10 @@ def agg_links(groupcols, links): "bus": [42, 41, 43] } - ids = ['roadTypeID', 'timeperiod', 'avgSpeedBinID', 'hourDayID', 'imarea'] + # Replace hours with hourDayID in groupcols + groupcols.remove("hours") + groupcols.append("hourDayID") + # Create subsets for each sourceTypeID and append together dfs = [] @@ -252,7 +258,7 @@ def agg_links(groupcols, links): for stype in source_type_lst: # Filter for just ids and vehicle type columns, rename, and add source type code - b1_source_type = b1[ids+[col for col in b1.columns if col.startswith(f"{vtype}_")]].copy() + b1_source_type = b1[groupcols+[col for col in b1.columns if col.startswith(f"{vtype}_")]].copy() b1_source_type = b1_source_type.rename(columns={f'{vtype}_vmt':'vmt', f'{vtype}_vht':'vht'}) b1_source_type['sourceTypeID'] = stype @@ -260,17 +266,29 @@ def agg_links(groupcols, links): b_temp = pd.concat(dfs) + hrday = [(hr*10)+5 for hr in HOURS] + + # If aggregating IM,nonIM, don't include im/nonIM region in template + if imarea is None: + template_values = list(product(SOURCE_TYPES, ROAD_TYPES, hrday, SPEED_BINS)) + template_cols = ['sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'] + template = pd.DataFrame(template_values, columns=template_cols) + template.sort_values(template_cols, inplace=True) + template.reset_index(drop=True, inplace=True) + + else: + template_values = list(product(SOURCE_TYPES, ROAD_TYPES, hrday, SPEED_BINS, [0,1])) # [0,1] is for IM region + template_cols = ['sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID', 'imarea'] + template = pd.DataFrame(template_values, columns=template_cols) + template.sort_values( ['imarea','sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) + template.reset_index(drop=True, inplace=True) + #### Apply data to template (all ID combinations) - hrday = [(hr*10)+5 for hr in HOURS] - template_values = list(product(SOURCE_TYPES, ROAD_TYPES, hrday, SPEED_BINS, [0,1])) # [0,1] is for IM region - template = pd.DataFrame(template_values, columns=['sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID', 'imarea']) - template.sort_values(['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) - template.reset_index(drop=True, inplace=True) # Merge data with template - b = pd.merge(template, b_temp, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID']) - # b.fillna(0, inplace=True) #remove null values + b = pd.merge(template, b_temp, how='left', on=template_cols) + b.fillna(0, inplace=True) #remove null values b.drop(columns='timeperiod', inplace=True) #remove negative vmt/vht values, if they exist, or fill with zeroes @@ -295,278 +313,332 @@ def get_initial_model_output(b, imarea=None): def get_avg_speed_distribution(b,imarea=None): - casecols = ['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID'] - - sumvht = b.groupby(casecols).agg({'vht':'sum'}) - sumvht.rename(columns={'vht':'allvht'}, inplace=True) - sumvht.reset_index(inplace=True) - share = pd.merge(b, sumvht, on=casecols, how='inner') - - #bus, pt 1: use roadTypeID 4 to replace missing values for roadTypeID 2 for sourceTypeID 41,42,43 for IM area - fb1_a = share.loc[(share['sourceTypeID']==42)&(share['roadTypeID']==4)&(share['imarea']==1)].copy(deep=True) - fb1_a['roadTypeID'] = 2 - fb1_b = fb1_a.copy() - fb1_b['sourceTypeID'] = 41 - fb1_c = fb1_a.copy() - fb1_c['sourceTypeID'] = 43 - fb1 = pd.concat([fb1_a, fb1_b, fb1_c]) - - #bus, pt2: use sourceTypeID 41,42,43 for IM area to replace missing values for non-IM area - fb2 = pd.concat([fb1, share.loc[(share['sourceTypeID'].isin([41,42,43]))&(share['imarea']==1)].copy(deep=True)]) - fb2['imarea']=0 - - #SU long-haul truck, pt1: use sourceTypeID 52 to replace missing values for sourceTypeID 53,54 for IM area - fb3 = share.loc[(share['sourceTypeID']==52)&(share['imarea']==1)].copy(deep=True) - fb3_a = fb3.copy() - fb3_a['sourceTypeID'] = 53 - fb3_b = fb3.copy() - fb3_b['sourceTypeID'] = 54 - fb3 = pd.concat([fb3_a, fb3_b]) - - #SU long-haul truck, pt2: use sourceTypeID 52,53,54 for IM area to replace missing values for non-IM area - fb4 = pd.concat([fb3, share.loc[(share['sourceTypeID']==52)&(share['imarea']==1)]], ignore_index=True) - fb4['imarea'] = 0 - - #MU long-haul truck pt1: use sourceTypeID 61 to replace missing values for sourceTypeID 62 for IM area - fb5 = share.loc[(share['sourceTypeID']==61)&(share['imarea']==1)].copy(deep=True) - fb5['sourceTypeID'] = 62 - - #MU long-haul truck pt2: use sourceTypeID 61, 62 for IM area to replace missing values for non-IM area - fb6 = pd.concat([fb5, share.loc[(share['sourceTypeID']==61)&(share['imarea']==1)].copy(deep=True)]) - fb6['imarea'] = 0 - - #combining this whole mess together - fallback = pd.concat([fb1, fb2, fb3, fb4, fb5, fb6], ignore_index=True) - fallback.rename(columns={'vht':'vht2', 'allvht':'allvht2'}, inplace=True) - fallback.drop(columns='vmt', inplace=True) - fallback.drop_duplicates(['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) - fallback.sort_values(['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) - - share = pd.merge(share, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID']) - share.loc[(share['allvht']==0)&~(share['allvht2'].isnull()), 'vht'] = share['vht2'] - share.loc[(share['allvht']==0)&~(share['allvht2'].isnull()), 'allvht'] = share['allvht2'] - share.eval('avgSpeedFraction = vht / allvht', inplace=True) - - avg_speed_dist = share[['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID','avgSpeedFraction']] + # If aggregating IM and nonIM, don't include replacement data if imarea is None: + casecols = ['sourceTypeID', 'roadTypeID', 'hourDayID'] + sumvht = b.groupby(casecols).agg({'vht':'sum'}) + sumvht.rename(columns={'vht':'allvht'}, inplace=True) + sumvht.reset_index(inplace=True) + share = pd.merge(b, sumvht, on=casecols, how='inner') + share.eval('avgSpeedFraction = vht / allvht', inplace=True) + avg_speed_dist = share[['sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID','avgSpeedFraction']] return avg_speed_dist + + # otherwise, fill will fallback data else: + casecols = ['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID'] + sumvht = b.groupby(casecols).agg({'vht':'sum'}) + sumvht.rename(columns={'vht':'allvht'}, inplace=True) + sumvht.reset_index(inplace=True) + share = pd.merge(b, sumvht, on=casecols, how='inner') + + #bus, pt 1: use roadTypeID 4 to replace missing values for roadTypeID 2 for sourceTypeID 41,42,43 for IM area + fb1_a = share.loc[(share['sourceTypeID']==42)&(share['roadTypeID']==4)&(share['imarea']==1)].copy(deep=True) + fb1_a['roadTypeID'] = 2 + fb1_b = fb1_a.copy() + fb1_b['sourceTypeID'] = 41 + fb1_c = fb1_a.copy() + fb1_c['sourceTypeID'] = 43 + fb1 = pd.concat([fb1_a, fb1_b, fb1_c]) + + #bus, pt2: use sourceTypeID 41,42,43 for IM area to replace missing values for non-IM area + fb2 = pd.concat([fb1, share.loc[(share['sourceTypeID'].isin([41,42,43]))&(share['imarea']==1)].copy(deep=True)]) + fb2['imarea']=0 + + #SU long-haul truck, pt1: use sourceTypeID 52 to replace missing values for sourceTypeID 53,54 for IM area + fb3 = share.loc[(share['sourceTypeID']==52)&(share['imarea']==1)].copy(deep=True) + fb3_a = fb3.copy() + fb3_a['sourceTypeID'] = 53 + fb3_b = fb3.copy() + fb3_b['sourceTypeID'] = 54 + fb3 = pd.concat([fb3_a, fb3_b]) + + #SU long-haul truck, pt2: use sourceTypeID 52,53,54 for IM area to replace missing values for non-IM area + fb4 = pd.concat([fb3, share.loc[(share['sourceTypeID']==52)&(share['imarea']==1)]], ignore_index=True) + fb4['imarea'] = 0 + + #MU long-haul truck pt1: use sourceTypeID 61 to replace missing values for sourceTypeID 62 for IM area + fb5 = share.loc[(share['sourceTypeID']==61)&(share['imarea']==1)].copy(deep=True) + fb5['sourceTypeID'] = 62 + + #MU long-haul truck pt2: use sourceTypeID 61, 62 for IM area to replace missing values for non-IM area + fb6 = pd.concat([fb5, share.loc[(share['sourceTypeID']==61)&(share['imarea']==1)].copy(deep=True)]) + fb6['imarea'] = 0 + + #combining this whole mess together + fallback = pd.concat([fb1, fb2, fb3, fb4, fb5, fb6], ignore_index=True) + fallback.rename(columns={'vht':'vht2', 'allvht':'allvht2'}, inplace=True) + fallback.drop(columns='vmt', inplace=True) + fallback.drop_duplicates(['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) + fallback.sort_values(['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) + + share = pd.merge(share, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID']) + share.loc[(share['allvht']==0)&~(share['allvht2'].isnull()), 'vht'] = share['vht2'] + share.loc[(share['allvht']==0)&~(share['allvht2'].isnull()), 'allvht'] = share['allvht2'] + share.eval('avgSpeedFraction = vht / allvht', inplace=True) + + avg_speed_dist = share[['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID','avgSpeedFraction']] return avg_speed_dist.loc[(avg_speed_dist['imarea']==imarea)].drop(columns='imarea') def get_road_type_distribution(b, imarea=None): - roadtype = b.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() - roadtype2 = b.groupby(['imarea','sourceTypeID']).agg({'vmt':'sum'}).rename(columns={'vmt':'sourceVMT'}).reset_index() - - roadtype = pd.merge(roadtype, roadtype2, how='left', on=['imarea','sourceTypeID']) - - #ensure correct datatypes - for f in ['sourceTypeID', 'roadTypeID', 'imarea']: - roadtype[f] = roadtype[f].astype('int') - for f in ['vmt','sourceVMT']: - roadtype[f] = roadtype[f].astype('float') - - #bus part1: use roadTypeID 4 to replace missing values for roadTypeID 2 for sourceTypeID 41,42,43 for IM area - fb1 = roadtype.loc[(roadtype['sourceTypeID']==42)&(roadtype['roadTypeID']==4)&(roadtype['imarea']==1)].copy(deep=True) - fb1_a = fb1.copy() - fb1_a['roadTypeID'] = 2 - fb1_b = fb1_a.copy() - fb1_b['sourceTypeID'] = 41 - fb1_c = fb1_b.copy() - fb1_c['sourceTypeID'] = 43 - fb1 = pd.concat([fb1_a, fb1_b, fb1_c], ignore_index=True) - - #bus part2: use sourcetypeID 41, 42, 43 for IM area to replace missing values for non-IM area - fb2 = pd.concat([fb1, roadtype.loc[(roadtype['sourceTypeID'].isin([41,42,43]))&(roadtype['imarea']==1)].copy(deep=True)], ignore_index=True) - fb2['imarea'] = 0 - - #SU long-haul truck part1: use sourcetypeID 52 to replace missing values for sourceTypeID 53,54 for IM area - fb3 = roadtype.loc[(roadtype['sourceTypeID']==52)&(roadtype['imarea']==1)].copy(deep=True) - fb3_a = fb3.copy() - fb3_a['sourceTypeID'] = 53 - fb3_b = fb3_a.copy() - fb3_b['sourceTypeID'] = 54 - fb3 = pd.concat([fb3_a, fb3_b], ignore_index=True) - - #SU long-hault truck part2: use sourcetypeID 52. 53. 54 for IM area to replace missing values for non-IM area - fb4 = pd.concat([fb3, roadtype.loc[(roadtype['sourceTypeID']==52)&roadtype['imarea']==1].copy(deep=True)]) - fb4['imarea']=0 - - #MU long-haul truck part1: use sourceTypeID 61 to replace missing values for sourcetypeID 62 for IM area - fb5 = roadtype.loc[(roadtype['sourceTypeID']==61)&(roadtype['imarea']==1)].copy(deep=True) - fb5['sourceTypeID'] = 62 - - #MU long-haul truck part2: use sourceTypeID 61,62 for IM area to replace missing values for non-IM area - fb6 = pd.concat([fb5, roadtype.loc[(roadtype['sourceTypeID']==61)&(roadtype['imarea']==1)].copy(deep=True)]) - fb6['imarea'] = 0 - - fallback = pd.concat([fb1,fb2,fb3,fb4,fb5,fb6]).rename(columns={'vmt':'vmt2', 'sourceVMT':'sourceVMT2'}).sort_values(['imarea','sourceTypeID','roadTypeID']).drop_duplicates(['imarea','sourceTypeID','roadTypeID']) - - roadtype = pd.merge(roadtype, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID']) - # roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), ['vmt', 'sourceVMT']] = roadtype[['vmt2', 'sourceVMT2']] - roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), 'vmt'] = roadtype['vmt2'] - roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), 'sourceVMT'] = roadtype['sourceVMT2'] #prevent division by zero def abovezero(x): return np.maximum(x,0.000001) - roadtype['sourceVMT'] = roadtype['sourceVMT'].apply(abovezero) - - roadtype.eval('roadTypeVMTFraction = vmt / sourceVMT', inplace=True) - roadtype['roadTypeVMTFraction'] = roadtype['roadTypeVMTFraction'].round(6) + # meaning data is not divided up by IM/nonIM if imarea is None: - road_type_distribution = roadtype[['sourceTypeID','roadTypeID','roadTypeVMTFraction','imarea']].copy() + roadtype = b.groupby(['sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() + roadtype2 = b.groupby(['sourceTypeID']).agg({'vmt':'sum'}).rename(columns={'vmt':'sourceVMT'}).reset_index() + roadtype = pd.merge(roadtype, roadtype2, how='left', on=['sourceTypeID']) + #ensure correct datatypes + for f in ['sourceTypeID', 'roadTypeID']: + roadtype[f] = roadtype[f].astype('int') + for f in ['vmt','sourceVMT']: + roadtype[f] = roadtype[f].astype('float') - else: - road_type_distribution = roadtype.loc[roadtype['imarea']==imarea,['sourceTypeID','roadTypeID','roadTypeVMTFraction']].copy() - return road_type_distribution + roadtype['sourceVMT'] = roadtype['sourceVMT'].apply(abovezero) + roadtype.eval('roadTypeVMTFraction = vmt / sourceVMT', inplace=True) + roadtype['roadTypeVMTFraction'] = roadtype['roadTypeVMTFraction'].round(6) + + return roadtype[['sourceTypeID','roadTypeID','roadTypeVMTFraction']].copy() -def get_ramp_fraction(links, imarea=None): - - rmp = links.loc[links['roadTypeID'].isin([2,4])].copy(deep=True) - rmp.eval('fwyvht = auto_vht + bplate_vht + sush_vht + mtrucklh_vht + htruck_vht + htrucklh_vht + bus_vht', inplace=True) - rmp.eval('fwyvmt = auto_vmt + bplate_vmt + sush_vmt + mtrucklh_vmt + htruck_vmt + htrucklh_vmt + bus_vmt', inplace=True) - rmp['rampvht'] = np.where(rmp['isramp']==1, rmp['fwyvht'], 0) - rmp['rampvmt'] = np.where(rmp['isramp']==1, rmp['fwyvmt'], 0) - - ramp = rmp.groupby(['imarea','roadTypeID']).agg({'fwyvht':'sum','rampvht':'sum','fwyvmt':'sum','rampvmt':'sum'}).reset_index() - ramp.eval('rampFraction = rampvht/fwyvht', inplace=True) - ramp['rampFraction'] = ramp['rampFraction'].round(6) - ramp.eval('vmtFraction = rampvmt/fwyvmt', inplace=True) - ramp['vmtFraction'] = ramp['vmtFraction'].round(6) - - # Output ramp fraction for im area - if imarea is None: - ramp_fraction = ramp[['roadTypeID','rampFraction', 'imarea']] else: - ramp_fraction = ramp.loc[ramp['imarea']==imarea,['roadTypeID','rampFraction']] - return ramp_fraction + roadtype = b.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() + roadtype2 = b.groupby(['imarea','sourceTypeID']).agg({'vmt':'sum'}).rename(columns={'vmt':'sourceVMT'}).reset_index() + + roadtype = pd.merge(roadtype, roadtype2, how='left', on=['imarea','sourceTypeID']) + + #ensure correct datatypes + for f in ['sourceTypeID', 'roadTypeID', 'imarea']: + roadtype[f] = roadtype[f].astype('int') + for f in ['vmt','sourceVMT']: + roadtype[f] = roadtype[f].astype('float') + + #bus part1: use roadTypeID 4 to replace missing values for roadTypeID 2 for sourceTypeID 41,42,43 for IM area + fb1 = roadtype.loc[(roadtype['sourceTypeID']==42)&(roadtype['roadTypeID']==4)&(roadtype['imarea']==1)].copy(deep=True) + fb1_a = fb1.copy() + fb1_a['roadTypeID'] = 2 + fb1_b = fb1_a.copy() + fb1_b['sourceTypeID'] = 41 + fb1_c = fb1_b.copy() + fb1_c['sourceTypeID'] = 43 + fb1 = pd.concat([fb1_a, fb1_b, fb1_c], ignore_index=True) + + #bus part2: use sourcetypeID 41, 42, 43 for IM area to replace missing values for non-IM area + fb2 = pd.concat([fb1, roadtype.loc[(roadtype['sourceTypeID'].isin([41,42,43]))&(roadtype['imarea']==1)].copy(deep=True)], ignore_index=True) + fb2['imarea'] = 0 + + #SU long-haul truck part1: use sourcetypeID 52 to replace missing values for sourceTypeID 53,54 for IM area + fb3 = roadtype.loc[(roadtype['sourceTypeID']==52)&(roadtype['imarea']==1)].copy(deep=True) + fb3_a = fb3.copy() + fb3_a['sourceTypeID'] = 53 + fb3_b = fb3_a.copy() + fb3_b['sourceTypeID'] = 54 + fb3 = pd.concat([fb3_a, fb3_b], ignore_index=True) + + #SU long-hault truck part2: use sourcetypeID 52. 53. 54 for IM area to replace missing values for non-IM area + fb4 = pd.concat([fb3, roadtype.loc[(roadtype['sourceTypeID']==52)&roadtype['imarea']==1].copy(deep=True)]) + fb4['imarea']=0 + + #MU long-haul truck part1: use sourceTypeID 61 to replace missing values for sourcetypeID 62 for IM area + fb5 = roadtype.loc[(roadtype['sourceTypeID']==61)&(roadtype['imarea']==1)].copy(deep=True) + fb5['sourceTypeID'] = 62 + + #MU long-haul truck part2: use sourceTypeID 61,62 for IM area to replace missing values for non-IM area + fb6 = pd.concat([fb5, roadtype.loc[(roadtype['sourceTypeID']==61)&(roadtype['imarea']==1)].copy(deep=True)]) + fb6['imarea'] = 0 + + fallback = pd.concat([fb1,fb2,fb3,fb4,fb5,fb6]).rename(columns={'vmt':'vmt2', 'sourceVMT':'sourceVMT2'}).sort_values(['imarea','sourceTypeID','roadTypeID']).drop_duplicates(['imarea','sourceTypeID','roadTypeID']) + + roadtype = pd.merge(roadtype, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID']) + # roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), ['vmt', 'sourceVMT']] = roadtype[['vmt2', 'sourceVMT2']] + roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), 'vmt'] = roadtype['vmt2'] + roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), 'sourceVMT'] = roadtype['sourceVMT2'] + + roadtype['sourceVMT'] = roadtype['sourceVMT'].apply(abovezero) + + roadtype.eval('roadTypeVMTFraction = vmt / sourceVMT', inplace=True) + roadtype['roadTypeVMTFraction'] = roadtype['roadTypeVMTFraction'].round(6) + + return roadtype.loc[roadtype['imarea']==imarea,['sourceTypeID','roadTypeID','roadTypeVMTFraction']].copy() + + + +# No longer included as of August 2026 +# def get_ramp_fraction(links, imarea=None): + +# rmp = links.loc[links['roadTypeID'].isin([2,4])].copy(deep=True) +# rmp.eval('fwyvht = auto_vht + bplate_vht + sush_vht + mtrucklh_vht + htruck_vht + htrucklh_vht + bus_vht', inplace=True) +# rmp.eval('fwyvmt = auto_vmt + bplate_vmt + sush_vmt + mtrucklh_vmt + htruck_vmt + htrucklh_vmt + bus_vmt', inplace=True) +# rmp['rampvht'] = np.where(rmp['isramp']==1, rmp['fwyvht'], 0) +# rmp['rampvmt'] = np.where(rmp['isramp']==1, rmp['fwyvmt'], 0) + +# ramp = rmp.groupby(['imarea','roadTypeID']).agg({'fwyvht':'sum','rampvht':'sum','fwyvmt':'sum','rampvmt':'sum'}).reset_index() +# ramp.eval('rampFraction = rampvht/fwyvht', inplace=True) +# ramp['rampFraction'] = ramp['rampFraction'].round(6) +# ramp.eval('vmtFraction = rampvmt/fwyvmt', inplace=True) +# ramp['vmtFraction'] = ramp['vmtFraction'].round(6) + +# # Output ramp fraction for im area +# if imarea is None: +# ramp_fraction = ramp[['roadTypeID','rampFraction', 'imarea']] +# else: +# ramp_fraction = ramp.loc[ramp['imarea']==imarea,['roadTypeID','rampFraction']] +# return ramp_fraction def get_hourly_vmt_fraction(b, imarea=None): # Apply data to template (all ID combinations) - roads = [1] + ROAD_TYPES # add off-network roads just for this function + roads = [1] + ROAD_TYPES # add in off-network roads just for this function dayID = [5] - template_values = list(product(SOURCE_TYPES, roads, HOURS, dayID, [0,1])) - template = pd.DataFrame(template_values, columns=['sourceTypeID', 'roadTypeID', 'hourID', 'dayID', 'imarea']) - template.sort_values(['imarea', 'sourceTypeID', 'roadTypeID', 'hourID'], inplace=True) - vmt = b.copy() - vmt['hourID'] = (vmt['hourDayID'] - 5)/10 - hourvmt = vmt.groupby(['imarea','sourceTypeID','roadTypeID','hourID']).agg({'vmt':'sum'}).reset_index() - sumvmt = hourvmt.groupby(['imarea', 'sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() - sumvmt.rename(columns={'vmt':'allvmt'},inplace=True) + if imarea is None: + template_values = list(product(SOURCE_TYPES, roads, HOURS, dayID)) + template = pd.DataFrame(template_values, columns=['sourceTypeID', 'roadTypeID', 'hourID', 'dayID']) + template.sort_values(['sourceTypeID', 'roadTypeID', 'hourID'], inplace=True) + vmt = b.copy() + vmt['hourID'] = (vmt['hourDayID'] - 5)/10 - vmtshare = pd.merge(hourvmt, sumvmt, how='left', on=['imarea','sourceTypeID','roadTypeID']) - vmtshare.sort_values(['imarea','sourceTypeID','roadTypeID','hourID'],inplace=True) + hourvmt = vmt.groupby(['sourceTypeID','roadTypeID','hourID']).agg({'vmt':'sum'}).reset_index() + sumvmt = hourvmt.groupby(['sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() + sumvmt.rename(columns={'vmt':'allvmt'},inplace=True) - ## -- use surrogates to replace missing values, if necessary - #bus part 1: use sourcetypeid 42 to replace missing values for sourceTypeID 41,43 for IM area - fb1 = vmtshare.loc[(vmtshare['sourceTypeID']==42)&(vmtshare['imarea']==1)].copy() - fb1_a = fb1.copy() - fb1_a['sourceTypeID'] = 41 - fb1_b = fb1.copy() - fb1_b['sourceTypeID'] = 43 - fb1 = pd.concat([fb1_a, fb1_b], ignore_index=True) + vmtshare = pd.merge(hourvmt, sumvmt, how='left', on=['sourceTypeID','roadTypeID']) + vmtshare.sort_values(['sourceTypeID','roadTypeID','hourID'],inplace=True) - #bus part2: use sourcetypeID 41,42,43 for IM area to replace missing values for non-IM area - fb2 = pd.concat([fb1, vmtshare.loc[(vmtshare['sourceTypeID'].isin([41,42,43]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()], ignore_index=True) - fb2['imarea'] = 0 + vmtshare['allvmt'] = np.maximum(vmtshare['allvmt'], 0.000001) + vmtshare.eval('hourVMTFraction = vmt / allvmt', inplace=True) + vmtshare['hourVMTFraction'] = vmtshare['hourVMTFraction'].round(6) - #su long-haul truck part1: use sourceTypeID 52 to replace missing values for sourcetypeID 53,54 for im area - fb3 = vmtshare.loc[(vmtshare['sourceTypeID']==52)&(vmtshare['imarea']==1)].copy() - fb3_a = fb3.copy() - fb3_a['sourceTypeID'] = 53 - fb3_b = fb3.copy() - fb3_b['sourceTypeID'] = 54 - fb3 = pd.concat([fb3_a, fb3_b], ignore_index=True) + vmtshare_b = vmtshare.copy() + vmtshare_b.loc[vmtshare_b['roadTypeID']==5, 'roadTypeID'] = 1 - #su long haul truck part2: use sourceTypeID 52,53,54 for IM area to replace missing values for non-IM area - fb4 = pd.concat([fb3, vmtshare.loc[(vmtshare['sourceTypeID'].isin([52,53,54]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()], ignore_index=True) - fb4['imarea'] = 0 + vmtshare = pd.concat([vmtshare, vmtshare_b], ignore_index=True).sort_values(['sourceTypeID','roadTypeID','hourID']) - #mu long-haul truck part 1: use sourcetypeID 61 to replace missing values for sourcetypeid 62 for im area - fb5 = vmtshare.loc[(vmtshare['sourceTypeID']==61)&(vmtshare['imarea']==1)].copy() - fb5['sourceTypeID'] = 62 + vmtshare = pd.merge(template, vmtshare, how='left', on=['sourceTypeID','roadTypeID','hourID']) - #mu long-haul truck part2: use sourcetypeid 61,62 for IM area to replace missing values for non-IM area - fb6 = pd.concat([fb5, vmtshare.loc[(vmtshare['sourceTypeID'].isin([61,62]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()],ignore_index=True) - fb6['imarea'] = 0 + vmtshare.drop_duplicates(['sourceTypeID','roadTypeID','dayID','hourID'], inplace=True) - fallback = pd.concat([fb1, fb2, fb3, fb4, fb5, fb6], ignore_index=True).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) - fallback.rename(columns={'vmt':'vmt2', 'allvmt':'allvmt2'},inplace=True) - fallback.drop_duplicates(subset=['imarea','sourceTypeID','roadTypeID','hourID'], inplace=True) + return vmtshare[['sourceTypeID','roadTypeID','dayID','hourID','hourVMTFraction']] - vmtshare = pd.merge(vmtshare, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID', 'hourID']) + else: + template_values = list(product(SOURCE_TYPES, roads, HOURS, dayID, [0,1])) + template = pd.DataFrame(template_values, columns=['sourceTypeID', 'roadTypeID', 'hourID', 'dayID', 'imarea']) + template.sort_values(['imarea', 'sourceTypeID', 'roadTypeID', 'hourID'], inplace=True) + vmt = b.copy() + vmt['hourID'] = (vmt['hourDayID'] - 5)/10 - #calculates hourvmtfraction based on original data - vmtshare['hourVMTFraction1'] = np.where(vmtshare['allvmt']>0.000001, vmtshare['vmt']/vmtshare['allvmt'], vmtshare['vmt']/0.000001) - #calculates hourvmtfraction based on fallback data - vmtshare.loc[~(vmtshare['vmt2'].isnull())&~(vmtshare['allvmt2'].isnull()), 'hourVMTFraction2'] = vmtshare['vmt2'] / vmtshare['allvmt2'] + hourvmt = vmt.groupby(['imarea','sourceTypeID','roadTypeID','hourID']).agg({'vmt':'sum'}).reset_index() + sumvmt = hourvmt.groupby(['imarea', 'sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() + sumvmt.rename(columns={'vmt':'allvmt'},inplace=True) + vmtshare = pd.merge(hourvmt, sumvmt, how='left', on=['imarea','sourceTypeID','roadTypeID']) + vmtshare.sort_values(['imarea','sourceTypeID','roadTypeID','hourID'],inplace=True) - #for sourcetypes 53,54 if there is any data - #then use both the non-zero vmt and the fallback data to arrive at the hourVMTFraction + ## -- use surrogates to replace missing values, if necessary + #bus part 1: use sourcetypeid 42 to replace missing values for sourceTypeID 41,43 for IM area + fb1 = vmtshare.loc[(vmtshare['sourceTypeID']==42)&(vmtshare['imarea']==1)].copy() + fb1_a = fb1.copy() + fb1_a['sourceTypeID'] = 41 + fb1_b = fb1.copy() + fb1_b['sourceTypeID'] = 43 + fb1 = pd.concat([fb1_a, fb1_b], ignore_index=True) - truckpart = vmtshare.loc[(vmtshare['sourceTypeID'].isin([53,54]))&(vmtshare['vmt']>0)].copy() - vmtcount = truckpart.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'vmt':'count'}).reset_index() - vmtcount.rename(columns={'vmt':'vmtcount1'},inplace=True) + #bus part2: use sourcetypeID 41,42,43 for IM area to replace missing values for non-IM area + fb2 = pd.concat([fb1, vmtshare.loc[(vmtshare['sourceTypeID'].isin([41,42,43]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()], ignore_index=True) + fb2['imarea'] = 0 + #su long-haul truck part1: use sourceTypeID 52 to replace missing values for sourcetypeID 53,54 for im area + fb3 = vmtshare.loc[(vmtshare['sourceTypeID']==52)&(vmtshare['imarea']==1)].copy() + fb3_a = fb3.copy() + fb3_a['sourceTypeID'] = 53 + fb3_b = fb3.copy() + fb3_b['sourceTypeID'] = 54 + fb3 = pd.concat([fb3_a, fb3_b], ignore_index=True) - vmtweight = pd.merge(vmtshare, vmtcount, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID']) - vmtweight2 = vmtweight.copy() - #use fallback vmtfraction for 0 vmt hours - vmtweight2.loc[(vmtweight2['sourceTypeID'].isin([53,54]))&(vmtweight2['allvmt']>0)&(vmtweight2['vmt']==0), 'hourVMTFractionpre'] = vmtweight2['hourVMTFraction2'] + #su long haul truck part2: use sourceTypeID 52,53,54 for IM area to replace missing values for non-IM area + fb4 = pd.concat([fb3, vmtshare.loc[(vmtshare['sourceTypeID'].isin([52,53,54]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()], ignore_index=True) + fb4['imarea'] = 0 - #use average of the original and fallback vmtfraction otherwise - #original data is weighted by number of hours with data - vmtweight2.loc[(vmtweight2['sourceTypeID'].isin([53,54]))&(vmtweight2['allvmt']>0)&(vmtweight2['vmt']>0), 'hourVMTFractionpre'] = (((vmtweight2['vmtcount1']/24)*vmtweight2['hourVMTFraction1'])+vmtweight2['hourVMTFraction2'])/((vmtweight2['vmtcount1']+24)/24) + #mu long-haul truck part 1: use sourcetypeID 61 to replace missing values for sourcetypeid 62 for im area + fb5 = vmtshare.loc[(vmtshare['sourceTypeID']==61)&(vmtshare['imarea']==1)].copy() + fb5['sourceTypeID'] = 62 + #mu long-haul truck part2: use sourcetypeid 61,62 for IM area to replace missing values for non-IM area + fb6 = pd.concat([fb5, vmtshare.loc[(vmtshare['sourceTypeID'].isin([61,62]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()],ignore_index=True) + fb6['imarea'] = 0 - vmtpre = vmtweight2.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'hourVMTFractionpre':'sum'}).reset_index() - vmtpre.rename(columns={'hourVMTFractionpre':'vmtpresum'},inplace=True) + fallback = pd.concat([fb1, fb2, fb3, fb4, fb5, fb6], ignore_index=True).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) + fallback.rename(columns={'vmt':'vmt2', 'allvmt':'allvmt2'},inplace=True) + fallback.drop_duplicates(subset=['imarea','sourceTypeID','roadTypeID','hourID'], inplace=True) + vmtshare = pd.merge(vmtshare, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID', 'hourID']) - vmtshare = pd.merge(vmtweight2, vmtpre, how='left', on=['imarea','sourceTypeID','roadTypeID']).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) - vmtshare.loc[vmtshare['allvmt']==0, 'vmt3'] = vmtshare['vmt'] - vmtshare.loc[vmtshare['allvmt']==0, 'allvmt3'] = vmtshare['allvmt'] + #calculates hourvmtfraction based on original data + vmtshare['hourVMTFraction1'] = np.where(vmtshare['allvmt']>0.000001, vmtshare['vmt']/vmtshare['allvmt'], vmtshare['vmt']/0.000001) + #calculates hourvmtfraction based on fallback data + vmtshare.loc[~(vmtshare['vmt2'].isnull())&~(vmtshare['allvmt2'].isnull()), 'hourVMTFraction2'] = vmtshare['vmt2'] / vmtshare['allvmt2'] - #substitution if no VMT for entire category - vmtshare.loc[(vmtshare['allvmt']==0)&(vmtshare['allvmt2']!=0), 'allvmt'] = vmtshare['allvmt2'] - vmtshare.loc[(vmtshare['vmt']==0)&(vmtshare['vmt2']!=0), 'vmt'] = vmtshare['vmt2'] - vmtshare.loc[((vmtshare['allvmt']==0)|(vmtshare['allvmt'].isnull()))&~(vmtshare['allvmt2'].isnull()), 'vmt'] = vmtshare['vmt2'] - vmtshare.loc[((vmtshare['allvmt']==0)|(vmtshare['allvmt'].isnull()))&~(vmtshare['allvmt2'].isnull()), 'allvmt'] = vmtshare['allvmt2'] + #for sourcetypes 53,54 if there is any data + #then use both the non-zero vmt and the fallback data to arrive at the hourVMTFraction - #prevent division by zero - vmtshare['allvmt'] = np.maximum(vmtshare['allvmt'], 0.000001) - vmtshare.eval('hourVMTFraction = vmt / allvmt', inplace=True) - vmtshare['hourVMTFraction'] = vmtshare['hourVMTFraction'].round(6) + truckpart = vmtshare.loc[(vmtshare['sourceTypeID'].isin([53,54]))&(vmtshare['vmt']>0)].copy() + vmtcount = truckpart.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'vmt':'count'}).reset_index() + vmtcount.rename(columns={'vmt':'vmtcount1'},inplace=True) - vmtshare.loc[(vmtshare['sourceTypeID'].isin([53,54]))&(vmtshare['vmtpresum']>0), 'hourVMTFraction'] = vmtshare['hourVMTFractionpre'] / vmtshare['vmtpresum'] - vmtshare['hourVMTFractionpre'] = vmtshare['hourVMTFractionpre'].round(6) - vmtshare.drop(columns=['vmtpresum','hourVMTFraction1','hourVMTFraction2','hourVMTFractionpre','vmtcount1'], inplace=True) + vmtweight = pd.merge(vmtshare, vmtcount, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID']) + vmtweight2 = vmtweight.copy() + #use fallback vmtfraction for 0 vmt hours + vmtweight2.loc[(vmtweight2['sourceTypeID'].isin([53,54]))&(vmtweight2['allvmt']>0)&(vmtweight2['vmt']==0), 'hourVMTFractionpre'] = vmtweight2['hourVMTFraction2'] - #apply urban arterial distribution to Off-Network type - vmtshare_b = vmtshare.copy() - vmtshare_b.loc[vmtshare_b['roadTypeID']==5, 'roadTypeID'] = 1 + #use average of the original and fallback vmtfraction otherwise + #original data is weighted by number of hours with data + vmtweight2.loc[(vmtweight2['sourceTypeID'].isin([53,54]))&(vmtweight2['allvmt']>0)&(vmtweight2['vmt']>0), 'hourVMTFractionpre'] = (((vmtweight2['vmtcount1']/24)*vmtweight2['hourVMTFraction1'])+vmtweight2['hourVMTFraction2'])/((vmtweight2['vmtcount1']+24)/24) - vmtshare = pd.concat([vmtshare, vmtshare_b], ignore_index=True).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) - vmtshare = pd.merge(template, vmtshare, how='left', on=['imarea','sourceTypeID','roadTypeID','hourID']) + vmtpre = vmtweight2.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'hourVMTFractionpre':'sum'}).reset_index() + vmtpre.rename(columns={'hourVMTFractionpre':'vmtpresum'},inplace=True) - vmtshare.drop_duplicates(['sourceTypeID','roadTypeID','dayID','hourID','imarea'], inplace=True) - if imarea is None: - hour_vmt_fraction = vmtshare[['sourceTypeID','roadTypeID','dayID','hourID','hourVMTFraction',"imarea"]] - else: - hour_vmt_fraction = vmtshare.loc[vmtshare['imarea']==imarea, ['sourceTypeID','roadTypeID','dayID','hourID','hourVMTFraction']] + vmtshare = pd.merge(vmtweight2, vmtpre, how='left', on=['imarea','sourceTypeID','roadTypeID']).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) + vmtshare.loc[vmtshare['allvmt']==0, 'vmt3'] = vmtshare['vmt'] + vmtshare.loc[vmtshare['allvmt']==0, 'allvmt3'] = vmtshare['allvmt'] + + + #substitution if no VMT for entire category + vmtshare.loc[(vmtshare['allvmt']==0)&(vmtshare['allvmt2']!=0), 'allvmt'] = vmtshare['allvmt2'] + vmtshare.loc[(vmtshare['vmt']==0)&(vmtshare['vmt2']!=0), 'vmt'] = vmtshare['vmt2'] + vmtshare.loc[((vmtshare['allvmt']==0)|(vmtshare['allvmt'].isnull()))&~(vmtshare['allvmt2'].isnull()), 'vmt'] = vmtshare['vmt2'] + vmtshare.loc[((vmtshare['allvmt']==0)|(vmtshare['allvmt'].isnull()))&~(vmtshare['allvmt2'].isnull()), 'allvmt'] = vmtshare['allvmt2'] + + #prevent division by zero + vmtshare['allvmt'] = np.maximum(vmtshare['allvmt'], 0.000001) + vmtshare.eval('hourVMTFraction = vmt / allvmt', inplace=True) + vmtshare['hourVMTFraction'] = vmtshare['hourVMTFraction'].round(6) + + vmtshare.loc[(vmtshare['sourceTypeID'].isin([53,54]))&(vmtshare['vmtpresum']>0), 'hourVMTFraction'] = vmtshare['hourVMTFractionpre'] / vmtshare['vmtpresum'] + vmtshare['hourVMTFractionpre'] = vmtshare['hourVMTFractionpre'].round(6) + + vmtshare.drop(columns=['vmtpresum','hourVMTFraction1','hourVMTFraction2','hourVMTFractionpre','vmtcount1'], inplace=True) + + #apply urban arterial distribution to Off-Network type + vmtshare_b = vmtshare.copy() + vmtshare_b.loc[vmtshare_b['roadTypeID']==5, 'roadTypeID'] = 1 + + vmtshare = pd.concat([vmtshare, vmtshare_b], ignore_index=True).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) + + vmtshare = pd.merge(template, vmtshare, how='left', on=['imarea','sourceTypeID','roadTypeID','hourID']) + + vmtshare.drop_duplicates(['sourceTypeID','roadTypeID','dayID','hourID','imarea'], inplace=True) + + return vmtshare.loc[vmtshare['imarea']==imarea, ['sourceTypeID','roadTypeID','dayID','hourID','hourVMTFraction']] - return hour_vmt_fraction def get_hpms_daily_vmt(b, imarea=None): #modeled vehicle types only @@ -584,19 +656,47 @@ def get_hpms_daily_vmt(b, imarea=None): } hpms['HPMSVtypeID'] = hpms['sourceTypeID'].map(key) - hpms1 = hpms.groupby(['imarea', 'roadTypeID', 'HPMSVtypeID']).agg({'vmt':'sum'}).reset_index() - hpms1.rename(columns={'vmt':'HPMSDailyVMT'}, inplace=True) - if imarea is None: - hpmsdailyvmt = hpms1[['roadTypeID','HPMSVtypeID','HPMSDailyVMT']] + hpms1 = hpms.groupby(['roadTypeID', 'HPMSVtypeID']).agg({'vmt':'sum'}).reset_index() + hpms1.rename(columns={'vmt':'HPMSDailyVMT'}, inplace=True) + hpms1['year'] = scenyear + return hpms1[['roadTypeID','HPMSVtypeID','HPMSDailyVMT', 'year']] else: - hpmsdailyvmt = hpms1.loc[hpms1['imarea']==imarea, ['roadTypeID','HPMSVtypeID','HPMSDailyVMT']] + hpms1 = hpms.groupby(['imarea', 'roadTypeID', 'HPMSVtypeID']).agg({'vmt':'sum'}).reset_index() + hpms1.rename(columns={'vmt':'HPMSDailyVMT'}, inplace=True) + hpms1['year'] = scenyear + return hpms1.loc[hpms1['imarea']==imarea, ['roadTypeID','HPMSVtypeID','HPMSDailyVMT', 'year']] - hpmsdailyvmt['year'] = scenyear +def get_hpms_daily_vmt_w_avgspeed(b, imarea=None): + #modeled vehicle types only + hpms = b.loc[b['sourceTypeID'].isin([21,31,32,42,52,53,61,62])].copy() - return hpmsdailyvmt + # key = { 'sourceTypeID' : 'HPMSVtypeID' } + key = { + 21:25, + 32:25, + 42:40, #transit bus vmt only + 52:50, + 53:50, + 61:60, + 62:60 + } + + hpms['HPMSVtypeID'] = hpms['sourceTypeID'].map(key) + + if imarea is None: + hpms1 = hpms.groupby(['roadTypeID', 'HPMSVtypeID', 'avgSpeedBinID']).agg({'vmt':'sum'}).reset_index() + hpms1.rename(columns={'vmt':'HPMSDailyVMT'}, inplace=True) + hpms1['year'] = scenyear + return hpms1[['roadTypeID','HPMSVtypeID','avgSpeedBinID','HPMSDailyVMT']] + + else: + hpms1 = hpms.groupby(['imarea', 'roadTypeID', 'HPMSVtypeID', 'avgSpeedBinID']).agg({'vmt':'sum'}).reset_index() + hpms1.rename(columns={'vmt':'HPMSDailyVMT'}, inplace=True) + hpms1['year'] = scenyear + return hpms1.loc[hpms1['imarea']==imarea, ['roadTypeID','HPMSVtypeID','avgSpeedBinID','HPMSDailyVMT']] def get_month_days(year): """ Accounts for leap year """ @@ -694,19 +794,19 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): # If just IM/nonIM run, set counties to empty string. Otherwise, use all CMAP region counties. if exportAs == "im": counties = [""] - im_regions = [("IM",1), ("nonIM", 0)] + im_regions = [("_IM",1), ("_nonIM", 0)] if exportAs == "im_county": counties = ['COOK', 'DUPAGE', 'KANE', 'KENDALL', 'LAKE', 'MCHENRY', 'WILL','GRUNDY'] - im_regions = [("IM",1), ("nonIM", 0)] + im_regions = [("_IM",1), ("_nonIM", 0)] if exportAs == "county": counties = ['COOK', 'DUPAGE', 'KANE', 'KENDALL', 'LAKE', 'MCHENRY', 'WILL','GRUNDY'] im_regions = [("",None)] + if exportAs == "full_region": + counties = [""] + im_regions = [("",None)] - # Define IDs - groupcols = ['imarea', 'roadTypeID', 'timeperiod', 'avgSpeedBinID', 'hours'] - # Loop over counties for county in counties: @@ -721,12 +821,13 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): county_ext = "" # Aggregate to VMT/VHT by group cols - b = agg_links(groupcols, links_to_use) + # if im_regions[0][1] is None, means don't group by IM/nonIM + # will group by IM/nonIM for any other value + b = agg_links(links_to_use, im_regions[0][1]) # Loop over IM regions for imarea_text, imarea in im_regions: - # Tab 1: Initial Model Output initial_model_output = get_initial_model_output(b, imarea) @@ -745,8 +846,11 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): # Tab 5: HPMS Daily VMT hpms_daily_vmt = get_hpms_daily_vmt(b, imarea) + + # Tab 6: HPMS Daily VMT with Average Speed group columns + hpms_daily_vmt_w_avgspeed = get_hpms_daily_vmt_w_avgspeed(b, imarea) - # Tab 6: HPMS Annual VMT + # Tab 7: HPMS Annual VMT hpms_annual_vmt = get_hpms_annual_vmt(hpms_daily_vmt, year) # Create folder for outputs if it doesn't already exist @@ -754,7 +858,12 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): out_folder.mkdir(exist_ok=True) # Output to Excel Workbook - out_path = out_folder.joinpath(f'MOVES_{model}_scen{scenyear}_{imarea_text}{county_ext}.xlsx') + if exportAs == "full_region": + out_path = out_folder.joinpath(f'MOVES_{model}_scen{scenyear}_full_region.xlsx') + + else: + out_path = out_folder.joinpath(f'MOVES_{model}_scen{scenyear}{county_ext}{imarea_text}.xlsx') + out_xlsx = pd.ExcelWriter(out_path) initial_model_output.to_excel(out_xlsx, sheet_name='initial_model_output', index=False) @@ -762,6 +871,7 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): road_type_distribution.to_excel(out_xlsx, sheet_name='RoadTypeDistribution', index=False) hourly_vmt_fraction.to_excel(out_xlsx, sheet_name='hourVMTFraction', index=False) hpms_daily_vmt.to_excel(out_xlsx, sheet_name='HPMSDailyVMT', index=False) + hpms_daily_vmt_w_avgspeed.to_excel(out_xlsx, sheet_name='HPMSDailyVMTRoadSpeed', index=False) hpms_annual_vmt.to_excel(out_xlsx, sheet_name='HPMSVtypeYear', index=False) out_xlsx.close() From 07aef357b68e0ef8511f143198baea28ffb018c6 Mon Sep 17 00:00:00 2001 From: Sarah Zebar Date: Tue, 18 Aug 2026 17:43:18 -0500 Subject: [PATCH 09/13] Replace fallback data logic used for AvgSpeedDistribution, RoadTypeDistribution, hourVMTFraction with regional data --- Database/post_macros/createMOVESinputfile.py | 608 +++++++------------ 1 file changed, 203 insertions(+), 405 deletions(-) diff --git a/Database/post_macros/createMOVESinputfile.py b/Database/post_macros/createMOVESinputfile.py index c6d9dfc..5be148f 100644 --- a/Database/post_macros/createMOVESinputfile.py +++ b/Database/post_macros/createMOVESinputfile.py @@ -6,6 +6,10 @@ # - Incorporated county data to output Excel Workbooks by IM region/county and just IM region (depending on 'exportAs') # - Added tab for Annual VMT calculation # - Incorporated globals from MOVES_constants.py, mainly for the template logic +# Sarah Zebar 2026/8/18 +# - Replace fallback data logic used for AvgSpeedDistribution, RoadTypeDistribution, hourVMTFraction with regional data +# - Reorganized final loop structure for better readability +# - Only for AvgSpeedDistribution - replace zeroes with 1e-10 for use in North Shore project # # # Tim O'Leary 2023/10/3 @@ -195,12 +199,9 @@ def speed_class(mph): return links -def agg_links(links, imarea=None): +def agg_links(links): - if imarea is None: - groupcols = ['roadTypeID', 'timeperiod', 'avgSpeedBinID', 'hours'] - else: - groupcols = ['roadTypeID', 'timeperiod', 'avgSpeedBinID', 'hours', 'imarea'] + groupcols = ['roadTypeID', 'timeperiod', 'avgSpeedBinID', 'hours'] # Define TBM vehicle types vtypes = ['auto','bplate','sush','mtrucklh','htrucklh','htruck','bus'] @@ -269,23 +270,14 @@ def agg_links(links, imarea=None): hrday = [(hr*10)+5 for hr in HOURS] # If aggregating IM,nonIM, don't include im/nonIM region in template - if imarea is None: - template_values = list(product(SOURCE_TYPES, ROAD_TYPES, hrday, SPEED_BINS)) - template_cols = ['sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'] - template = pd.DataFrame(template_values, columns=template_cols) - template.sort_values(template_cols, inplace=True) - template.reset_index(drop=True, inplace=True) + # if imarea is None: + template_values = list(product(SOURCE_TYPES, ROAD_TYPES, hrday, SPEED_BINS)) + template_cols = ['sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'] + template = pd.DataFrame(template_values, columns=template_cols) + template.sort_values(template_cols, inplace=True) + template.reset_index(drop=True, inplace=True) - else: - template_values = list(product(SOURCE_TYPES, ROAD_TYPES, hrday, SPEED_BINS, [0,1])) # [0,1] is for IM region - template_cols = ['sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID', 'imarea'] - template = pd.DataFrame(template_values, columns=template_cols) - template.sort_values( ['imarea','sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) - template.reset_index(drop=True, inplace=True) - - #### Apply data to template (all ID combinations) - # Merge data with template b = pd.merge(template, b_temp, how='left', on=template_cols) b.fillna(0, inplace=True) #remove null values @@ -299,172 +291,92 @@ def replace_neg_w_zero(x): return b -def get_initial_model_output(b, imarea=None): - """ Just filters to given imarea and excludes non-modeled source types""" - stypes_to_exclude = [11,41,43,51,54] +def filter_links(links, county, imarea): + filtered_links = links.copy() + if county is not None: + filtered_links = filtered_links.loc[filtered_links["county_name"] == county] - if imarea is None: - initial_model_output = b.loc[~(b["sourceTypeID"].isin(stypes_to_exclude))].copy(deep=True) + if imarea is not None: + filtered_links = filtered_links.loc[filtered_links["imarea"] == imarea] - else: - initial_model_output = b.loc[~(b["sourceTypeID"].isin(stypes_to_exclude)) & (b['imarea']==imarea)].copy(deep=True) - - return initial_model_output - -def get_avg_speed_distribution(b,imarea=None): + return filtered_links - # If aggregating IM and nonIM, don't include replacement data - if imarea is None: - casecols = ['sourceTypeID', 'roadTypeID', 'hourDayID'] - sumvht = b.groupby(casecols).agg({'vht':'sum'}) - sumvht.rename(columns={'vht':'allvht'}, inplace=True) - sumvht.reset_index(inplace=True) - share = pd.merge(b, sumvht, on=casecols, how='inner') - share.eval('avgSpeedFraction = vht / allvht', inplace=True) - avg_speed_dist = share[['sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID','avgSpeedFraction']] - return avg_speed_dist +def get_initial_model_output(b): + """ Just excludes non-modeled source types""" + stypes_to_exclude = [11,41,43,51,54] + initial_model_output = b.loc[~(b["sourceTypeID"].isin(stypes_to_exclude))].copy(deep=True) + return initial_model_output +def get_avg_speed_distribution(b,fallback_data): - # otherwise, fill will fallback data - else: - casecols = ['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID'] - sumvht = b.groupby(casecols).agg({'vht':'sum'}) - sumvht.rename(columns={'vht':'allvht'}, inplace=True) - sumvht.reset_index(inplace=True) - share = pd.merge(b, sumvht, on=casecols, how='inner') - - #bus, pt 1: use roadTypeID 4 to replace missing values for roadTypeID 2 for sourceTypeID 41,42,43 for IM area - fb1_a = share.loc[(share['sourceTypeID']==42)&(share['roadTypeID']==4)&(share['imarea']==1)].copy(deep=True) - fb1_a['roadTypeID'] = 2 - fb1_b = fb1_a.copy() - fb1_b['sourceTypeID'] = 41 - fb1_c = fb1_a.copy() - fb1_c['sourceTypeID'] = 43 - fb1 = pd.concat([fb1_a, fb1_b, fb1_c]) - - #bus, pt2: use sourceTypeID 41,42,43 for IM area to replace missing values for non-IM area - fb2 = pd.concat([fb1, share.loc[(share['sourceTypeID'].isin([41,42,43]))&(share['imarea']==1)].copy(deep=True)]) - fb2['imarea']=0 - - #SU long-haul truck, pt1: use sourceTypeID 52 to replace missing values for sourceTypeID 53,54 for IM area - fb3 = share.loc[(share['sourceTypeID']==52)&(share['imarea']==1)].copy(deep=True) - fb3_a = fb3.copy() - fb3_a['sourceTypeID'] = 53 - fb3_b = fb3.copy() - fb3_b['sourceTypeID'] = 54 - fb3 = pd.concat([fb3_a, fb3_b]) - - #SU long-haul truck, pt2: use sourceTypeID 52,53,54 for IM area to replace missing values for non-IM area - fb4 = pd.concat([fb3, share.loc[(share['sourceTypeID']==52)&(share['imarea']==1)]], ignore_index=True) - fb4['imarea'] = 0 - - #MU long-haul truck pt1: use sourceTypeID 61 to replace missing values for sourceTypeID 62 for IM area - fb5 = share.loc[(share['sourceTypeID']==61)&(share['imarea']==1)].copy(deep=True) - fb5['sourceTypeID'] = 62 - - #MU long-haul truck pt2: use sourceTypeID 61, 62 for IM area to replace missing values for non-IM area - fb6 = pd.concat([fb5, share.loc[(share['sourceTypeID']==61)&(share['imarea']==1)].copy(deep=True)]) - fb6['imarea'] = 0 - - #combining this whole mess together - fallback = pd.concat([fb1, fb2, fb3, fb4, fb5, fb6], ignore_index=True) - fallback.rename(columns={'vht':'vht2', 'allvht':'allvht2'}, inplace=True) - fallback.drop(columns='vmt', inplace=True) - fallback.drop_duplicates(['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) - fallback.sort_values(['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID'], inplace=True) - - share = pd.merge(share, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID']) - share.loc[(share['allvht']==0)&~(share['allvht2'].isnull()), 'vht'] = share['vht2'] - share.loc[(share['allvht']==0)&~(share['allvht2'].isnull()), 'allvht'] = share['allvht2'] - share.eval('avgSpeedFraction = vht / allvht', inplace=True) - - avg_speed_dist = share[['imarea', 'sourceTypeID', 'roadTypeID', 'hourDayID', 'avgSpeedBinID','avgSpeedFraction']] - return avg_speed_dist.loc[(avg_speed_dist['imarea']==imarea)].drop(columns='imarea') + casecols = ['sourceTypeID', 'roadTypeID', 'hourDayID'] + out_cols = casecols + ["avgSpeedBinID", "avgSpeedFraction"] + + # Calculate avgSpeedFraction by casecol group + speed_dist = b.copy() + speed_dist["avgSpeedFraction"] = speed_dist.groupby(casecols)["vht"].transform(lambda x: x/x.sum()) + + # Only include fallback data if not full region run + if fallback_data: + # If entire group is null, it's because all VMTs in the group were zero (0/0 error results in NaN) + # Fill these with fallback data (regional defaults) since we can't have null data in MOVES inputs + + # First merge in regional data + fallback_data_sheet = fallback_data["AvgSpeedDistribution"] + speed_dist = pd.merge(speed_dist, + fallback_data_sheet, + on=casecols + ["avgSpeedBinID"], + how = "left", + suffixes = ("_original", "_regional")) + + # Create flag for groups that need fallback + speed_dist["regional_default"] = speed_dist["avgSpeedFraction_original"].isna() + out_cols += ["regional_default"] + + # Combine into 1 column + speed_dist["avgSpeedFraction"] = np.where(speed_dist["regional_default"], + speed_dist["avgSpeedFraction_regional"], + speed_dist["avgSpeedFraction_original"]) + + # Fill all zeroes with very small value for North Shore Project for You Zhou + speed_dist = speed_dist.replace(0,1e-10) -def get_road_type_distribution(b, imarea=None): - - #prevent division by zero - def abovezero(x): - return np.maximum(x,0.000001) - - # meaning data is not divided up by IM/nonIM - if imarea is None: - roadtype = b.groupby(['sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() - roadtype2 = b.groupby(['sourceTypeID']).agg({'vmt':'sum'}).rename(columns={'vmt':'sourceVMT'}).reset_index() - roadtype = pd.merge(roadtype, roadtype2, how='left', on=['sourceTypeID']) - #ensure correct datatypes - for f in ['sourceTypeID', 'roadTypeID']: - roadtype[f] = roadtype[f].astype('int') - for f in ['vmt','sourceVMT']: - roadtype[f] = roadtype[f].astype('float') - - - roadtype['sourceVMT'] = roadtype['sourceVMT'].apply(abovezero) - roadtype.eval('roadTypeVMTFraction = vmt / sourceVMT', inplace=True) - roadtype['roadTypeVMTFraction'] = roadtype['roadTypeVMTFraction'].round(6) - - return roadtype[['sourceTypeID','roadTypeID','roadTypeVMTFraction']].copy() - - else: - roadtype = b.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() - roadtype2 = b.groupby(['imarea','sourceTypeID']).agg({'vmt':'sum'}).rename(columns={'vmt':'sourceVMT'}).reset_index() - - roadtype = pd.merge(roadtype, roadtype2, how='left', on=['imarea','sourceTypeID']) - - #ensure correct datatypes - for f in ['sourceTypeID', 'roadTypeID', 'imarea']: - roadtype[f] = roadtype[f].astype('int') - for f in ['vmt','sourceVMT']: - roadtype[f] = roadtype[f].astype('float') + return speed_dist[out_cols] - #bus part1: use roadTypeID 4 to replace missing values for roadTypeID 2 for sourceTypeID 41,42,43 for IM area - fb1 = roadtype.loc[(roadtype['sourceTypeID']==42)&(roadtype['roadTypeID']==4)&(roadtype['imarea']==1)].copy(deep=True) - fb1_a = fb1.copy() - fb1_a['roadTypeID'] = 2 - fb1_b = fb1_a.copy() - fb1_b['sourceTypeID'] = 41 - fb1_c = fb1_b.copy() - fb1_c['sourceTypeID'] = 43 - fb1 = pd.concat([fb1_a, fb1_b, fb1_c], ignore_index=True) +def get_road_type_distribution(b, fallback_data): - #bus part2: use sourcetypeID 41, 42, 43 for IM area to replace missing values for non-IM area - fb2 = pd.concat([fb1, roadtype.loc[(roadtype['sourceTypeID'].isin([41,42,43]))&(roadtype['imarea']==1)].copy(deep=True)], ignore_index=True) - fb2['imarea'] = 0 + # First aggregate VMT to sourceTypeID, roadTypeID level + road_dist = b.copy() + road_dist = road_dist.groupby(["sourceTypeID", "roadTypeID"]).agg({'vmt':'sum'}).reset_index() - #SU long-haul truck part1: use sourcetypeID 52 to replace missing values for sourceTypeID 53,54 for IM area - fb3 = roadtype.loc[(roadtype['sourceTypeID']==52)&(roadtype['imarea']==1)].copy(deep=True) - fb3_a = fb3.copy() - fb3_a['sourceTypeID'] = 53 - fb3_b = fb3_a.copy() - fb3_b['sourceTypeID'] = 54 - fb3 = pd.concat([fb3_a, fb3_b], ignore_index=True) + # Then Calculate roadTypeVMTFraction by sourcetype + road_dist["roadTypeVMTFraction"] = road_dist.groupby("sourceTypeID")["vmt"].transform(lambda x: x/x.sum()) - #SU long-hault truck part2: use sourcetypeID 52. 53. 54 for IM area to replace missing values for non-IM area - fb4 = pd.concat([fb3, roadtype.loc[(roadtype['sourceTypeID']==52)&roadtype['imarea']==1].copy(deep=True)]) - fb4['imarea']=0 + out_cols = ["sourceTypeID", "roadTypeID", "roadTypeVMTFraction"] - #MU long-haul truck part1: use sourceTypeID 61 to replace missing values for sourcetypeID 62 for IM area - fb5 = roadtype.loc[(roadtype['sourceTypeID']==61)&(roadtype['imarea']==1)].copy(deep=True) - fb5['sourceTypeID'] = 62 + if fallback_data: + # Same as avg speed dist - If entire group is null, it's because all VMTs in the group were zero (0/0 error results in NaN) + # Fill these with fallback data (regional defaults) since we can't have null data in MOVES inputs - #MU long-haul truck part2: use sourceTypeID 61,62 for IM area to replace missing values for non-IM area - fb6 = pd.concat([fb5, roadtype.loc[(roadtype['sourceTypeID']==61)&(roadtype['imarea']==1)].copy(deep=True)]) - fb6['imarea'] = 0 + # First merge in regional data + fallback_data_sheet = fallback_data["RoadTypeDistribution"] + road_dist = pd.merge(road_dist, + fallback_data_sheet, + on=["sourceTypeID", "roadTypeID"], + how = "left", + suffixes = ("_original", "_regional")) - fallback = pd.concat([fb1,fb2,fb3,fb4,fb5,fb6]).rename(columns={'vmt':'vmt2', 'sourceVMT':'sourceVMT2'}).sort_values(['imarea','sourceTypeID','roadTypeID']).drop_duplicates(['imarea','sourceTypeID','roadTypeID']) + # Create flag for groups that need fallback + road_dist["regional_default"] = road_dist["roadTypeVMTFraction_original"].isna() + out_cols += ["regional_default"] - roadtype = pd.merge(roadtype, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID']) - # roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), ['vmt', 'sourceVMT']] = roadtype[['vmt2', 'sourceVMT2']] - roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), 'vmt'] = roadtype['vmt2'] - roadtype.loc[(roadtype['sourceVMT']==0)&~(roadtype['sourceVMT2'].isnull()), 'sourceVMT'] = roadtype['sourceVMT2'] - - roadtype['sourceVMT'] = roadtype['sourceVMT'].apply(abovezero) - - roadtype.eval('roadTypeVMTFraction = vmt / sourceVMT', inplace=True) - roadtype['roadTypeVMTFraction'] = roadtype['roadTypeVMTFraction'].round(6) - - return roadtype.loc[roadtype['imarea']==imarea,['sourceTypeID','roadTypeID','roadTypeVMTFraction']].copy() + # Combine into 1 column + road_dist["roadTypeVMTFraction"] = np.where(road_dist["regional_default"], + road_dist["roadTypeVMTFraction_regional"], + road_dist["roadTypeVMTFraction_original"]) + + return road_dist[out_cols] @@ -490,157 +402,63 @@ def abovezero(x): # ramp_fraction = ramp.loc[ramp['imarea']==imarea,['roadTypeID','rampFraction']] # return ramp_fraction -def get_hourly_vmt_fraction(b, imarea=None): +def get_hourly_vmt_fraction(b, fallback_data): # Apply data to template (all ID combinations) roads = [1] + ROAD_TYPES # add in off-network roads just for this function dayID = [5] - if imarea is None: - template_values = list(product(SOURCE_TYPES, roads, HOURS, dayID)) - template = pd.DataFrame(template_values, columns=['sourceTypeID', 'roadTypeID', 'hourID', 'dayID']) - template.sort_values(['sourceTypeID', 'roadTypeID', 'hourID'], inplace=True) - vmt = b.copy() - vmt['hourID'] = (vmt['hourDayID'] - 5)/10 - - hourvmt = vmt.groupby(['sourceTypeID','roadTypeID','hourID']).agg({'vmt':'sum'}).reset_index() - sumvmt = hourvmt.groupby(['sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() - sumvmt.rename(columns={'vmt':'allvmt'},inplace=True) - - vmtshare = pd.merge(hourvmt, sumvmt, how='left', on=['sourceTypeID','roadTypeID']) - vmtshare.sort_values(['sourceTypeID','roadTypeID','hourID'],inplace=True) - - vmtshare['allvmt'] = np.maximum(vmtshare['allvmt'], 0.000001) - vmtshare.eval('hourVMTFraction = vmt / allvmt', inplace=True) - vmtshare['hourVMTFraction'] = vmtshare['hourVMTFraction'].round(6) - - vmtshare_b = vmtshare.copy() - vmtshare_b.loc[vmtshare_b['roadTypeID']==5, 'roadTypeID'] = 1 - - vmtshare = pd.concat([vmtshare, vmtshare_b], ignore_index=True).sort_values(['sourceTypeID','roadTypeID','hourID']) - - vmtshare = pd.merge(template, vmtshare, how='left', on=['sourceTypeID','roadTypeID','hourID']) - - vmtshare.drop_duplicates(['sourceTypeID','roadTypeID','dayID','hourID'], inplace=True) - - return vmtshare[['sourceTypeID','roadTypeID','dayID','hourID','hourVMTFraction']] - - else: - template_values = list(product(SOURCE_TYPES, roads, HOURS, dayID, [0,1])) - template = pd.DataFrame(template_values, columns=['sourceTypeID', 'roadTypeID', 'hourID', 'dayID', 'imarea']) - template.sort_values(['imarea', 'sourceTypeID', 'roadTypeID', 'hourID'], inplace=True) - vmt = b.copy() - vmt['hourID'] = (vmt['hourDayID'] - 5)/10 - - hourvmt = vmt.groupby(['imarea','sourceTypeID','roadTypeID','hourID']).agg({'vmt':'sum'}).reset_index() - sumvmt = hourvmt.groupby(['imarea', 'sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() - sumvmt.rename(columns={'vmt':'allvmt'},inplace=True) - - vmtshare = pd.merge(hourvmt, sumvmt, how='left', on=['imarea','sourceTypeID','roadTypeID']) - vmtshare.sort_values(['imarea','sourceTypeID','roadTypeID','hourID'],inplace=True) - - ## -- use surrogates to replace missing values, if necessary - #bus part 1: use sourcetypeid 42 to replace missing values for sourceTypeID 41,43 for IM area - fb1 = vmtshare.loc[(vmtshare['sourceTypeID']==42)&(vmtshare['imarea']==1)].copy() - fb1_a = fb1.copy() - fb1_a['sourceTypeID'] = 41 - fb1_b = fb1.copy() - fb1_b['sourceTypeID'] = 43 - fb1 = pd.concat([fb1_a, fb1_b], ignore_index=True) - - #bus part2: use sourcetypeID 41,42,43 for IM area to replace missing values for non-IM area - fb2 = pd.concat([fb1, vmtshare.loc[(vmtshare['sourceTypeID'].isin([41,42,43]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()], ignore_index=True) - fb2['imarea'] = 0 - - #su long-haul truck part1: use sourceTypeID 52 to replace missing values for sourcetypeID 53,54 for im area - fb3 = vmtshare.loc[(vmtshare['sourceTypeID']==52)&(vmtshare['imarea']==1)].copy() - fb3_a = fb3.copy() - fb3_a['sourceTypeID'] = 53 - fb3_b = fb3.copy() - fb3_b['sourceTypeID'] = 54 - fb3 = pd.concat([fb3_a, fb3_b], ignore_index=True) - - #su long haul truck part2: use sourceTypeID 52,53,54 for IM area to replace missing values for non-IM area - fb4 = pd.concat([fb3, vmtshare.loc[(vmtshare['sourceTypeID'].isin([52,53,54]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()], ignore_index=True) - fb4['imarea'] = 0 - - #mu long-haul truck part 1: use sourcetypeID 61 to replace missing values for sourcetypeid 62 for im area - fb5 = vmtshare.loc[(vmtshare['sourceTypeID']==61)&(vmtshare['imarea']==1)].copy() - fb5['sourceTypeID'] = 62 - - #mu long-haul truck part2: use sourcetypeid 61,62 for IM area to replace missing values for non-IM area - fb6 = pd.concat([fb5, vmtshare.loc[(vmtshare['sourceTypeID'].isin([61,62]))&(vmtshare['imarea']==1)&(vmtshare['allvmt']>0)].copy()],ignore_index=True) - fb6['imarea'] = 0 + template_values = list(product(SOURCE_TYPES, roads, HOURS, dayID)) + template = pd.DataFrame(template_values, columns=['sourceTypeID', 'roadTypeID', 'hourID', 'dayID']) + template.sort_values(['sourceTypeID', 'roadTypeID', 'hourID'], inplace=True) + vmt = b.copy() + vmt['hourID'] = (vmt['hourDayID'] - 5)/10 - fallback = pd.concat([fb1, fb2, fb3, fb4, fb5, fb6], ignore_index=True).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) - fallback.rename(columns={'vmt':'vmt2', 'allvmt':'allvmt2'},inplace=True) - fallback.drop_duplicates(subset=['imarea','sourceTypeID','roadTypeID','hourID'], inplace=True) + hourvmt = vmt.groupby(['sourceTypeID','roadTypeID','hourID']).agg({'vmt':'sum'}).reset_index() + sumvmt = hourvmt.groupby(['sourceTypeID','roadTypeID']).agg({'vmt':'sum'}).reset_index() + sumvmt.rename(columns={'vmt':'allvmt'},inplace=True) - vmtshare = pd.merge(vmtshare, fallback, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID', 'hourID']) + vmtshare = pd.merge(hourvmt, sumvmt, how='left', on=['sourceTypeID','roadTypeID']) + vmtshare.sort_values(['sourceTypeID','roadTypeID','hourID'],inplace=True) - #calculates hourvmtfraction based on original data - vmtshare['hourVMTFraction1'] = np.where(vmtshare['allvmt']>0.000001, vmtshare['vmt']/vmtshare['allvmt'], vmtshare['vmt']/0.000001) - #calculates hourvmtfraction based on fallback data - vmtshare.loc[~(vmtshare['vmt2'].isnull())&~(vmtshare['allvmt2'].isnull()), 'hourVMTFraction2'] = vmtshare['vmt2'] / vmtshare['allvmt2'] + # vmtshare['allvmt'] = np.maximum(vmtshare['allvmt'], 0.000001) + vmtshare.eval('hourVMTFraction = vmt / allvmt', inplace=True) + # vmtshare['hourVMTFraction'] = vmtshare['hourVMTFraction'].round(6) + vmtshare_b = vmtshare.copy() + vmtshare_b.loc[vmtshare_b['roadTypeID']==5, 'roadTypeID'] = 1 - #for sourcetypes 53,54 if there is any data - #then use both the non-zero vmt and the fallback data to arrive at the hourVMTFraction + vmtshare = pd.concat([vmtshare, vmtshare_b], ignore_index=True).sort_values(['sourceTypeID','roadTypeID','hourID']) - truckpart = vmtshare.loc[(vmtshare['sourceTypeID'].isin([53,54]))&(vmtshare['vmt']>0)].copy() - vmtcount = truckpart.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'vmt':'count'}).reset_index() - vmtcount.rename(columns={'vmt':'vmtcount1'},inplace=True) + vmtshare = pd.merge(template, vmtshare, how='left', on=['sourceTypeID','roadTypeID','hourID']) + vmtshare.drop_duplicates(['sourceTypeID','roadTypeID','dayID','hourID'], inplace=True) - vmtweight = pd.merge(vmtshare, vmtcount, how='left', on=['imarea', 'sourceTypeID', 'roadTypeID']) - vmtweight2 = vmtweight.copy() - #use fallback vmtfraction for 0 vmt hours - vmtweight2.loc[(vmtweight2['sourceTypeID'].isin([53,54]))&(vmtweight2['allvmt']>0)&(vmtweight2['vmt']==0), 'hourVMTFractionpre'] = vmtweight2['hourVMTFraction2'] - - #use average of the original and fallback vmtfraction otherwise - #original data is weighted by number of hours with data - vmtweight2.loc[(vmtweight2['sourceTypeID'].isin([53,54]))&(vmtweight2['allvmt']>0)&(vmtweight2['vmt']>0), 'hourVMTFractionpre'] = (((vmtweight2['vmtcount1']/24)*vmtweight2['hourVMTFraction1'])+vmtweight2['hourVMTFraction2'])/((vmtweight2['vmtcount1']+24)/24) - - - vmtpre = vmtweight2.groupby(['imarea','sourceTypeID','roadTypeID']).agg({'hourVMTFractionpre':'sum'}).reset_index() - vmtpre.rename(columns={'hourVMTFractionpre':'vmtpresum'},inplace=True) - - - vmtshare = pd.merge(vmtweight2, vmtpre, how='left', on=['imarea','sourceTypeID','roadTypeID']).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) - vmtshare.loc[vmtshare['allvmt']==0, 'vmt3'] = vmtshare['vmt'] - vmtshare.loc[vmtshare['allvmt']==0, 'allvmt3'] = vmtshare['allvmt'] - - - #substitution if no VMT for entire category - vmtshare.loc[(vmtshare['allvmt']==0)&(vmtshare['allvmt2']!=0), 'allvmt'] = vmtshare['allvmt2'] - vmtshare.loc[(vmtshare['vmt']==0)&(vmtshare['vmt2']!=0), 'vmt'] = vmtshare['vmt2'] - vmtshare.loc[((vmtshare['allvmt']==0)|(vmtshare['allvmt'].isnull()))&~(vmtshare['allvmt2'].isnull()), 'vmt'] = vmtshare['vmt2'] - vmtshare.loc[((vmtshare['allvmt']==0)|(vmtshare['allvmt'].isnull()))&~(vmtshare['allvmt2'].isnull()), 'allvmt'] = vmtshare['allvmt2'] - - #prevent division by zero - vmtshare['allvmt'] = np.maximum(vmtshare['allvmt'], 0.000001) - vmtshare.eval('hourVMTFraction = vmt / allvmt', inplace=True) - vmtshare['hourVMTFraction'] = vmtshare['hourVMTFraction'].round(6) - - vmtshare.loc[(vmtshare['sourceTypeID'].isin([53,54]))&(vmtshare['vmtpresum']>0), 'hourVMTFraction'] = vmtshare['hourVMTFractionpre'] / vmtshare['vmtpresum'] - vmtshare['hourVMTFractionpre'] = vmtshare['hourVMTFractionpre'].round(6) - - vmtshare.drop(columns=['vmtpresum','hourVMTFraction1','hourVMTFraction2','hourVMTFractionpre','vmtcount1'], inplace=True) - - #apply urban arterial distribution to Off-Network type - vmtshare_b = vmtshare.copy() - vmtshare_b.loc[vmtshare_b['roadTypeID']==5, 'roadTypeID'] = 1 - - vmtshare = pd.concat([vmtshare, vmtshare_b], ignore_index=True).sort_values(['imarea','sourceTypeID','roadTypeID','hourID']) - - vmtshare = pd.merge(template, vmtshare, how='left', on=['imarea','sourceTypeID','roadTypeID','hourID']) + out_cols = ['sourceTypeID','roadTypeID','dayID','hourID','hourVMTFraction'] + if fallback_data: + # If entire group is null, it's because all VMTs in the group were zero (0/0 error results in NaN) + # Fill these with fallback data (regional defaults) since we can't have null data in MOVES inputs + # First merge in regional data + fallback_data_sheet = fallback_data["hourVMTFraction"] + vmtshare = pd.merge(vmtshare, + fallback_data_sheet, + on=["sourceTypeID", "roadTypeID", "dayID", "hourID"], + how = "left", + suffixes = ("_original", "_regional")) + + # Create flag for groups that need fallback + vmtshare["regional_default"] = vmtshare["hourVMTFraction_original"].isna() + out_cols += ["regional_default"] - vmtshare.drop_duplicates(['sourceTypeID','roadTypeID','dayID','hourID','imarea'], inplace=True) + # Combine into 1 column + vmtshare["hourVMTFraction"] = np.where(vmtshare["regional_default"], + vmtshare["hourVMTFraction_regional"], + vmtshare["hourVMTFraction_original"]) + return vmtshare[out_cols] - return vmtshare.loc[vmtshare['imarea']==imarea, ['sourceTypeID','roadTypeID','dayID','hourID','hourVMTFraction']] -def get_hpms_daily_vmt(b, imarea=None): +def get_hpms_daily_vmt(b): #modeled vehicle types only hpms = b.loc[b['sourceTypeID'].isin([21,31,32,42,52,53,61,62])].copy() @@ -657,19 +475,12 @@ def get_hpms_daily_vmt(b, imarea=None): hpms['HPMSVtypeID'] = hpms['sourceTypeID'].map(key) - if imarea is None: - hpms1 = hpms.groupby(['roadTypeID', 'HPMSVtypeID']).agg({'vmt':'sum'}).reset_index() - hpms1.rename(columns={'vmt':'HPMSDailyVMT'}, inplace=True) - hpms1['year'] = scenyear - return hpms1[['roadTypeID','HPMSVtypeID','HPMSDailyVMT', 'year']] + hpms_out = hpms.groupby(['roadTypeID', 'HPMSVtypeID']).agg({'vmt':'sum'}).reset_index() + hpms_out.rename(columns={'vmt':'HPMSDailyVMT'}, inplace=True) + hpms_out['year'] = scenyear + return hpms_out[['roadTypeID','HPMSVtypeID','HPMSDailyVMT', 'year']] - else: - hpms1 = hpms.groupby(['imarea', 'roadTypeID', 'HPMSVtypeID']).agg({'vmt':'sum'}).reset_index() - hpms1.rename(columns={'vmt':'HPMSDailyVMT'}, inplace=True) - hpms1['year'] = scenyear - return hpms1.loc[hpms1['imarea']==imarea, ['roadTypeID','HPMSVtypeID','HPMSDailyVMT', 'year']] - -def get_hpms_daily_vmt_w_avgspeed(b, imarea=None): +def get_hpms_daily_vmt_w_avgspeed(b): #modeled vehicle types only hpms = b.loc[b['sourceTypeID'].isin([21,31,32,42,52,53,61,62])].copy() @@ -686,17 +497,11 @@ def get_hpms_daily_vmt_w_avgspeed(b, imarea=None): hpms['HPMSVtypeID'] = hpms['sourceTypeID'].map(key) - if imarea is None: - hpms1 = hpms.groupby(['roadTypeID', 'HPMSVtypeID', 'avgSpeedBinID']).agg({'vmt':'sum'}).reset_index() - hpms1.rename(columns={'vmt':'HPMSDailyVMT'}, inplace=True) - hpms1['year'] = scenyear - return hpms1[['roadTypeID','HPMSVtypeID','avgSpeedBinID','HPMSDailyVMT']] + hpms_out = hpms.groupby(['roadTypeID', 'HPMSVtypeID', 'avgSpeedBinID']).agg({'vmt':'sum'}).reset_index() + hpms_out.rename(columns={'vmt':'HPMSDailyVMT'}, inplace=True) + hpms_out['year'] = scenyear + return hpms_out[['roadTypeID','HPMSVtypeID','avgSpeedBinID','HPMSDailyVMT']] - else: - hpms1 = hpms.groupby(['imarea', 'roadTypeID', 'HPMSVtypeID', 'avgSpeedBinID']).agg({'vmt':'sum'}).reset_index() - hpms1.rename(columns={'vmt':'HPMSDailyVMT'}, inplace=True) - hpms1['year'] = scenyear - return hpms1.loc[hpms1['imarea']==imarea, ['roadTypeID','HPMSVtypeID','avgSpeedBinID','HPMSDailyVMT']] def get_month_days(year): """ Accounts for leap year """ @@ -708,11 +513,8 @@ def get_month_days(year): # Check if year is a leap year, and if so increase days in February by 1 check_leap = (year-2016)/4 if check_leap.is_integer(): - # print(f" ---> {year} is a leap year.") feb_ind = days_mo["month"].index("February") days_mo['days'][feb_ind] +=1 - # else: - # print(f" ---> {year} is not a leap year.") days_mo_df =pd.DataFrame(days_mo) @@ -771,6 +573,8 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): return emme_adj + + if __name__ == "__main__": # Get parameters from batch file @@ -779,7 +583,7 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): model = config['model_version'] # e.g., 'c23q4' scenyear = config['scenario_code'] # e.g., '400' year = config['year'] - exportAs = config['exportAs'] # im or im_county + exportAs = config['exportAs'] # Load in punchlink for specific scenario year linkdata = pd.read_csv(DB_DIR.joinpath('data', 'punchlink.csv')) @@ -791,90 +595,84 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): # Get clean link data links = clean_linkdata(linkdata) - # If just IM/nonIM run, set counties to empty string. Otherwise, use all CMAP region counties. + # Set by_county and by_imarea booleans according to exportAs type if exportAs == "im": - counties = [""] - im_regions = [("_IM",1), ("_nonIM", 0)] + by_county = False + by_imarea = True if exportAs == "im_county": - counties = ['COOK', 'DUPAGE', 'KANE', 'KENDALL', 'LAKE', 'MCHENRY', 'WILL','GRUNDY'] - im_regions = [("_IM",1), ("_nonIM", 0)] + by_county = True + by_imarea = True if exportAs == "county": - counties = ['COOK', 'DUPAGE', 'KANE', 'KENDALL', 'LAKE', 'MCHENRY', 'WILL','GRUNDY'] - im_regions = [("",None)] + by_county = True + by_imarea = False if exportAs == "full_region": - counties = [""] - im_regions = [("",None)] - + by_county = False + by_imarea = False + # Define iterables + if by_county: + counties = [('_COOK', 'COOK'), + ('_DUPAGE', 'DUPAGE'), + ('_KANE','KANE'), + ('_KENDALL','KENDALL'), + ('_LAKE','LAKE'), + ('_MCHENRY','MCHENRY'), + ('_WILL','WILL'), + ('_GRUNDY','GRUNDY')] + else: + counties = [("", None)] - # Loop over counties - for county in counties: - - # If im_county run, filter for just links in a given county - if county != "": - links_to_use = links.loc[links["county_name"] == county] - county_ext = f"_{county}" - - # Otherwise, use entire links dataset - else: - links_to_use = links.copy() - county_ext = "" - - # Aggregate to VMT/VHT by group cols - # if im_regions[0][1] is None, means don't group by IM/nonIM - # will group by IM/nonIM for any other value - b = agg_links(links_to_use, im_regions[0][1]) - - # Loop over IM regions - for imarea_text, imarea in im_regions: - - # Tab 1: Initial Model Output - initial_model_output = get_initial_model_output(b, imarea) - - # If no data, don't output file - if (np.all(initial_model_output["vmt"]==0)) & (np.all(initial_model_output["vht"]==0)): - continue - - # Tab 2: Average Speed Distribution - avg_speed_dist = get_avg_speed_distribution(b,imarea) - - # Tab 3: Road Type Distribution - road_type_distribution = get_road_type_distribution(b, imarea) - - # Tab 4: Hourly VMT Fraction - hourly_vmt_fraction = get_hourly_vmt_fraction(b, imarea) - - # Tab 5: HPMS Daily VMT - hpms_daily_vmt = get_hpms_daily_vmt(b, imarea) - - # Tab 6: HPMS Daily VMT with Average Speed group columns - hpms_daily_vmt_w_avgspeed = get_hpms_daily_vmt_w_avgspeed(b, imarea) - - # Tab 7: HPMS Annual VMT - hpms_annual_vmt = get_hpms_annual_vmt(hpms_daily_vmt, year) - - # Create folder for outputs if it doesn't already exist - out_folder = DB_DIR.joinpath('data', f'MOVES_{model}_scen{scenyear}') - out_folder.mkdir(exist_ok=True) - - # Output to Excel Workbook - if exportAs == "full_region": - out_path = out_folder.joinpath(f'MOVES_{model}_scen{scenyear}_full_region.xlsx') + if by_imarea: + im_regions = [("_IM",1), ("_nonIM", 0)] + else: + im_regions = [("",None)] - else: - out_path = out_folder.joinpath(f'MOVES_{model}_scen{scenyear}{county_ext}{imarea_text}.xlsx') - out_xlsx = pd.ExcelWriter(out_path) + # Define output folder + out_folder = DB_DIR.joinpath('data', f'MOVES_{model}_scen{scenyear}') - initial_model_output.to_excel(out_xlsx, sheet_name='initial_model_output', index=False) - avg_speed_dist.to_excel(out_xlsx, sheet_name='AvgSpeedDistribution', index=False) - road_type_distribution.to_excel(out_xlsx, sheet_name='RoadTypeDistribution', index=False) - hourly_vmt_fraction.to_excel(out_xlsx, sheet_name='hourVMTFraction', index=False) - hpms_daily_vmt.to_excel(out_xlsx, sheet_name='HPMSDailyVMT', index=False) - hpms_daily_vmt_w_avgspeed.to_excel(out_xlsx, sheet_name='HPMSDailyVMTRoadSpeed', index=False) - hpms_annual_vmt.to_excel(out_xlsx, sheet_name='HPMSVtypeYear', index=False) + # If doing full region run, set fallback to False + # Otherwise, read in full region data + if exportAs == "full_region": + fallback_data = False + else: + fallback_data_path = out_folder.joinpath(f'MOVES_{model}_scen{scenyear}.xlsx') + fallback_data = pd.read_excel(fallback_data_path, sheet_name = None) - out_xlsx.close() + print(f"Outputting Results to {out_folder}") + for county_text, county in counties: + for imarea_text, imarea in im_regions: + + # Filter for county/imarea + filtered_links = filter_links(links, county, imarea) + + # Aggregate to VMT/VHT by sourceTypeID, roadTypeID, hourDayID, avgSpeedBinID + b = agg_links(filtered_links) + + # Calculate data for tabs + initial_model_output = get_initial_model_output(b) + avg_speed_dist = get_avg_speed_distribution(b, fallback_data) + road_type_dist = get_road_type_distribution(b, fallback_data) + hourly_vmt_fraction = get_hourly_vmt_fraction(b, fallback_data) + hpms_daily_vmt = get_hpms_daily_vmt(b) + hpms_daily_vmt_w_avgspeed = get_hpms_daily_vmt_w_avgspeed(b) + hpms_annual_vmt = get_hpms_annual_vmt(hpms_daily_vmt, year) + + # Define filename and export all tabs to excel workbook + file_name = f'MOVES_{model}_scen{scenyear}{county_text}{imarea_text}.xlsx' + out_path = out_folder.joinpath(file_name) + out_xlsx = pd.ExcelWriter(out_path) + + initial_model_output.to_excel(out_xlsx, sheet_name='initial_model_output', index=False) + avg_speed_dist.to_excel(out_xlsx, sheet_name='AvgSpeedDistribution', index=False) + road_type_dist.to_excel(out_xlsx, sheet_name='RoadTypeDistribution', index=False) + hourly_vmt_fraction.to_excel(out_xlsx, sheet_name='hourVMTFraction', index=False) + hpms_daily_vmt.to_excel(out_xlsx, sheet_name='HPMSDailyVMT', index=False) + hpms_daily_vmt_w_avgspeed.to_excel(out_xlsx, sheet_name='HPMSDailyVMTRoadSpeed', index=False) + hpms_annual_vmt.to_excel(out_xlsx, sheet_name='HPMSVtypeYear', index=False) + + out_xlsx.close() + print("Saved:", file_name) print("Done!") From db31d62ccde796023ee3349a6852373e5a859af1 Mon Sep 17 00:00:00 2001 From: Sarah Zebar Date: Tue, 18 Aug 2026 17:45:03 -0500 Subject: [PATCH 10/13] Added comment about running exportAs = full_region first --- Database/post_macros/createMOVESinputfile.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Database/post_macros/createMOVESinputfile.py b/Database/post_macros/createMOVESinputfile.py index 5be148f..2348a53 100644 --- a/Database/post_macros/createMOVESinputfile.py +++ b/Database/post_macros/createMOVESinputfile.py @@ -8,6 +8,7 @@ # - Incorporated globals from MOVES_constants.py, mainly for the template logic # Sarah Zebar 2026/8/18 # - Replace fallback data logic used for AvgSpeedDistribution, RoadTypeDistribution, hourVMTFraction with regional data +# - NOTE: first run must be exportAs = "full_region" to obtain regional data # - Reorganized final loop structure for better readability # - Only for AvgSpeedDistribution - replace zeroes with 1e-10 for use in North Shore project # From 9fa10fd4cd9533050614bdbf5e12b5bc8009d6a4 Mon Sep 17 00:00:00 2001 From: Sarah Zebar Date: Tue, 18 Aug 2026 17:48:09 -0500 Subject: [PATCH 11/13] changed yearID in HPMSVtypeYear tab from scenyear to year --- Database/post_macros/createMOVESinputfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Database/post_macros/createMOVESinputfile.py b/Database/post_macros/createMOVESinputfile.py index 2348a53..7ada85e 100644 --- a/Database/post_macros/createMOVESinputfile.py +++ b/Database/post_macros/createMOVESinputfile.py @@ -569,7 +569,7 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): # Format for export emme_adj.rename(columns={'sourceTypeID':'HPMSVtypeID', 'final_VMT':'HPMSBaseYearVMT'}, inplace=True) - emme_adj['yearID'] = scenyear + emme_adj['yearID'] = year emme_adj=emme_adj[['HPMSVtypeID', 'yearID', 'HPMSBaseYearVMT']].copy() return emme_adj From 327b78e388eb4fbb84a27536ec58a9c25c0654d6 Mon Sep 17 00:00:00 2001 From: Sarah Zebar Date: Wed, 19 Aug 2026 09:57:10 -0500 Subject: [PATCH 12/13] Replaced zone17_county_crosswalk.csv with GEOG_IN.txt --- Database/data/zone17_county_crosswalk.csv | 3633 ------------------ Database/post_macros/createMOVESinputfile.py | 16 +- 2 files changed, 10 insertions(+), 3639 deletions(-) delete mode 100644 Database/data/zone17_county_crosswalk.csv diff --git a/Database/data/zone17_county_crosswalk.csv b/Database/data/zone17_county_crosswalk.csv deleted file mode 100644 index f4003a5..0000000 --- a/Database/data/zone17_county_crosswalk.csv +++ /dev/null @@ -1,3633 +0,0 @@ -zone17,county_fips,county_name,state -1,17031,COOK,IL -2,17031,COOK,IL -3,17031,COOK,IL -4,17031,COOK,IL -5,17031,COOK,IL -6,17031,COOK,IL -7,17031,COOK,IL -8,17031,COOK,IL -9,17031,COOK,IL -10,17031,COOK,IL -11,17031,COOK,IL -12,17031,COOK,IL -13,17031,COOK,IL -14,17031,COOK,IL -15,17031,COOK,IL -16,17031,COOK,IL -17,17031,COOK,IL -18,17031,COOK,IL -19,17031,COOK,IL -20,17031,COOK,IL -21,17031,COOK,IL -22,17031,COOK,IL -23,17031,COOK,IL -24,17031,COOK,IL -25,17031,COOK,IL -26,17031,COOK,IL -27,17031,COOK,IL -28,17031,COOK,IL -29,17031,COOK,IL -30,17031,COOK,IL -31,17031,COOK,IL -32,17031,COOK,IL -33,17031,COOK,IL -34,17031,COOK,IL -35,17031,COOK,IL -36,17031,COOK,IL -37,17031,COOK,IL -38,17031,COOK,IL -39,17031,COOK,IL -40,17031,COOK,IL -41,17031,COOK,IL -42,17031,COOK,IL -43,17031,COOK,IL -44,17031,COOK,IL -45,17031,COOK,IL -46,17031,COOK,IL -47,17031,COOK,IL -48,17031,COOK,IL -49,17031,COOK,IL -50,17031,COOK,IL -51,17031,COOK,IL -52,17031,COOK,IL -53,17031,COOK,IL -54,17031,COOK,IL -55,17031,COOK,IL -56,17031,COOK,IL -57,17031,COOK,IL -58,17031,COOK,IL -59,17031,COOK,IL -60,17031,COOK,IL -61,17031,COOK,IL -62,17031,COOK,IL -63,17031,COOK,IL -64,17031,COOK,IL -65,17031,COOK,IL -66,17031,COOK,IL -67,17031,COOK,IL -68,17031,COOK,IL -69,17031,COOK,IL -70,17031,COOK,IL -71,17031,COOK,IL -72,17031,COOK,IL -73,17031,COOK,IL -74,17031,COOK,IL -75,17031,COOK,IL -76,17031,COOK,IL -77,17031,COOK,IL -78,17031,COOK,IL -79,17031,COOK,IL -80,17031,COOK,IL -81,17031,COOK,IL -82,17031,COOK,IL -83,17031,COOK,IL -84,17031,COOK,IL -85,17031,COOK,IL -86,17031,COOK,IL -87,17031,COOK,IL -88,17031,COOK,IL -89,17031,COOK,IL -90,17031,COOK,IL -91,17031,COOK,IL -92,17031,COOK,IL -93,17031,COOK,IL -94,17031,COOK,IL -95,17031,COOK,IL -96,17031,COOK,IL -97,17031,COOK,IL -98,17031,COOK,IL -99,17031,COOK,IL -100,17031,COOK,IL -101,17031,COOK,IL -102,17031,COOK,IL -103,17031,COOK,IL -104,17031,COOK,IL -105,17031,COOK,IL -106,17031,COOK,IL -107,17031,COOK,IL -108,17031,COOK,IL -109,17031,COOK,IL -110,17031,COOK,IL -111,17031,COOK,IL -112,17031,COOK,IL -113,17031,COOK,IL -114,17031,COOK,IL -115,17031,COOK,IL -116,17031,COOK,IL -117,17031,COOK,IL -118,17031,COOK,IL -119,17031,COOK,IL -120,17031,COOK,IL -121,17031,COOK,IL -122,17031,COOK,IL -123,17031,COOK,IL -124,17031,COOK,IL -125,17031,COOK,IL -126,17031,COOK,IL -127,17031,COOK,IL -128,17031,COOK,IL -129,17031,COOK,IL -130,17031,COOK,IL -131,17031,COOK,IL -132,17031,COOK,IL -133,17031,COOK,IL -134,17031,COOK,IL -135,17031,COOK,IL -136,17031,COOK,IL -137,17031,COOK,IL -138,17031,COOK,IL -139,17031,COOK,IL -140,17031,COOK,IL -141,17031,COOK,IL -142,17031,COOK,IL -143,17031,COOK,IL -144,17031,COOK,IL -145,17031,COOK,IL -146,17031,COOK,IL -147,17031,COOK,IL -148,17031,COOK,IL -149,17031,COOK,IL -150,17031,COOK,IL -151,17031,COOK,IL -152,17031,COOK,IL -153,17031,COOK,IL -154,17031,COOK,IL -155,17031,COOK,IL -156,17031,COOK,IL -157,17031,COOK,IL -158,17031,COOK,IL -159,17031,COOK,IL -1160,17031,COOK,IL -160,17031,COOK,IL -161,17031,COOK,IL -162,17031,COOK,IL -163,17031,COOK,IL -164,17031,COOK,IL -165,17031,COOK,IL -166,17031,COOK,IL -167,17031,COOK,IL -168,17031,COOK,IL -169,17031,COOK,IL -170,17031,COOK,IL -171,17031,COOK,IL -172,17031,COOK,IL -173,17031,COOK,IL -174,17031,COOK,IL -175,17031,COOK,IL -176,17031,COOK,IL -177,17031,COOK,IL -178,17031,COOK,IL -179,17031,COOK,IL -180,17031,COOK,IL -181,17031,COOK,IL -182,17031,COOK,IL -183,17031,COOK,IL -184,17031,COOK,IL -185,17031,COOK,IL -186,17031,COOK,IL -187,17031,COOK,IL -188,17031,COOK,IL -189,17031,COOK,IL -190,17031,COOK,IL -191,17031,COOK,IL -192,17031,COOK,IL -193,17031,COOK,IL -194,17031,COOK,IL -195,17031,COOK,IL -196,17031,COOK,IL -197,17031,COOK,IL -198,17031,COOK,IL -199,17031,COOK,IL -200,17031,COOK,IL -201,17031,COOK,IL -202,17031,COOK,IL -203,17031,COOK,IL -204,17031,COOK,IL -205,17031,COOK,IL -206,17031,COOK,IL -207,17031,COOK,IL -208,17031,COOK,IL -209,17031,COOK,IL -210,17031,COOK,IL -211,17031,COOK,IL -212,17031,COOK,IL -213,17031,COOK,IL -214,17031,COOK,IL -215,17031,COOK,IL -216,17031,COOK,IL -217,17031,COOK,IL -218,17031,COOK,IL -219,17031,COOK,IL -220,17031,COOK,IL -221,17031,COOK,IL -222,17031,COOK,IL -223,17031,COOK,IL -224,17031,COOK,IL -225,17031,COOK,IL -226,17031,COOK,IL -227,17031,COOK,IL -228,17031,COOK,IL -229,17031,COOK,IL -230,17031,COOK,IL -231,17031,COOK,IL -232,17031,COOK,IL -233,17031,COOK,IL -234,17031,COOK,IL -235,17031,COOK,IL -236,17031,COOK,IL -237,17031,COOK,IL -238,17031,COOK,IL -239,17031,COOK,IL -240,17031,COOK,IL -241,17031,COOK,IL -242,17031,COOK,IL -243,17031,COOK,IL -244,17031,COOK,IL -245,17031,COOK,IL -246,17031,COOK,IL -247,17031,COOK,IL -248,17031,COOK,IL -249,17031,COOK,IL -250,17031,COOK,IL -251,17031,COOK,IL -252,17031,COOK,IL -253,17031,COOK,IL -254,17031,COOK,IL -255,17031,COOK,IL -256,17031,COOK,IL -257,17031,COOK,IL -258,17031,COOK,IL -259,17031,COOK,IL -260,17031,COOK,IL -261,17031,COOK,IL -262,17031,COOK,IL -263,17031,COOK,IL -264,17031,COOK,IL -265,17031,COOK,IL -266,17031,COOK,IL -267,17031,COOK,IL -268,17031,COOK,IL -269,17031,COOK,IL -270,17031,COOK,IL -271,17031,COOK,IL -272,17031,COOK,IL -273,17031,COOK,IL -274,17031,COOK,IL -275,17031,COOK,IL -276,17031,COOK,IL -277,17031,COOK,IL -278,17031,COOK,IL -279,17031,COOK,IL -280,17031,COOK,IL -281,17031,COOK,IL -282,17031,COOK,IL -283,17031,COOK,IL -284,17031,COOK,IL -285,17031,COOK,IL -286,17031,COOK,IL -287,17031,COOK,IL -288,17031,COOK,IL -289,17031,COOK,IL -290,17031,COOK,IL -291,17031,COOK,IL -292,17031,COOK,IL -293,17031,COOK,IL -294,17031,COOK,IL -295,17031,COOK,IL -296,17031,COOK,IL -297,17031,COOK,IL -298,17031,COOK,IL -299,17031,COOK,IL -300,17031,COOK,IL -301,17031,COOK,IL -302,17031,COOK,IL -303,17031,COOK,IL -304,17031,COOK,IL -305,17031,COOK,IL -306,17031,COOK,IL -307,17031,COOK,IL -308,17031,COOK,IL -309,17031,COOK,IL -310,17031,COOK,IL -311,17031,COOK,IL -312,17031,COOK,IL -313,17031,COOK,IL -314,17031,COOK,IL -315,17031,COOK,IL -316,17031,COOK,IL -317,17031,COOK,IL -318,17031,COOK,IL -319,17031,COOK,IL -320,17031,COOK,IL -321,17031,COOK,IL -322,17031,COOK,IL -323,17031,COOK,IL -324,17031,COOK,IL -325,17031,COOK,IL -326,17031,COOK,IL -327,17031,COOK,IL -328,17031,COOK,IL -329,17031,COOK,IL -330,17031,COOK,IL -331,17031,COOK,IL -332,17031,COOK,IL -333,17031,COOK,IL -334,17031,COOK,IL -335,17031,COOK,IL -336,17031,COOK,IL -337,17031,COOK,IL -338,17031,COOK,IL -339,17031,COOK,IL -340,17031,COOK,IL -341,17031,COOK,IL -342,17031,COOK,IL -343,17031,COOK,IL -344,17031,COOK,IL -345,17031,COOK,IL -346,17031,COOK,IL -347,17031,COOK,IL -348,17031,COOK,IL -349,17031,COOK,IL -350,17031,COOK,IL -351,17031,COOK,IL -352,17031,COOK,IL -353,17031,COOK,IL -354,17031,COOK,IL -355,17031,COOK,IL -356,17031,COOK,IL -357,17031,COOK,IL -358,17031,COOK,IL -359,17031,COOK,IL -360,17031,COOK,IL -361,17031,COOK,IL -362,17031,COOK,IL -363,17031,COOK,IL -364,17031,COOK,IL -365,17031,COOK,IL -366,17031,COOK,IL -367,17031,COOK,IL -368,17031,COOK,IL -369,17031,COOK,IL -370,17031,COOK,IL -371,17031,COOK,IL -372,17031,COOK,IL -373,17031,COOK,IL -374,17031,COOK,IL -375,17031,COOK,IL -376,17031,COOK,IL -377,17031,COOK,IL -378,17031,COOK,IL -379,17031,COOK,IL -380,17031,COOK,IL -381,17031,COOK,IL -382,17031,COOK,IL -383,17031,COOK,IL -384,17031,COOK,IL -385,17031,COOK,IL -386,17031,COOK,IL -387,17031,COOK,IL -388,17031,COOK,IL -389,17031,COOK,IL -390,17031,COOK,IL -391,17031,COOK,IL -392,17031,COOK,IL -393,17031,COOK,IL -394,17031,COOK,IL -395,17031,COOK,IL -396,17031,COOK,IL -397,17031,COOK,IL -398,17031,COOK,IL -399,17031,COOK,IL -400,17031,COOK,IL -401,17031,COOK,IL -402,17031,COOK,IL -403,17031,COOK,IL -404,17031,COOK,IL -405,17031,COOK,IL -406,17031,COOK,IL -407,17031,COOK,IL -408,17031,COOK,IL -409,17031,COOK,IL -410,17031,COOK,IL -411,17031,COOK,IL -412,17031,COOK,IL -413,17031,COOK,IL -414,17031,COOK,IL -415,17031,COOK,IL -416,17031,COOK,IL -417,17031,COOK,IL -418,17031,COOK,IL -419,17031,COOK,IL -420,17031,COOK,IL -421,17031,COOK,IL -422,17031,COOK,IL -423,17031,COOK,IL -424,17031,COOK,IL -425,17031,COOK,IL -426,17031,COOK,IL -427,17031,COOK,IL -428,17031,COOK,IL -429,17031,COOK,IL -430,17031,COOK,IL -431,17031,COOK,IL -432,17031,COOK,IL -433,17031,COOK,IL -434,17031,COOK,IL -435,17031,COOK,IL -436,17031,COOK,IL -437,17031,COOK,IL -438,17031,COOK,IL -439,17031,COOK,IL -440,17031,COOK,IL -441,17031,COOK,IL -442,17031,COOK,IL -443,17031,COOK,IL -444,17031,COOK,IL -445,17031,COOK,IL -446,17031,COOK,IL -447,17031,COOK,IL -448,17031,COOK,IL -449,17031,COOK,IL -450,17031,COOK,IL -451,17031,COOK,IL -452,17031,COOK,IL -453,17031,COOK,IL -454,17031,COOK,IL -455,17031,COOK,IL -456,17031,COOK,IL -457,17031,COOK,IL -458,17031,COOK,IL -459,17031,COOK,IL -460,17031,COOK,IL -461,17031,COOK,IL -462,17031,COOK,IL -463,17031,COOK,IL -464,17031,COOK,IL -465,17031,COOK,IL -466,17031,COOK,IL -467,17031,COOK,IL -468,17031,COOK,IL -469,17031,COOK,IL -470,17031,COOK,IL -471,17031,COOK,IL -472,17031,COOK,IL -473,17031,COOK,IL -474,17031,COOK,IL -475,17031,COOK,IL -476,17031,COOK,IL -477,17031,COOK,IL -478,17031,COOK,IL -479,17031,COOK,IL -480,17031,COOK,IL -481,17031,COOK,IL -482,17031,COOK,IL -483,17031,COOK,IL -484,17031,COOK,IL -485,17031,COOK,IL -486,17031,COOK,IL -487,17031,COOK,IL -488,17031,COOK,IL -489,17031,COOK,IL -490,17031,COOK,IL -491,17031,COOK,IL -492,17031,COOK,IL -493,17031,COOK,IL -494,17031,COOK,IL -495,17031,COOK,IL -496,17031,COOK,IL -497,17031,COOK,IL -498,17031,COOK,IL -499,17031,COOK,IL -500,17031,COOK,IL -501,17031,COOK,IL -502,17031,COOK,IL -503,17031,COOK,IL -504,17031,COOK,IL -505,17031,COOK,IL -506,17031,COOK,IL -507,17031,COOK,IL -508,17031,COOK,IL -509,17031,COOK,IL -510,17031,COOK,IL -511,17031,COOK,IL -512,17031,COOK,IL -513,17031,COOK,IL -514,17031,COOK,IL -515,17031,COOK,IL -516,17031,COOK,IL -517,17031,COOK,IL -518,17031,COOK,IL -519,17031,COOK,IL -520,17031,COOK,IL -521,17031,COOK,IL -522,17031,COOK,IL -523,17031,COOK,IL -524,17031,COOK,IL -525,17031,COOK,IL -526,17031,COOK,IL -527,17031,COOK,IL -528,17031,COOK,IL -529,17031,COOK,IL -530,17031,COOK,IL -531,17031,COOK,IL -532,17031,COOK,IL -533,17031,COOK,IL -534,17031,COOK,IL -535,17031,COOK,IL -536,17031,COOK,IL -537,17031,COOK,IL -538,17031,COOK,IL -539,17031,COOK,IL -540,17031,COOK,IL -541,17031,COOK,IL -542,17031,COOK,IL -543,17031,COOK,IL -544,17031,COOK,IL -545,17031,COOK,IL -546,17031,COOK,IL -547,17031,COOK,IL -548,17031,COOK,IL -549,17031,COOK,IL -550,17031,COOK,IL -551,17031,COOK,IL -552,17031,COOK,IL -553,17031,COOK,IL -554,17031,COOK,IL -555,17031,COOK,IL -556,17031,COOK,IL -557,17031,COOK,IL -558,17031,COOK,IL -559,17031,COOK,IL -560,17031,COOK,IL -561,17031,COOK,IL -562,17031,COOK,IL -563,17031,COOK,IL -564,17031,COOK,IL -565,17031,COOK,IL -566,17031,COOK,IL -567,17031,COOK,IL -568,17031,COOK,IL -569,17031,COOK,IL -570,17031,COOK,IL -571,17031,COOK,IL -572,17031,COOK,IL -573,17031,COOK,IL -574,17031,COOK,IL -575,17031,COOK,IL -576,17031,COOK,IL -577,17031,COOK,IL -578,17031,COOK,IL -579,17031,COOK,IL -580,17031,COOK,IL -581,17031,COOK,IL -582,17031,COOK,IL -583,17031,COOK,IL -584,17031,COOK,IL -585,17031,COOK,IL -586,17031,COOK,IL -587,17031,COOK,IL -588,17031,COOK,IL -589,17031,COOK,IL -590,17031,COOK,IL -591,17031,COOK,IL -592,17031,COOK,IL -593,17031,COOK,IL -594,17031,COOK,IL -595,17031,COOK,IL -596,17031,COOK,IL -597,17031,COOK,IL -598,17031,COOK,IL -599,17031,COOK,IL -600,17031,COOK,IL -601,17031,COOK,IL -602,17031,COOK,IL -603,17031,COOK,IL -604,17031,COOK,IL -605,17031,COOK,IL -606,17031,COOK,IL -607,17031,COOK,IL -608,17031,COOK,IL -609,17031,COOK,IL -610,17031,COOK,IL -611,17031,COOK,IL -612,17031,COOK,IL -613,17031,COOK,IL -614,17031,COOK,IL -615,17031,COOK,IL -616,17031,COOK,IL -617,17031,COOK,IL -618,17031,COOK,IL -619,17031,COOK,IL -620,17031,COOK,IL -621,17031,COOK,IL -622,17031,COOK,IL -623,17031,COOK,IL -624,17031,COOK,IL -625,17031,COOK,IL -626,17031,COOK,IL -627,17031,COOK,IL -628,17031,COOK,IL -629,17031,COOK,IL -630,17031,COOK,IL -631,17031,COOK,IL -632,17031,COOK,IL -633,17031,COOK,IL -634,17031,COOK,IL -635,17031,COOK,IL -636,17031,COOK,IL -637,17031,COOK,IL -638,17031,COOK,IL -639,17031,COOK,IL -640,17031,COOK,IL -641,17031,COOK,IL -642,17031,COOK,IL -643,17031,COOK,IL -644,17031,COOK,IL -645,17031,COOK,IL -646,17031,COOK,IL -647,17031,COOK,IL -648,17031,COOK,IL -649,17031,COOK,IL -650,17031,COOK,IL -651,17031,COOK,IL -652,17031,COOK,IL -653,17031,COOK,IL -654,17031,COOK,IL -655,17031,COOK,IL -656,17031,COOK,IL -657,17031,COOK,IL -658,17031,COOK,IL -659,17031,COOK,IL -660,17031,COOK,IL -661,17031,COOK,IL -662,17031,COOK,IL -663,17031,COOK,IL -664,17031,COOK,IL -665,17031,COOK,IL -666,17031,COOK,IL -667,17031,COOK,IL -668,17031,COOK,IL -669,17031,COOK,IL -670,17031,COOK,IL -671,17031,COOK,IL -672,17031,COOK,IL -673,17031,COOK,IL -674,17031,COOK,IL -675,17031,COOK,IL -676,17031,COOK,IL -677,17031,COOK,IL -678,17031,COOK,IL -679,17031,COOK,IL -680,17031,COOK,IL -681,17031,COOK,IL -682,17031,COOK,IL -683,17031,COOK,IL -684,17031,COOK,IL -685,17031,COOK,IL -686,17031,COOK,IL -687,17031,COOK,IL -688,17031,COOK,IL -689,17031,COOK,IL -690,17031,COOK,IL -691,17031,COOK,IL -692,17031,COOK,IL -693,17031,COOK,IL -694,17031,COOK,IL -695,17031,COOK,IL -696,17031,COOK,IL -697,17031,COOK,IL -698,17031,COOK,IL -699,17031,COOK,IL -700,17031,COOK,IL -701,17031,COOK,IL -702,17031,COOK,IL -703,17031,COOK,IL -704,17031,COOK,IL -705,17031,COOK,IL -706,17031,COOK,IL -707,17031,COOK,IL -708,17031,COOK,IL -709,17031,COOK,IL -710,17031,COOK,IL -711,17031,COOK,IL -712,17031,COOK,IL -713,17031,COOK,IL -714,17031,COOK,IL -715,17031,COOK,IL -716,17031,COOK,IL -717,17031,COOK,IL -718,17031,COOK,IL -719,17031,COOK,IL -720,17031,COOK,IL -721,17031,COOK,IL -722,17031,COOK,IL -723,17031,COOK,IL -724,17031,COOK,IL -725,17031,COOK,IL -726,17031,COOK,IL -727,17031,COOK,IL -728,17031,COOK,IL -729,17031,COOK,IL -730,17031,COOK,IL -731,17031,COOK,IL -732,17031,COOK,IL -733,17031,COOK,IL -734,17031,COOK,IL -735,17031,COOK,IL -736,17031,COOK,IL -737,17031,COOK,IL -738,17031,COOK,IL -739,17031,COOK,IL -740,17031,COOK,IL -741,17031,COOK,IL -742,17031,COOK,IL -743,17031,COOK,IL -744,17031,COOK,IL -745,17031,COOK,IL -746,17031,COOK,IL -747,17031,COOK,IL -748,17031,COOK,IL -749,17031,COOK,IL -750,17031,COOK,IL -751,17031,COOK,IL -752,17031,COOK,IL -753,17031,COOK,IL -754,17031,COOK,IL -755,17031,COOK,IL -756,17031,COOK,IL -757,17031,COOK,IL -758,17031,COOK,IL -759,17031,COOK,IL -760,17031,COOK,IL -761,17031,COOK,IL -762,17031,COOK,IL -763,17031,COOK,IL -764,17031,COOK,IL -765,17031,COOK,IL -766,17031,COOK,IL -767,17031,COOK,IL -768,17031,COOK,IL -769,17031,COOK,IL -770,17031,COOK,IL -771,17031,COOK,IL -772,17031,COOK,IL -773,17031,COOK,IL -774,17031,COOK,IL -775,17031,COOK,IL -776,17031,COOK,IL -777,17031,COOK,IL -778,17031,COOK,IL -779,17031,COOK,IL -780,17031,COOK,IL -781,17031,COOK,IL -782,17031,COOK,IL -783,17031,COOK,IL -784,17031,COOK,IL -785,17031,COOK,IL -786,17031,COOK,IL -787,17031,COOK,IL -788,17031,COOK,IL -789,17031,COOK,IL -790,17031,COOK,IL -791,17031,COOK,IL -792,17031,COOK,IL -793,17031,COOK,IL -794,17031,COOK,IL -795,17031,COOK,IL -796,17031,COOK,IL -797,17031,COOK,IL -798,17031,COOK,IL -799,17031,COOK,IL -800,17031,COOK,IL -801,17031,COOK,IL -802,17031,COOK,IL -803,17031,COOK,IL -804,17031,COOK,IL -805,17031,COOK,IL -806,17031,COOK,IL -807,17031,COOK,IL -808,17031,COOK,IL -809,17031,COOK,IL -810,17031,COOK,IL -811,17031,COOK,IL -812,17031,COOK,IL -813,17031,COOK,IL -814,17031,COOK,IL -815,17031,COOK,IL -816,17031,COOK,IL -817,17031,COOK,IL -818,17031,COOK,IL -819,17031,COOK,IL -820,17031,COOK,IL -821,17031,COOK,IL -822,17031,COOK,IL -823,17031,COOK,IL -824,17031,COOK,IL -825,17031,COOK,IL -826,17031,COOK,IL -827,17031,COOK,IL -828,17031,COOK,IL -829,17031,COOK,IL -830,17031,COOK,IL -831,17031,COOK,IL -832,17031,COOK,IL -833,17031,COOK,IL -834,17031,COOK,IL -835,17031,COOK,IL -836,17031,COOK,IL -837,17031,COOK,IL -838,17031,COOK,IL -839,17031,COOK,IL -840,17031,COOK,IL -841,17031,COOK,IL -842,17031,COOK,IL -843,17031,COOK,IL -844,17031,COOK,IL -845,17031,COOK,IL -846,17031,COOK,IL -847,17031,COOK,IL -848,17031,COOK,IL -849,17031,COOK,IL -850,17031,COOK,IL -851,17031,COOK,IL -852,17031,COOK,IL -853,17031,COOK,IL -854,17031,COOK,IL -855,17031,COOK,IL -856,17031,COOK,IL -857,17031,COOK,IL -858,17031,COOK,IL -859,17031,COOK,IL -860,17031,COOK,IL -861,17031,COOK,IL -862,17031,COOK,IL -863,17031,COOK,IL -864,17031,COOK,IL -865,17031,COOK,IL -866,17031,COOK,IL -867,17031,COOK,IL -868,17031,COOK,IL -869,17031,COOK,IL -870,17031,COOK,IL -871,17031,COOK,IL -872,17031,COOK,IL -873,17031,COOK,IL -874,17031,COOK,IL -875,17031,COOK,IL -876,17031,COOK,IL -877,17031,COOK,IL -878,17031,COOK,IL -879,17031,COOK,IL -880,17031,COOK,IL -881,17031,COOK,IL -882,17031,COOK,IL -883,17031,COOK,IL -884,17031,COOK,IL -885,17031,COOK,IL -886,17031,COOK,IL -887,17031,COOK,IL -888,17031,COOK,IL -889,17031,COOK,IL -890,17031,COOK,IL -891,17031,COOK,IL -892,17031,COOK,IL -893,17031,COOK,IL -894,17031,COOK,IL -895,17031,COOK,IL -896,17031,COOK,IL -897,17031,COOK,IL -898,17031,COOK,IL -899,17031,COOK,IL -900,17031,COOK,IL -901,17031,COOK,IL -902,17031,COOK,IL -903,17031,COOK,IL -904,17031,COOK,IL -905,17031,COOK,IL -906,17031,COOK,IL -907,17031,COOK,IL -908,17031,COOK,IL -909,17031,COOK,IL -910,17031,COOK,IL -911,17031,COOK,IL -912,17031,COOK,IL -913,17031,COOK,IL -914,17031,COOK,IL -915,17031,COOK,IL -916,17031,COOK,IL -917,17031,COOK,IL -918,17031,COOK,IL -919,17031,COOK,IL -920,17031,COOK,IL -921,17031,COOK,IL -922,17031,COOK,IL -923,17031,COOK,IL -924,17031,COOK,IL -925,17031,COOK,IL -926,17031,COOK,IL -927,17031,COOK,IL -928,17031,COOK,IL -929,17031,COOK,IL -930,17031,COOK,IL -931,17031,COOK,IL -932,17031,COOK,IL -933,17031,COOK,IL -934,17031,COOK,IL -935,17031,COOK,IL -936,17031,COOK,IL -937,17031,COOK,IL -938,17031,COOK,IL -939,17031,COOK,IL -940,17031,COOK,IL -941,17031,COOK,IL -942,17031,COOK,IL -943,17031,COOK,IL -944,17031,COOK,IL -945,17031,COOK,IL -946,17031,COOK,IL -947,17031,COOK,IL -948,17031,COOK,IL -949,17031,COOK,IL -950,17031,COOK,IL -951,17031,COOK,IL -952,17031,COOK,IL -953,17031,COOK,IL -954,17031,COOK,IL -955,17031,COOK,IL -956,17031,COOK,IL -957,17031,COOK,IL -958,17031,COOK,IL -959,17031,COOK,IL -960,17031,COOK,IL -961,17031,COOK,IL -962,17031,COOK,IL -963,17031,COOK,IL -964,17031,COOK,IL -965,17031,COOK,IL -966,17031,COOK,IL -967,17031,COOK,IL -968,17031,COOK,IL -969,17031,COOK,IL -970,17031,COOK,IL -971,17031,COOK,IL -972,17031,COOK,IL -973,17031,COOK,IL -974,17031,COOK,IL -975,17031,COOK,IL -976,17031,COOK,IL -977,17031,COOK,IL -978,17031,COOK,IL -979,17031,COOK,IL -980,17031,COOK,IL -981,17031,COOK,IL -982,17031,COOK,IL -983,17031,COOK,IL -984,17031,COOK,IL -985,17031,COOK,IL -986,17031,COOK,IL -987,17031,COOK,IL -988,17031,COOK,IL -989,17031,COOK,IL -990,17031,COOK,IL -991,17031,COOK,IL -992,17031,COOK,IL -993,17031,COOK,IL -994,17031,COOK,IL -995,17031,COOK,IL -996,17031,COOK,IL -997,17031,COOK,IL -998,17031,COOK,IL -999,17031,COOK,IL -1000,17031,COOK,IL -1001,17031,COOK,IL -1002,17031,COOK,IL -1003,17031,COOK,IL -1004,17031,COOK,IL -1005,17031,COOK,IL -1006,17031,COOK,IL -1007,17031,COOK,IL -1008,17031,COOK,IL -1009,17031,COOK,IL -1010,17031,COOK,IL -1011,17031,COOK,IL -1012,17031,COOK,IL -1013,17031,COOK,IL -1014,17031,COOK,IL -1015,17031,COOK,IL -1016,17031,COOK,IL -1017,17031,COOK,IL -1018,17031,COOK,IL -1019,17031,COOK,IL -1020,17031,COOK,IL -1021,17031,COOK,IL -1022,17031,COOK,IL -1023,17031,COOK,IL -1024,17031,COOK,IL -1025,17031,COOK,IL -1026,17031,COOK,IL -1027,17031,COOK,IL -1028,17031,COOK,IL -1029,17031,COOK,IL -1030,17031,COOK,IL -1031,17031,COOK,IL -1032,17031,COOK,IL -1033,17031,COOK,IL -1034,17031,COOK,IL -1035,17031,COOK,IL -1036,17031,COOK,IL -1037,17031,COOK,IL -1038,17031,COOK,IL -1039,17031,COOK,IL -1040,17031,COOK,IL -1041,17031,COOK,IL -1042,17031,COOK,IL -1043,17031,COOK,IL -1044,17031,COOK,IL -1045,17031,COOK,IL -1046,17031,COOK,IL -1047,17031,COOK,IL -1048,17031,COOK,IL -1049,17031,COOK,IL -1050,17031,COOK,IL -1051,17031,COOK,IL -1052,17031,COOK,IL -1053,17031,COOK,IL -1054,17031,COOK,IL -1055,17031,COOK,IL -1056,17031,COOK,IL -1057,17031,COOK,IL -1058,17031,COOK,IL -1059,17031,COOK,IL -1060,17031,COOK,IL -1061,17031,COOK,IL -1062,17031,COOK,IL -1063,17031,COOK,IL -1064,17031,COOK,IL -1065,17031,COOK,IL -1066,17031,COOK,IL -1067,17031,COOK,IL -1068,17031,COOK,IL -1069,17031,COOK,IL -1070,17031,COOK,IL -1071,17031,COOK,IL -1072,17031,COOK,IL -1073,17031,COOK,IL -1074,17031,COOK,IL -1075,17031,COOK,IL -1076,17031,COOK,IL -1077,17031,COOK,IL -1078,17031,COOK,IL -1079,17031,COOK,IL -1080,17031,COOK,IL -1081,17031,COOK,IL -1082,17031,COOK,IL -1083,17031,COOK,IL -1084,17031,COOK,IL -1085,17031,COOK,IL -1086,17031,COOK,IL -1087,17031,COOK,IL -1088,17031,COOK,IL -1089,17031,COOK,IL -1090,17031,COOK,IL -1091,17031,COOK,IL -1092,17031,COOK,IL -1093,17031,COOK,IL -1094,17031,COOK,IL -1095,17031,COOK,IL -1096,17031,COOK,IL -1097,17031,COOK,IL -1098,17031,COOK,IL -1099,17031,COOK,IL -1100,17031,COOK,IL -1101,17031,COOK,IL -1102,17031,COOK,IL -1103,17031,COOK,IL -1104,17031,COOK,IL -1105,17031,COOK,IL -1106,17031,COOK,IL -1107,17031,COOK,IL -1108,17031,COOK,IL -1109,17031,COOK,IL -1110,17031,COOK,IL -1111,17031,COOK,IL -1112,17031,COOK,IL -1113,17031,COOK,IL -1114,17031,COOK,IL -1115,17031,COOK,IL -1116,17031,COOK,IL -1117,17031,COOK,IL -1118,17031,COOK,IL -1119,17031,COOK,IL -1120,17031,COOK,IL -1121,17031,COOK,IL -1122,17031,COOK,IL -1123,17031,COOK,IL -1124,17031,COOK,IL -1125,17031,COOK,IL -1126,17031,COOK,IL -1127,17031,COOK,IL -1128,17031,COOK,IL -1129,17031,COOK,IL -1130,17031,COOK,IL -1131,17031,COOK,IL -1132,17031,COOK,IL -1133,17031,COOK,IL -1134,17031,COOK,IL -1135,17031,COOK,IL -1136,17031,COOK,IL -1137,17031,COOK,IL -1138,17031,COOK,IL -1139,17031,COOK,IL -1140,17031,COOK,IL -1141,17031,COOK,IL -1142,17031,COOK,IL -1143,17031,COOK,IL -1144,17031,COOK,IL -1145,17031,COOK,IL -1146,17031,COOK,IL -1147,17031,COOK,IL -1148,17031,COOK,IL -1149,17031,COOK,IL -1150,17031,COOK,IL -1151,17031,COOK,IL -1152,17031,COOK,IL -1153,17031,COOK,IL -1154,17031,COOK,IL -1155,17031,COOK,IL -1156,17031,COOK,IL -1157,17031,COOK,IL -1158,17031,COOK,IL -1159,17031,COOK,IL -1161,17031,COOK,IL -1162,17031,COOK,IL -1163,17031,COOK,IL -1164,17031,COOK,IL -1165,17031,COOK,IL -1166,17031,COOK,IL -1167,17031,COOK,IL -1168,17031,COOK,IL -1169,17031,COOK,IL -1170,17031,COOK,IL -1171,17031,COOK,IL -1172,17031,COOK,IL -1173,17031,COOK,IL -1174,17031,COOK,IL -1175,17031,COOK,IL -1176,17031,COOK,IL -1177,17031,COOK,IL -1178,17031,COOK,IL -1179,17031,COOK,IL -1180,17031,COOK,IL -1181,17031,COOK,IL -1182,17031,COOK,IL -1183,17031,COOK,IL -1184,17031,COOK,IL -1185,17031,COOK,IL -1186,17031,COOK,IL -1187,17031,COOK,IL -1188,17031,COOK,IL -1189,17031,COOK,IL -1190,17031,COOK,IL -1191,17031,COOK,IL -1192,17031,COOK,IL -1193,17031,COOK,IL -1194,17031,COOK,IL -1195,17031,COOK,IL -1196,17031,COOK,IL -1197,17031,COOK,IL -1198,17031,COOK,IL -1199,17031,COOK,IL -1200,17031,COOK,IL -1201,17031,COOK,IL -1202,17031,COOK,IL -1203,17031,COOK,IL -1204,17031,COOK,IL -1205,17031,COOK,IL -1206,17031,COOK,IL -1207,17031,COOK,IL -1208,17031,COOK,IL -1209,17031,COOK,IL -1210,17031,COOK,IL -1211,17031,COOK,IL -1212,17031,COOK,IL -1213,17031,COOK,IL -1214,17031,COOK,IL -1215,17031,COOK,IL -1216,17031,COOK,IL -1217,17031,COOK,IL -1218,17031,COOK,IL -1219,17031,COOK,IL -1220,17031,COOK,IL -1221,17031,COOK,IL -1222,17031,COOK,IL -1223,17031,COOK,IL -1224,17031,COOK,IL -1225,17031,COOK,IL -1226,17031,COOK,IL -1227,17031,COOK,IL -1228,17031,COOK,IL -1229,17031,COOK,IL -1230,17031,COOK,IL -1231,17031,COOK,IL -1232,17031,COOK,IL -1233,17031,COOK,IL -1234,17031,COOK,IL -1235,17031,COOK,IL -1236,17031,COOK,IL -1237,17031,COOK,IL -1238,17031,COOK,IL -1239,17031,COOK,IL -1240,17031,COOK,IL -1241,17031,COOK,IL -1242,17031,COOK,IL -1243,17031,COOK,IL -1244,17031,COOK,IL -1245,17031,COOK,IL -1246,17031,COOK,IL -1247,17031,COOK,IL -1248,17031,COOK,IL -1249,17031,COOK,IL -1250,17031,COOK,IL -1251,17031,COOK,IL -1252,17031,COOK,IL -1253,17031,COOK,IL -1254,17031,COOK,IL -1255,17031,COOK,IL -1256,17031,COOK,IL -1257,17031,COOK,IL -1258,17031,COOK,IL -1259,17031,COOK,IL -1260,17031,COOK,IL -1261,17031,COOK,IL -1262,17031,COOK,IL -1263,17031,COOK,IL -1264,17031,COOK,IL -1265,17031,COOK,IL -1266,17031,COOK,IL -1267,17031,COOK,IL -1268,17031,COOK,IL -1269,17031,COOK,IL -1270,17031,COOK,IL -1271,17031,COOK,IL -1272,17031,COOK,IL -1273,17031,COOK,IL -1274,17031,COOK,IL -1275,17031,COOK,IL -1276,17031,COOK,IL -1277,17031,COOK,IL -1278,17031,COOK,IL -1279,17031,COOK,IL -1280,17031,COOK,IL -1281,17031,COOK,IL -1282,17031,COOK,IL -1283,17031,COOK,IL -1284,17031,COOK,IL -1285,17031,COOK,IL -1286,17031,COOK,IL -1287,17031,COOK,IL -1288,17031,COOK,IL -1289,17031,COOK,IL -1290,17031,COOK,IL -1291,17031,COOK,IL -1292,17031,COOK,IL -1293,17031,COOK,IL -1294,17031,COOK,IL -1295,17031,COOK,IL -1296,17031,COOK,IL -1297,17031,COOK,IL -1298,17031,COOK,IL -1299,17031,COOK,IL -1300,17031,COOK,IL -1301,17031,COOK,IL -1302,17031,COOK,IL -1303,17031,COOK,IL -1304,17031,COOK,IL -1305,17031,COOK,IL -1306,17031,COOK,IL -1307,17031,COOK,IL -1308,17031,COOK,IL -1309,17031,COOK,IL -1310,17031,COOK,IL -1311,17031,COOK,IL -1312,17031,COOK,IL -1313,17031,COOK,IL -1314,17031,COOK,IL -1315,17031,COOK,IL -1316,17031,COOK,IL -1317,17031,COOK,IL -1318,17031,COOK,IL -1319,17031,COOK,IL -1320,17031,COOK,IL -1321,17031,COOK,IL -1322,17031,COOK,IL -1323,17031,COOK,IL -1324,17031,COOK,IL -1325,17031,COOK,IL -1326,17031,COOK,IL -1327,17031,COOK,IL -1328,17031,COOK,IL -1329,17031,COOK,IL -1330,17031,COOK,IL -1331,17031,COOK,IL -1332,17031,COOK,IL -1333,17031,COOK,IL -1334,17031,COOK,IL -1335,17031,COOK,IL -1336,17031,COOK,IL -1337,17031,COOK,IL -1338,17031,COOK,IL -1339,17031,COOK,IL -1340,17031,COOK,IL -1341,17031,COOK,IL -1342,17031,COOK,IL -1343,17031,COOK,IL -1344,17031,COOK,IL -1345,17031,COOK,IL -1346,17031,COOK,IL -1347,17031,COOK,IL -1348,17031,COOK,IL -1349,17031,COOK,IL -1350,17031,COOK,IL -1351,17031,COOK,IL -1352,17031,COOK,IL -1353,17031,COOK,IL -1354,17031,COOK,IL -1355,17031,COOK,IL -1356,17031,COOK,IL -1357,17031,COOK,IL -1358,17031,COOK,IL -1359,17031,COOK,IL -1360,17031,COOK,IL -1361,17031,COOK,IL -1362,17031,COOK,IL -1363,17031,COOK,IL -1364,17031,COOK,IL -1365,17031,COOK,IL -1366,17031,COOK,IL -1367,17031,COOK,IL -1368,17031,COOK,IL -1369,17031,COOK,IL -1370,17031,COOK,IL -1371,17031,COOK,IL -1372,17031,COOK,IL -1373,17031,COOK,IL -1374,17031,COOK,IL -1375,17031,COOK,IL -1376,17031,COOK,IL -1377,17031,COOK,IL -1378,17031,COOK,IL -1379,17031,COOK,IL -1380,17031,COOK,IL -1381,17031,COOK,IL -1382,17031,COOK,IL -1383,17031,COOK,IL -1384,17031,COOK,IL -1385,17031,COOK,IL -1386,17031,COOK,IL -1387,17031,COOK,IL -1388,17031,COOK,IL -1389,17031,COOK,IL -1390,17031,COOK,IL -1391,17031,COOK,IL -1392,17031,COOK,IL -1393,17031,COOK,IL -1394,17031,COOK,IL -1395,17031,COOK,IL -1396,17031,COOK,IL -1397,17031,COOK,IL -1398,17031,COOK,IL -1399,17031,COOK,IL -1400,17031,COOK,IL -1401,17031,COOK,IL -1402,17031,COOK,IL -1403,17031,COOK,IL -1404,17031,COOK,IL -1405,17031,COOK,IL -1406,17031,COOK,IL -1407,17031,COOK,IL -1408,17031,COOK,IL -1409,17031,COOK,IL -1410,17031,COOK,IL -1411,17031,COOK,IL -1412,17031,COOK,IL -1413,17031,COOK,IL -1414,17031,COOK,IL -1415,17031,COOK,IL -1416,17031,COOK,IL -1417,17031,COOK,IL -1418,17031,COOK,IL -1419,17031,COOK,IL -1420,17031,COOK,IL -1421,17031,COOK,IL -1422,17031,COOK,IL -1423,17031,COOK,IL -1424,17031,COOK,IL -1425,17031,COOK,IL -1426,17031,COOK,IL -1427,17031,COOK,IL -1428,17031,COOK,IL -1429,17031,COOK,IL -1430,17031,COOK,IL -1431,17031,COOK,IL -1432,17031,COOK,IL -1433,17031,COOK,IL -1434,17031,COOK,IL -1435,17031,COOK,IL -1436,17031,COOK,IL -1437,17031,COOK,IL -1438,17031,COOK,IL -1439,17031,COOK,IL -1440,17031,COOK,IL -1441,17031,COOK,IL -1442,17031,COOK,IL -1443,17031,COOK,IL -1444,17031,COOK,IL -1445,17031,COOK,IL -1446,17031,COOK,IL -1447,17031,COOK,IL -1448,17031,COOK,IL -1449,17031,COOK,IL -1450,17031,COOK,IL -1451,17031,COOK,IL -1452,17031,COOK,IL -1453,17031,COOK,IL -1454,17031,COOK,IL -1455,17031,COOK,IL -1456,17031,COOK,IL -1457,17031,COOK,IL -1458,17031,COOK,IL -1459,17031,COOK,IL -1460,17031,COOK,IL -1461,17031,COOK,IL -1462,17031,COOK,IL -1463,17031,COOK,IL -1464,17031,COOK,IL -1465,17031,COOK,IL -1466,17031,COOK,IL -1467,17031,COOK,IL -1468,17031,COOK,IL -1469,17031,COOK,IL -1470,17031,COOK,IL -1471,17031,COOK,IL -1472,17031,COOK,IL -1473,17031,COOK,IL -1474,17031,COOK,IL -1475,17031,COOK,IL -1476,17031,COOK,IL -1477,17031,COOK,IL -1478,17031,COOK,IL -1479,17031,COOK,IL -1480,17031,COOK,IL -1481,17031,COOK,IL -1482,17031,COOK,IL -1483,17031,COOK,IL -1484,17031,COOK,IL -1485,17031,COOK,IL -1486,17031,COOK,IL -1487,17031,COOK,IL -1488,17031,COOK,IL -1489,17031,COOK,IL -1490,17031,COOK,IL -1491,17031,COOK,IL -1492,17031,COOK,IL -1493,17031,COOK,IL -1494,17031,COOK,IL -1495,17031,COOK,IL -1496,17031,COOK,IL -1497,17031,COOK,IL -1498,17031,COOK,IL -1499,17031,COOK,IL -1500,17031,COOK,IL -1501,17031,COOK,IL -1502,17031,COOK,IL -1503,17031,COOK,IL -1504,17031,COOK,IL -1505,17031,COOK,IL -1506,17031,COOK,IL -1507,17031,COOK,IL -1508,17031,COOK,IL -1509,17031,COOK,IL -1510,17031,COOK,IL -1511,17031,COOK,IL -1512,17031,COOK,IL -1513,17031,COOK,IL -1514,17031,COOK,IL -1515,17031,COOK,IL -1516,17031,COOK,IL -1517,17031,COOK,IL -1518,17031,COOK,IL -1519,17031,COOK,IL -1520,17031,COOK,IL -1521,17031,COOK,IL -1522,17031,COOK,IL -1523,17031,COOK,IL -1524,17031,COOK,IL -1525,17031,COOK,IL -1526,17031,COOK,IL -1527,17031,COOK,IL -1528,17031,COOK,IL -1529,17031,COOK,IL -1530,17031,COOK,IL -1531,17031,COOK,IL -1532,17031,COOK,IL -1533,17031,COOK,IL -1534,17031,COOK,IL -1535,17031,COOK,IL -1536,17031,COOK,IL -1537,17031,COOK,IL -1538,17031,COOK,IL -1539,17031,COOK,IL -1540,17031,COOK,IL -1541,17031,COOK,IL -1542,17031,COOK,IL -1543,17031,COOK,IL -1544,17031,COOK,IL -1545,17031,COOK,IL -1546,17031,COOK,IL -1547,17031,COOK,IL -1548,17031,COOK,IL -1549,17031,COOK,IL -1550,17031,COOK,IL -1551,17031,COOK,IL -1552,17031,COOK,IL -1553,17031,COOK,IL -1554,17031,COOK,IL -1555,17031,COOK,IL -1556,17031,COOK,IL -1557,17031,COOK,IL -1558,17031,COOK,IL -1559,17031,COOK,IL -1560,17031,COOK,IL -1561,17031,COOK,IL -1562,17031,COOK,IL -1563,17031,COOK,IL -1564,17031,COOK,IL -1565,17031,COOK,IL -1566,17031,COOK,IL -1567,17031,COOK,IL -1568,17031,COOK,IL -1569,17031,COOK,IL -1570,17031,COOK,IL -1571,17031,COOK,IL -1572,17031,COOK,IL -1573,17031,COOK,IL -1574,17031,COOK,IL -1575,17031,COOK,IL -1576,17031,COOK,IL -1577,17031,COOK,IL -1578,17031,COOK,IL -1579,17031,COOK,IL -1580,17031,COOK,IL -1581,17031,COOK,IL -1582,17031,COOK,IL -1583,17031,COOK,IL -1584,17031,COOK,IL -1585,17031,COOK,IL -1586,17031,COOK,IL -1587,17031,COOK,IL -1588,17031,COOK,IL -1589,17031,COOK,IL -1590,17031,COOK,IL -1591,17031,COOK,IL -1592,17031,COOK,IL -1593,17031,COOK,IL -1594,17031,COOK,IL -1595,17031,COOK,IL -1596,17031,COOK,IL -1597,17031,COOK,IL -1598,17031,COOK,IL -1599,17031,COOK,IL -1600,17031,COOK,IL -1601,17031,COOK,IL -1602,17031,COOK,IL -1603,17031,COOK,IL -1604,17031,COOK,IL -1605,17031,COOK,IL -1606,17031,COOK,IL -1607,17031,COOK,IL -1608,17031,COOK,IL -1609,17031,COOK,IL -1610,17031,COOK,IL -1611,17031,COOK,IL -1612,17031,COOK,IL -1613,17031,COOK,IL -1614,17031,COOK,IL -1615,17031,COOK,IL -1616,17031,COOK,IL -1617,17031,COOK,IL -1618,17031,COOK,IL -1619,17031,COOK,IL -1620,17031,COOK,IL -1621,17031,COOK,IL -1622,17031,COOK,IL -1623,17031,COOK,IL -1624,17031,COOK,IL -1625,17031,COOK,IL -1626,17031,COOK,IL -1627,17031,COOK,IL -1628,17031,COOK,IL -1629,17031,COOK,IL -1630,17031,COOK,IL -1631,17031,COOK,IL -1632,17031,COOK,IL -1633,17031,COOK,IL -1634,17031,COOK,IL -1635,17031,COOK,IL -1636,17031,COOK,IL -1637,17031,COOK,IL -1638,17031,COOK,IL -1639,17031,COOK,IL -1640,17031,COOK,IL -1641,17031,COOK,IL -1642,17031,COOK,IL -1643,17031,COOK,IL -1644,17031,COOK,IL -1645,17031,COOK,IL -1646,17031,COOK,IL -1647,17031,COOK,IL -1648,17031,COOK,IL -1649,17031,COOK,IL -1650,17031,COOK,IL -1651,17031,COOK,IL -1652,17031,COOK,IL -1653,17031,COOK,IL -1654,17031,COOK,IL -1655,17031,COOK,IL -1656,17031,COOK,IL -1657,17031,COOK,IL -1658,17031,COOK,IL -1659,17031,COOK,IL -1660,17031,COOK,IL -1661,17031,COOK,IL -1662,17031,COOK,IL -1663,17031,COOK,IL -1664,17031,COOK,IL -1665,17031,COOK,IL -1666,17031,COOK,IL -1667,17031,COOK,IL -1668,17031,COOK,IL -1669,17031,COOK,IL -1670,17031,COOK,IL -1671,17031,COOK,IL -1672,17031,COOK,IL -1673,17031,COOK,IL -1674,17031,COOK,IL -1675,17031,COOK,IL -1676,17031,COOK,IL -1677,17031,COOK,IL -1678,17031,COOK,IL -1679,17031,COOK,IL -1680,17031,COOK,IL -1681,17031,COOK,IL -1682,17031,COOK,IL -1683,17031,COOK,IL -1684,17031,COOK,IL -1685,17031,COOK,IL -1686,17031,COOK,IL -1687,17031,COOK,IL -1688,17031,COOK,IL -1689,17031,COOK,IL -1690,17031,COOK,IL -1691,17031,COOK,IL -1692,17031,COOK,IL -1693,17031,COOK,IL -1694,17031,COOK,IL -1695,17031,COOK,IL -1696,17031,COOK,IL -1697,17031,COOK,IL -1698,17031,COOK,IL -1699,17031,COOK,IL -1700,17031,COOK,IL -1701,17031,COOK,IL -1702,17031,COOK,IL -1703,17031,COOK,IL -1704,17031,COOK,IL -1705,17031,COOK,IL -1706,17031,COOK,IL -1707,17031,COOK,IL -1708,17031,COOK,IL -1709,17031,COOK,IL -1710,17031,COOK,IL -1711,17031,COOK,IL -1712,17031,COOK,IL -1713,17031,COOK,IL -1714,17031,COOK,IL -1715,17031,COOK,IL -1716,17031,COOK,IL -1717,17031,COOK,IL -1718,17031,COOK,IL -1719,17031,COOK,IL -1720,17031,COOK,IL -1721,17031,COOK,IL -1722,17031,COOK,IL -1723,17031,COOK,IL -1724,17031,COOK,IL -1725,17031,COOK,IL -1726,17031,COOK,IL -1727,17031,COOK,IL -1728,17031,COOK,IL -1729,17031,COOK,IL -1730,17031,COOK,IL -1731,17031,COOK,IL -1732,17031,COOK,IL -1733,17043,DUPAGE,IL -1734,17043,DUPAGE,IL -1735,17043,DUPAGE,IL -1736,17043,DUPAGE,IL -1737,17043,DUPAGE,IL -1738,17043,DUPAGE,IL -1739,17043,DUPAGE,IL -1740,17043,DUPAGE,IL -1741,17043,DUPAGE,IL -1742,17043,DUPAGE,IL -1743,17043,DUPAGE,IL -1744,17043,DUPAGE,IL -1745,17043,DUPAGE,IL -1746,17043,DUPAGE,IL -1747,17043,DUPAGE,IL -1748,17043,DUPAGE,IL -1749,17043,DUPAGE,IL -1750,17043,DUPAGE,IL -1751,17043,DUPAGE,IL -1752,17043,DUPAGE,IL -1753,17043,DUPAGE,IL -1754,17043,DUPAGE,IL -1755,17043,DUPAGE,IL -1756,17043,DUPAGE,IL -1757,17043,DUPAGE,IL -1758,17043,DUPAGE,IL -1759,17043,DUPAGE,IL -1760,17043,DUPAGE,IL -1761,17043,DUPAGE,IL -1762,17043,DUPAGE,IL -1763,17043,DUPAGE,IL -1764,17043,DUPAGE,IL -1765,17043,DUPAGE,IL -1766,17043,DUPAGE,IL -1767,17043,DUPAGE,IL -1768,17043,DUPAGE,IL -1769,17043,DUPAGE,IL -1770,17043,DUPAGE,IL -1771,17043,DUPAGE,IL -1772,17043,DUPAGE,IL -1773,17043,DUPAGE,IL -1774,17043,DUPAGE,IL -1775,17043,DUPAGE,IL -1776,17043,DUPAGE,IL -1777,17043,DUPAGE,IL -1778,17043,DUPAGE,IL -1779,17043,DUPAGE,IL -1780,17043,DUPAGE,IL -1781,17043,DUPAGE,IL -1782,17043,DUPAGE,IL -1783,17043,DUPAGE,IL -1784,17043,DUPAGE,IL -1785,17043,DUPAGE,IL -1786,17043,DUPAGE,IL -1787,17043,DUPAGE,IL -1788,17043,DUPAGE,IL -1789,17043,DUPAGE,IL -1790,17043,DUPAGE,IL -1791,17043,DUPAGE,IL -1792,17043,DUPAGE,IL -1793,17043,DUPAGE,IL -1794,17043,DUPAGE,IL -1795,17043,DUPAGE,IL -1796,17043,DUPAGE,IL -1797,17043,DUPAGE,IL -1798,17043,DUPAGE,IL -1799,17043,DUPAGE,IL -1800,17043,DUPAGE,IL -1801,17043,DUPAGE,IL -1802,17043,DUPAGE,IL -1803,17043,DUPAGE,IL -1804,17043,DUPAGE,IL -1805,17043,DUPAGE,IL -1806,17043,DUPAGE,IL -1807,17043,DUPAGE,IL -1808,17043,DUPAGE,IL -1809,17043,DUPAGE,IL -1810,17043,DUPAGE,IL -1811,17043,DUPAGE,IL -1812,17043,DUPAGE,IL -1813,17043,DUPAGE,IL -1814,17043,DUPAGE,IL -1815,17043,DUPAGE,IL -1816,17043,DUPAGE,IL -1817,17043,DUPAGE,IL -1818,17043,DUPAGE,IL -1819,17043,DUPAGE,IL -1820,17043,DUPAGE,IL -1821,17043,DUPAGE,IL -1822,17043,DUPAGE,IL -1823,17043,DUPAGE,IL -1824,17043,DUPAGE,IL -1825,17043,DUPAGE,IL -1826,17043,DUPAGE,IL -1827,17043,DUPAGE,IL -1828,17043,DUPAGE,IL -1829,17043,DUPAGE,IL -1830,17043,DUPAGE,IL -1831,17043,DUPAGE,IL -1832,17043,DUPAGE,IL -1833,17043,DUPAGE,IL -1834,17043,DUPAGE,IL -1835,17043,DUPAGE,IL -1836,17043,DUPAGE,IL -1837,17043,DUPAGE,IL -1838,17043,DUPAGE,IL -1839,17043,DUPAGE,IL -1840,17043,DUPAGE,IL -1841,17043,DUPAGE,IL -1842,17043,DUPAGE,IL -1843,17043,DUPAGE,IL -1844,17043,DUPAGE,IL -1845,17043,DUPAGE,IL -1846,17043,DUPAGE,IL -1847,17043,DUPAGE,IL -1848,17043,DUPAGE,IL -1849,17043,DUPAGE,IL -1850,17043,DUPAGE,IL -1851,17043,DUPAGE,IL -1852,17043,DUPAGE,IL -1853,17043,DUPAGE,IL -1854,17043,DUPAGE,IL -1855,17043,DUPAGE,IL -1856,17043,DUPAGE,IL -1857,17043,DUPAGE,IL -1858,17043,DUPAGE,IL -1859,17043,DUPAGE,IL -1860,17043,DUPAGE,IL -1861,17043,DUPAGE,IL -1862,17043,DUPAGE,IL -1863,17043,DUPAGE,IL -1864,17043,DUPAGE,IL -1865,17043,DUPAGE,IL -1866,17043,DUPAGE,IL -1867,17043,DUPAGE,IL -1868,17043,DUPAGE,IL -1869,17043,DUPAGE,IL -1870,17043,DUPAGE,IL -1871,17043,DUPAGE,IL -1872,17043,DUPAGE,IL -1873,17043,DUPAGE,IL -1874,17043,DUPAGE,IL -1875,17043,DUPAGE,IL -1876,17043,DUPAGE,IL -1877,17043,DUPAGE,IL -1878,17043,DUPAGE,IL -1879,17043,DUPAGE,IL -1880,17043,DUPAGE,IL -1881,17043,DUPAGE,IL -1882,17043,DUPAGE,IL -1883,17043,DUPAGE,IL -1884,17043,DUPAGE,IL -1885,17043,DUPAGE,IL -1886,17043,DUPAGE,IL -1887,17043,DUPAGE,IL -1888,17043,DUPAGE,IL -1889,17043,DUPAGE,IL -1890,17043,DUPAGE,IL -1891,17043,DUPAGE,IL -1892,17043,DUPAGE,IL -1893,17043,DUPAGE,IL -1894,17043,DUPAGE,IL -1895,17043,DUPAGE,IL -1896,17043,DUPAGE,IL -1897,17043,DUPAGE,IL -1898,17043,DUPAGE,IL -1899,17043,DUPAGE,IL -1900,17043,DUPAGE,IL -1901,17043,DUPAGE,IL -1902,17043,DUPAGE,IL -1903,17043,DUPAGE,IL -1904,17043,DUPAGE,IL -1905,17043,DUPAGE,IL -1906,17043,DUPAGE,IL -1907,17043,DUPAGE,IL -1908,17043,DUPAGE,IL -1909,17043,DUPAGE,IL -1910,17043,DUPAGE,IL -1911,17043,DUPAGE,IL -1912,17043,DUPAGE,IL -1913,17043,DUPAGE,IL -1914,17043,DUPAGE,IL -1915,17043,DUPAGE,IL -1916,17043,DUPAGE,IL -1917,17043,DUPAGE,IL -1918,17043,DUPAGE,IL -1919,17043,DUPAGE,IL -1920,17043,DUPAGE,IL -1921,17043,DUPAGE,IL -1922,17043,DUPAGE,IL -1923,17043,DUPAGE,IL -1924,17043,DUPAGE,IL -1925,17043,DUPAGE,IL -1926,17043,DUPAGE,IL -1927,17043,DUPAGE,IL -1928,17043,DUPAGE,IL -1929,17043,DUPAGE,IL -1930,17043,DUPAGE,IL -1931,17043,DUPAGE,IL -1932,17043,DUPAGE,IL -1933,17043,DUPAGE,IL -1934,17043,DUPAGE,IL -1935,17043,DUPAGE,IL -1936,17043,DUPAGE,IL -1937,17043,DUPAGE,IL -1938,17043,DUPAGE,IL -1939,17043,DUPAGE,IL -1940,17043,DUPAGE,IL -1941,17043,DUPAGE,IL -1942,17043,DUPAGE,IL -1943,17043,DUPAGE,IL -1944,17043,DUPAGE,IL -1945,17043,DUPAGE,IL -1946,17043,DUPAGE,IL -1947,17043,DUPAGE,IL -1948,17043,DUPAGE,IL -1949,17043,DUPAGE,IL -1950,17043,DUPAGE,IL -1951,17043,DUPAGE,IL -1952,17043,DUPAGE,IL -1953,17043,DUPAGE,IL -1954,17043,DUPAGE,IL -1955,17043,DUPAGE,IL -1956,17043,DUPAGE,IL -1957,17043,DUPAGE,IL -1958,17043,DUPAGE,IL -1959,17043,DUPAGE,IL -1960,17043,DUPAGE,IL -1961,17043,DUPAGE,IL -1962,17043,DUPAGE,IL -1963,17043,DUPAGE,IL -1964,17043,DUPAGE,IL -1965,17043,DUPAGE,IL -1966,17043,DUPAGE,IL -1967,17043,DUPAGE,IL -1968,17043,DUPAGE,IL -1969,17043,DUPAGE,IL -1970,17043,DUPAGE,IL -1971,17043,DUPAGE,IL -1972,17043,DUPAGE,IL -1973,17043,DUPAGE,IL -1974,17043,DUPAGE,IL -1975,17043,DUPAGE,IL -1976,17043,DUPAGE,IL -1977,17043,DUPAGE,IL -1978,17043,DUPAGE,IL -1979,17043,DUPAGE,IL -1980,17043,DUPAGE,IL -1981,17043,DUPAGE,IL -1982,17043,DUPAGE,IL -1983,17043,DUPAGE,IL -1984,17043,DUPAGE,IL -1985,17043,DUPAGE,IL -1986,17043,DUPAGE,IL -1987,17043,DUPAGE,IL -1988,17043,DUPAGE,IL -1989,17043,DUPAGE,IL -1990,17043,DUPAGE,IL -1991,17043,DUPAGE,IL -1992,17043,DUPAGE,IL -1993,17043,DUPAGE,IL -1994,17043,DUPAGE,IL -1995,17043,DUPAGE,IL -1996,17043,DUPAGE,IL -1997,17043,DUPAGE,IL -1998,17043,DUPAGE,IL -1999,17043,DUPAGE,IL -2000,17043,DUPAGE,IL -2001,17043,DUPAGE,IL -2002,17043,DUPAGE,IL -2003,17043,DUPAGE,IL -2004,17043,DUPAGE,IL -2005,17043,DUPAGE,IL -2006,17043,DUPAGE,IL -2007,17043,DUPAGE,IL -2008,17043,DUPAGE,IL -2009,17043,DUPAGE,IL -2010,17043,DUPAGE,IL -2011,17043,DUPAGE,IL -2012,17043,DUPAGE,IL -2013,17043,DUPAGE,IL -2014,17043,DUPAGE,IL -2015,17043,DUPAGE,IL -2016,17043,DUPAGE,IL -2017,17043,DUPAGE,IL -2018,17043,DUPAGE,IL -2019,17043,DUPAGE,IL -2020,17043,DUPAGE,IL -2021,17043,DUPAGE,IL -2022,17043,DUPAGE,IL -2023,17043,DUPAGE,IL -2024,17043,DUPAGE,IL -2025,17043,DUPAGE,IL -2026,17043,DUPAGE,IL -2027,17043,DUPAGE,IL -2028,17043,DUPAGE,IL -2029,17043,DUPAGE,IL -2030,17043,DUPAGE,IL -2031,17043,DUPAGE,IL -2032,17043,DUPAGE,IL -2033,17043,DUPAGE,IL -2034,17043,DUPAGE,IL -2035,17043,DUPAGE,IL -2036,17043,DUPAGE,IL -2037,17043,DUPAGE,IL -2038,17043,DUPAGE,IL -2039,17043,DUPAGE,IL -2040,17043,DUPAGE,IL -2041,17043,DUPAGE,IL -2042,17043,DUPAGE,IL -2043,17043,DUPAGE,IL -2044,17043,DUPAGE,IL -2045,17043,DUPAGE,IL -2046,17043,DUPAGE,IL -2047,17043,DUPAGE,IL -2048,17043,DUPAGE,IL -2049,17043,DUPAGE,IL -2050,17043,DUPAGE,IL -2051,17043,DUPAGE,IL -2052,17043,DUPAGE,IL -2053,17043,DUPAGE,IL -2054,17043,DUPAGE,IL -2055,17043,DUPAGE,IL -2056,17043,DUPAGE,IL -2057,17043,DUPAGE,IL -2058,17043,DUPAGE,IL -2059,17043,DUPAGE,IL -2060,17043,DUPAGE,IL -2061,17043,DUPAGE,IL -2062,17043,DUPAGE,IL -2063,17043,DUPAGE,IL -2064,17043,DUPAGE,IL -2065,17043,DUPAGE,IL -2066,17043,DUPAGE,IL -2067,17043,DUPAGE,IL -2068,17043,DUPAGE,IL -2069,17043,DUPAGE,IL -2070,17043,DUPAGE,IL -2071,17043,DUPAGE,IL -2072,17043,DUPAGE,IL -2073,17043,DUPAGE,IL -2074,17043,DUPAGE,IL -2075,17043,DUPAGE,IL -2076,17043,DUPAGE,IL -2077,17043,DUPAGE,IL -2078,17043,DUPAGE,IL -2079,17043,DUPAGE,IL -2080,17043,DUPAGE,IL -2081,17043,DUPAGE,IL -2082,17043,DUPAGE,IL -2083,17043,DUPAGE,IL -2084,17043,DUPAGE,IL -2085,17043,DUPAGE,IL -2086,17043,DUPAGE,IL -2087,17043,DUPAGE,IL -2088,17043,DUPAGE,IL -2089,17043,DUPAGE,IL -2090,17043,DUPAGE,IL -2091,17043,DUPAGE,IL -2092,17043,DUPAGE,IL -2093,17043,DUPAGE,IL -2094,17043,DUPAGE,IL -2095,17043,DUPAGE,IL -2096,17043,DUPAGE,IL -2097,17043,DUPAGE,IL -2098,17043,DUPAGE,IL -2099,17043,DUPAGE,IL -2100,17043,DUPAGE,IL -2101,17043,DUPAGE,IL -2102,17043,DUPAGE,IL -2103,17043,DUPAGE,IL -2104,17043,DUPAGE,IL -2105,17043,DUPAGE,IL -2106,17043,DUPAGE,IL -2107,17043,DUPAGE,IL -2108,17043,DUPAGE,IL -2109,17043,DUPAGE,IL -2110,17043,DUPAGE,IL -2111,17043,DUPAGE,IL -2112,17089,KANE,IL -2113,17089,KANE,IL -2114,17089,KANE,IL -2115,17089,KANE,IL -2116,17089,KANE,IL -2117,17089,KANE,IL -2118,17089,KANE,IL -2119,17089,KANE,IL -2120,17089,KANE,IL -2121,17089,KANE,IL -2122,17089,KANE,IL -2123,17089,KANE,IL -2124,17089,KANE,IL -2125,17089,KANE,IL -2126,17089,KANE,IL -2127,17089,KANE,IL -2128,17089,KANE,IL -2129,17089,KANE,IL -2130,17089,KANE,IL -2131,17089,KANE,IL -2132,17089,KANE,IL -2133,17089,KANE,IL -2134,17089,KANE,IL -2135,17089,KANE,IL -2136,17089,KANE,IL -2137,17089,KANE,IL -2138,17089,KANE,IL -2139,17089,KANE,IL -2140,17089,KANE,IL -2141,17089,KANE,IL -2142,17089,KANE,IL -2143,17089,KANE,IL -2144,17089,KANE,IL -2145,17089,KANE,IL -2146,17089,KANE,IL -2147,17089,KANE,IL -2148,17089,KANE,IL -2149,17089,KANE,IL -2150,17089,KANE,IL -2151,17089,KANE,IL -2152,17089,KANE,IL -2153,17089,KANE,IL -2154,17089,KANE,IL -2155,17089,KANE,IL -2156,17089,KANE,IL -2157,17089,KANE,IL -2158,17089,KANE,IL -2159,17089,KANE,IL -2160,17089,KANE,IL -2161,17089,KANE,IL -2162,17089,KANE,IL -2163,17089,KANE,IL -2164,17089,KANE,IL -2165,17089,KANE,IL -2166,17089,KANE,IL -2167,17089,KANE,IL -2168,17089,KANE,IL -2169,17089,KANE,IL -2170,17089,KANE,IL -2171,17089,KANE,IL -2172,17089,KANE,IL -2173,17089,KANE,IL -2174,17089,KANE,IL -2175,17089,KANE,IL -2176,17089,KANE,IL -2177,17089,KANE,IL -2178,17089,KANE,IL -2179,17089,KANE,IL -2180,17089,KANE,IL -2181,17089,KANE,IL -2182,17089,KANE,IL -2183,17089,KANE,IL -2184,17089,KANE,IL -2185,17089,KANE,IL -2186,17089,KANE,IL -2187,17089,KANE,IL -2188,17089,KANE,IL -2189,17089,KANE,IL -2190,17089,KANE,IL -2191,17089,KANE,IL -2192,17089,KANE,IL -2193,17089,KANE,IL -2194,17089,KANE,IL -2195,17089,KANE,IL -2196,17089,KANE,IL -2197,17089,KANE,IL -2198,17089,KANE,IL -2199,17089,KANE,IL -2200,17089,KANE,IL -2201,17089,KANE,IL -2202,17089,KANE,IL -2203,17089,KANE,IL -2204,17089,KANE,IL -2205,17089,KANE,IL -2206,17089,KANE,IL -2207,17089,KANE,IL -2208,17089,KANE,IL -2209,17089,KANE,IL -2210,17089,KANE,IL -2211,17089,KANE,IL -2212,17089,KANE,IL -2213,17089,KANE,IL -2214,17089,KANE,IL -2215,17089,KANE,IL -2216,17089,KANE,IL -2217,17089,KANE,IL -2218,17089,KANE,IL -2219,17089,KANE,IL -2220,17089,KANE,IL -2221,17089,KANE,IL -2222,17089,KANE,IL -2223,17089,KANE,IL -2224,17089,KANE,IL -2225,17089,KANE,IL -2226,17089,KANE,IL -2227,17089,KANE,IL -2228,17089,KANE,IL -2229,17089,KANE,IL -2230,17089,KANE,IL -2231,17089,KANE,IL -2232,17089,KANE,IL -2233,17089,KANE,IL -2234,17089,KANE,IL -2235,17089,KANE,IL -2236,17089,KANE,IL -2237,17089,KANE,IL -2238,17089,KANE,IL -2239,17089,KANE,IL -2240,17089,KANE,IL -2241,17089,KANE,IL -2242,17089,KANE,IL -2243,17089,KANE,IL -2244,17089,KANE,IL -2245,17089,KANE,IL -2246,17089,KANE,IL -2247,17089,KANE,IL -2248,17089,KANE,IL -2249,17089,KANE,IL -2250,17089,KANE,IL -2251,17089,KANE,IL -2252,17089,KANE,IL -2253,17089,KANE,IL -2254,17089,KANE,IL -2255,17089,KANE,IL -2256,17089,KANE,IL -2257,17089,KANE,IL -2258,17089,KANE,IL -2259,17089,KANE,IL -2260,17089,KANE,IL -2261,17089,KANE,IL -2262,17089,KANE,IL -2263,17089,KANE,IL -2264,17089,KANE,IL -2265,17089,KANE,IL -2266,17089,KANE,IL -2267,17089,KANE,IL -2268,17089,KANE,IL -2269,17089,KANE,IL -2270,17089,KANE,IL -2271,17089,KANE,IL -2272,17089,KANE,IL -2273,17089,KANE,IL -2274,17089,KANE,IL -2275,17089,KANE,IL -2276,17089,KANE,IL -2277,17089,KANE,IL -2278,17089,KANE,IL -2279,17089,KANE,IL -2280,17089,KANE,IL -2281,17089,KANE,IL -2282,17089,KANE,IL -2283,17089,KANE,IL -2284,17089,KANE,IL -2285,17089,KANE,IL -2286,17089,KANE,IL -2287,17089,KANE,IL -2288,17089,KANE,IL -2289,17089,KANE,IL -2290,17089,KANE,IL -2291,17089,KANE,IL -2292,17089,KANE,IL -2293,17089,KANE,IL -2294,17089,KANE,IL -2295,17089,KANE,IL -2296,17089,KANE,IL -2297,17089,KANE,IL -2298,17089,KANE,IL -2299,17089,KANE,IL -2300,17089,KANE,IL -2301,17089,KANE,IL -2302,17089,KANE,IL -2303,17089,KANE,IL -2304,17089,KANE,IL -2305,17093,KENDALL,IL -2306,17093,KENDALL,IL -2307,17093,KENDALL,IL -2308,17093,KENDALL,IL -2309,17093,KENDALL,IL -2310,17093,KENDALL,IL -2311,17093,KENDALL,IL -2312,17093,KENDALL,IL -2313,17093,KENDALL,IL -2314,17093,KENDALL,IL -2315,17093,KENDALL,IL -2316,17093,KENDALL,IL -2317,17093,KENDALL,IL -2318,17093,KENDALL,IL -2319,17093,KENDALL,IL -2320,17093,KENDALL,IL -2321,17093,KENDALL,IL -2322,17093,KENDALL,IL -2323,17093,KENDALL,IL -2324,17093,KENDALL,IL -2325,17093,KENDALL,IL -2326,17097,LAKE,IL -2327,17097,LAKE,IL -2328,17097,LAKE,IL -2329,17097,LAKE,IL -2330,17097,LAKE,IL -2331,17097,LAKE,IL -2332,17097,LAKE,IL -2333,17097,LAKE,IL -2334,17097,LAKE,IL -2335,17097,LAKE,IL -2336,17097,LAKE,IL -2337,17097,LAKE,IL -2338,17097,LAKE,IL -2339,17097,LAKE,IL -2340,17097,LAKE,IL -2341,17097,LAKE,IL -2342,17097,LAKE,IL -2343,17097,LAKE,IL -2344,17097,LAKE,IL -2345,17097,LAKE,IL -2346,17097,LAKE,IL -2347,17097,LAKE,IL -2348,17097,LAKE,IL -2349,17097,LAKE,IL -2350,17097,LAKE,IL -2351,17097,LAKE,IL -2352,17097,LAKE,IL -2353,17097,LAKE,IL -2354,17097,LAKE,IL -2355,17097,LAKE,IL -2356,17097,LAKE,IL -2357,17097,LAKE,IL -2358,17097,LAKE,IL -2359,17097,LAKE,IL -2360,17097,LAKE,IL -2361,17097,LAKE,IL -2362,17097,LAKE,IL -2363,17097,LAKE,IL -2364,17097,LAKE,IL -2365,17097,LAKE,IL -2366,17097,LAKE,IL -2367,17097,LAKE,IL -2368,17097,LAKE,IL -2369,17097,LAKE,IL -2370,17097,LAKE,IL -2371,17097,LAKE,IL -2372,17097,LAKE,IL -2373,17097,LAKE,IL -2374,17097,LAKE,IL -2375,17097,LAKE,IL -2376,17097,LAKE,IL -2377,17097,LAKE,IL -2378,17097,LAKE,IL -2379,17097,LAKE,IL -2380,17097,LAKE,IL -2381,17097,LAKE,IL -2382,17097,LAKE,IL -2383,17097,LAKE,IL -2384,17097,LAKE,IL -2385,17097,LAKE,IL -2386,17097,LAKE,IL -2387,17097,LAKE,IL -2388,17097,LAKE,IL -2389,17097,LAKE,IL -2390,17097,LAKE,IL -2391,17097,LAKE,IL -2392,17097,LAKE,IL -2393,17097,LAKE,IL -2394,17097,LAKE,IL -2395,17097,LAKE,IL -2396,17097,LAKE,IL -2397,17097,LAKE,IL -2398,17097,LAKE,IL -2399,17097,LAKE,IL -2400,17097,LAKE,IL -2401,17097,LAKE,IL -2402,17097,LAKE,IL -2403,17097,LAKE,IL -2404,17097,LAKE,IL -2405,17097,LAKE,IL -2406,17097,LAKE,IL -2407,17097,LAKE,IL -2408,17097,LAKE,IL -2409,17097,LAKE,IL -2410,17097,LAKE,IL -2411,17097,LAKE,IL -2412,17097,LAKE,IL -2413,17097,LAKE,IL -2414,17097,LAKE,IL -2415,17097,LAKE,IL -2416,17097,LAKE,IL -2417,17097,LAKE,IL -2418,17097,LAKE,IL -2419,17097,LAKE,IL -2420,17097,LAKE,IL -2421,17097,LAKE,IL -2422,17097,LAKE,IL -2423,17097,LAKE,IL -2424,17097,LAKE,IL -2425,17097,LAKE,IL -2426,17097,LAKE,IL -2427,17097,LAKE,IL -2428,17097,LAKE,IL -2429,17097,LAKE,IL -2430,17097,LAKE,IL -2431,17097,LAKE,IL -2432,17097,LAKE,IL -2433,17097,LAKE,IL -2434,17097,LAKE,IL -2435,17097,LAKE,IL -2436,17097,LAKE,IL -2437,17097,LAKE,IL -2438,17097,LAKE,IL -2439,17097,LAKE,IL -2440,17097,LAKE,IL -2441,17097,LAKE,IL -2442,17097,LAKE,IL -2443,17097,LAKE,IL -2444,17097,LAKE,IL -2445,17097,LAKE,IL -2446,17097,LAKE,IL -2447,17097,LAKE,IL -2448,17097,LAKE,IL -2449,17097,LAKE,IL -2450,17097,LAKE,IL -2451,17097,LAKE,IL -2452,17097,LAKE,IL -2453,17097,LAKE,IL -2454,17097,LAKE,IL -2455,17097,LAKE,IL -2456,17097,LAKE,IL -2457,17097,LAKE,IL -2458,17097,LAKE,IL -2459,17097,LAKE,IL -2460,17097,LAKE,IL -2461,17097,LAKE,IL -2462,17097,LAKE,IL -2463,17097,LAKE,IL -2464,17097,LAKE,IL -2465,17097,LAKE,IL -2466,17097,LAKE,IL -2467,17097,LAKE,IL -2468,17097,LAKE,IL -2469,17097,LAKE,IL -2470,17097,LAKE,IL -2471,17097,LAKE,IL -2472,17097,LAKE,IL -2473,17097,LAKE,IL -2474,17097,LAKE,IL -2475,17097,LAKE,IL -2476,17097,LAKE,IL -2477,17097,LAKE,IL -2478,17097,LAKE,IL -2479,17097,LAKE,IL -2480,17097,LAKE,IL -2481,17097,LAKE,IL -2482,17097,LAKE,IL -2483,17097,LAKE,IL -2484,17097,LAKE,IL -2485,17097,LAKE,IL -2486,17097,LAKE,IL -2487,17097,LAKE,IL -2488,17097,LAKE,IL -2489,17097,LAKE,IL -2490,17097,LAKE,IL -2491,17097,LAKE,IL -2492,17097,LAKE,IL -2493,17097,LAKE,IL -2494,17097,LAKE,IL -2495,17097,LAKE,IL -2496,17097,LAKE,IL -2497,17097,LAKE,IL -2498,17097,LAKE,IL -2499,17097,LAKE,IL -2500,17097,LAKE,IL -2501,17097,LAKE,IL -2502,17097,LAKE,IL -2503,17097,LAKE,IL -2504,17097,LAKE,IL -2505,17097,LAKE,IL -2506,17097,LAKE,IL -2507,17097,LAKE,IL -2508,17097,LAKE,IL -2509,17097,LAKE,IL -2510,17097,LAKE,IL -2511,17097,LAKE,IL -2512,17097,LAKE,IL -2513,17097,LAKE,IL -2514,17097,LAKE,IL -2515,17097,LAKE,IL -2516,17097,LAKE,IL -2517,17097,LAKE,IL -2518,17097,LAKE,IL -2519,17097,LAKE,IL -2520,17097,LAKE,IL -2521,17097,LAKE,IL -2522,17097,LAKE,IL -2523,17097,LAKE,IL -2524,17097,LAKE,IL -2525,17097,LAKE,IL -2526,17097,LAKE,IL -2527,17097,LAKE,IL -2528,17097,LAKE,IL -2529,17097,LAKE,IL -2530,17097,LAKE,IL -2531,17097,LAKE,IL -2532,17097,LAKE,IL -2533,17097,LAKE,IL -2534,17097,LAKE,IL -2535,17097,LAKE,IL -2536,17097,LAKE,IL -2537,17097,LAKE,IL -2538,17097,LAKE,IL -2539,17097,LAKE,IL -2540,17097,LAKE,IL -2541,17097,LAKE,IL -2542,17097,LAKE,IL -2543,17097,LAKE,IL -2544,17097,LAKE,IL -2545,17097,LAKE,IL -2546,17097,LAKE,IL -2547,17097,LAKE,IL -2548,17097,LAKE,IL -2549,17097,LAKE,IL -2550,17097,LAKE,IL -2551,17097,LAKE,IL -2552,17097,LAKE,IL -2553,17097,LAKE,IL -2554,17097,LAKE,IL -2555,17097,LAKE,IL -2556,17097,LAKE,IL -2557,17097,LAKE,IL -2558,17097,LAKE,IL -2559,17097,LAKE,IL -2560,17097,LAKE,IL -2561,17097,LAKE,IL -2562,17097,LAKE,IL -2563,17097,LAKE,IL -2564,17097,LAKE,IL -2565,17097,LAKE,IL -2566,17097,LAKE,IL -2567,17097,LAKE,IL -2568,17097,LAKE,IL -2569,17097,LAKE,IL -2570,17097,LAKE,IL -2571,17097,LAKE,IL -2572,17097,LAKE,IL -2573,17097,LAKE,IL -2574,17097,LAKE,IL -2575,17097,LAKE,IL -2576,17097,LAKE,IL -2577,17097,LAKE,IL -2578,17097,LAKE,IL -2579,17097,LAKE,IL -2580,17097,LAKE,IL -2581,17097,LAKE,IL -2582,17097,LAKE,IL -2583,17097,LAKE,IL -2584,17111,MCHENRY,IL -2585,17111,MCHENRY,IL -2586,17111,MCHENRY,IL -2587,17111,MCHENRY,IL -2588,17111,MCHENRY,IL -2589,17111,MCHENRY,IL -2590,17111,MCHENRY,IL -2591,17111,MCHENRY,IL -2592,17111,MCHENRY,IL -2593,17111,MCHENRY,IL -2594,17111,MCHENRY,IL -2595,17111,MCHENRY,IL -2596,17111,MCHENRY,IL -2597,17111,MCHENRY,IL -2598,17111,MCHENRY,IL -2599,17111,MCHENRY,IL -2600,17111,MCHENRY,IL -2601,17111,MCHENRY,IL -2602,17111,MCHENRY,IL -2603,17111,MCHENRY,IL -2604,17111,MCHENRY,IL -2605,17111,MCHENRY,IL -2606,17111,MCHENRY,IL -2607,17111,MCHENRY,IL -2608,17111,MCHENRY,IL -2609,17111,MCHENRY,IL -2610,17111,MCHENRY,IL -2611,17111,MCHENRY,IL -2612,17111,MCHENRY,IL -2613,17111,MCHENRY,IL -2614,17111,MCHENRY,IL -2615,17111,MCHENRY,IL -2616,17111,MCHENRY,IL -2617,17111,MCHENRY,IL -2618,17111,MCHENRY,IL -2619,17111,MCHENRY,IL -2620,17111,MCHENRY,IL -2621,17111,MCHENRY,IL -2622,17111,MCHENRY,IL -2623,17111,MCHENRY,IL -2624,17111,MCHENRY,IL -2625,17111,MCHENRY,IL -2626,17111,MCHENRY,IL -2627,17111,MCHENRY,IL -2628,17111,MCHENRY,IL -2629,17111,MCHENRY,IL -2630,17111,MCHENRY,IL -2631,17111,MCHENRY,IL -2632,17111,MCHENRY,IL -2633,17111,MCHENRY,IL -2634,17111,MCHENRY,IL -2635,17111,MCHENRY,IL -2636,17111,MCHENRY,IL -2637,17111,MCHENRY,IL -2638,17111,MCHENRY,IL -2639,17111,MCHENRY,IL -2640,17111,MCHENRY,IL -2641,17111,MCHENRY,IL -2642,17111,MCHENRY,IL -2643,17111,MCHENRY,IL -2644,17111,MCHENRY,IL -2645,17111,MCHENRY,IL -2646,17111,MCHENRY,IL -2647,17111,MCHENRY,IL -2648,17111,MCHENRY,IL -2649,17111,MCHENRY,IL -2650,17111,MCHENRY,IL -2651,17111,MCHENRY,IL -2652,17111,MCHENRY,IL -2653,17111,MCHENRY,IL -2654,17111,MCHENRY,IL -2655,17111,MCHENRY,IL -2656,17111,MCHENRY,IL -2657,17111,MCHENRY,IL -2658,17111,MCHENRY,IL -2659,17111,MCHENRY,IL -2660,17111,MCHENRY,IL -2661,17111,MCHENRY,IL -2662,17111,MCHENRY,IL -2663,17111,MCHENRY,IL -2664,17111,MCHENRY,IL -2665,17111,MCHENRY,IL -2666,17111,MCHENRY,IL -2667,17111,MCHENRY,IL -2668,17111,MCHENRY,IL -2669,17111,MCHENRY,IL -2670,17111,MCHENRY,IL -2671,17111,MCHENRY,IL -2672,17111,MCHENRY,IL -2673,17111,MCHENRY,IL -2674,17111,MCHENRY,IL -2675,17111,MCHENRY,IL -2676,17111,MCHENRY,IL -2677,17111,MCHENRY,IL -2678,17111,MCHENRY,IL -2679,17111,MCHENRY,IL -2680,17111,MCHENRY,IL -2681,17111,MCHENRY,IL -2682,17111,MCHENRY,IL -2683,17111,MCHENRY,IL -2684,17111,MCHENRY,IL -2685,17111,MCHENRY,IL -2686,17111,MCHENRY,IL -2687,17111,MCHENRY,IL -2688,17111,MCHENRY,IL -2689,17111,MCHENRY,IL -2690,17111,MCHENRY,IL -2691,17111,MCHENRY,IL -2692,17111,MCHENRY,IL -2693,17111,MCHENRY,IL -2694,17111,MCHENRY,IL -2695,17111,MCHENRY,IL -2696,17111,MCHENRY,IL -2697,17111,MCHENRY,IL -2698,17111,MCHENRY,IL -2699,17111,MCHENRY,IL -2700,17111,MCHENRY,IL -2701,17111,MCHENRY,IL -2702,17111,MCHENRY,IL -2703,17197,WILL,IL -2704,17197,WILL,IL -2705,17197,WILL,IL -2706,17197,WILL,IL -2707,17197,WILL,IL -2708,17197,WILL,IL -2709,17197,WILL,IL -2710,17197,WILL,IL -2711,17197,WILL,IL -2712,17197,WILL,IL -2713,17197,WILL,IL -2714,17197,WILL,IL -2715,17197,WILL,IL -2716,17197,WILL,IL -2717,17197,WILL,IL -2718,17197,WILL,IL -2719,17197,WILL,IL -2720,17197,WILL,IL -2721,17197,WILL,IL -2722,17197,WILL,IL -2723,17197,WILL,IL -2724,17197,WILL,IL -2725,17197,WILL,IL -2726,17197,WILL,IL -2727,17197,WILL,IL -2728,17197,WILL,IL -2729,17197,WILL,IL -2730,17197,WILL,IL -2731,17197,WILL,IL -2732,17197,WILL,IL -2733,17197,WILL,IL -2734,17197,WILL,IL -2735,17197,WILL,IL -2736,17197,WILL,IL -2737,17197,WILL,IL -2738,17197,WILL,IL -2739,17197,WILL,IL -2740,17197,WILL,IL -2741,17197,WILL,IL -2742,17197,WILL,IL -2743,17197,WILL,IL -2744,17197,WILL,IL -2745,17197,WILL,IL -2746,17197,WILL,IL -2747,17197,WILL,IL -2748,17197,WILL,IL -2749,17197,WILL,IL -2750,17197,WILL,IL -2751,17197,WILL,IL -2752,17197,WILL,IL -2753,17197,WILL,IL -2754,17197,WILL,IL -2755,17197,WILL,IL -2756,17197,WILL,IL -2757,17197,WILL,IL -2758,17197,WILL,IL -2759,17197,WILL,IL -2760,17197,WILL,IL -2761,17197,WILL,IL -2762,17197,WILL,IL -2763,17197,WILL,IL -2764,17197,WILL,IL -2765,17197,WILL,IL -2766,17197,WILL,IL -2767,17197,WILL,IL -2768,17197,WILL,IL -2769,17197,WILL,IL -2770,17197,WILL,IL -2771,17197,WILL,IL -2772,17197,WILL,IL -2773,17197,WILL,IL -2774,17197,WILL,IL -2775,17197,WILL,IL -2776,17197,WILL,IL -2777,17197,WILL,IL -2778,17197,WILL,IL -2779,17197,WILL,IL -2780,17197,WILL,IL -2781,17197,WILL,IL -2782,17197,WILL,IL -2783,17197,WILL,IL -2784,17197,WILL,IL -2785,17197,WILL,IL -2786,17197,WILL,IL -2787,17197,WILL,IL -2788,17197,WILL,IL -2789,17197,WILL,IL -2790,17197,WILL,IL -2791,17197,WILL,IL -2792,17197,WILL,IL -2793,17197,WILL,IL -2794,17197,WILL,IL -2795,17197,WILL,IL -2796,17197,WILL,IL -2797,17197,WILL,IL -2798,17197,WILL,IL -2799,17197,WILL,IL -2800,17197,WILL,IL -2801,17197,WILL,IL -2802,17197,WILL,IL -2803,17197,WILL,IL -2804,17197,WILL,IL -2805,17197,WILL,IL -2806,17197,WILL,IL -2807,17197,WILL,IL -2808,17197,WILL,IL -2809,17197,WILL,IL -2810,17197,WILL,IL -2811,17197,WILL,IL -2812,17197,WILL,IL -2813,17197,WILL,IL -2814,17197,WILL,IL -2815,17197,WILL,IL -2816,17197,WILL,IL -2817,17197,WILL,IL -2818,17197,WILL,IL -2819,17197,WILL,IL -2820,17197,WILL,IL -2821,17197,WILL,IL -2822,17197,WILL,IL -2823,17197,WILL,IL -2824,17197,WILL,IL -2825,17197,WILL,IL -2826,17197,WILL,IL -2827,17197,WILL,IL -2828,17197,WILL,IL -2829,17197,WILL,IL -2830,17197,WILL,IL -2831,17197,WILL,IL -2832,17197,WILL,IL -2833,17197,WILL,IL -2834,17197,WILL,IL -2835,17197,WILL,IL -2836,17197,WILL,IL -2837,17197,WILL,IL -2838,17197,WILL,IL -2839,17197,WILL,IL -2840,17197,WILL,IL -2841,17197,WILL,IL -2842,17197,WILL,IL -2843,17197,WILL,IL -2844,17197,WILL,IL -2845,17197,WILL,IL -2846,17197,WILL,IL -2847,17197,WILL,IL -2848,17197,WILL,IL -2849,17197,WILL,IL -2850,17197,WILL,IL -2851,17197,WILL,IL -2852,17197,WILL,IL -2853,17197,WILL,IL -2854,17197,WILL,IL -2855,17197,WILL,IL -2856,17197,WILL,IL -2857,17197,WILL,IL -2858,17197,WILL,IL -2859,17197,WILL,IL -2860,17197,WILL,IL -2861,17197,WILL,IL -2862,17197,WILL,IL -2863,17197,WILL,IL -2864,17197,WILL,IL -2865,17197,WILL,IL -2866,17197,WILL,IL -2867,17197,WILL,IL -2868,17197,WILL,IL -2869,17197,WILL,IL -2870,17197,WILL,IL -2871,17197,WILL,IL -2872,17197,WILL,IL -2873,17197,WILL,IL -2874,17197,WILL,IL -2875,17197,WILL,IL -2876,17197,WILL,IL -2877,17197,WILL,IL -2878,17197,WILL,IL -2879,17197,WILL,IL -2880,17197,WILL,IL -2881,17197,WILL,IL -2882,17197,WILL,IL -2883,17197,WILL,IL -2884,17197,WILL,IL -2885,17197,WILL,IL -2886,17197,WILL,IL -2887,17197,WILL,IL -2888,17197,WILL,IL -2889,17197,WILL,IL -2890,17197,WILL,IL -2891,17197,WILL,IL -2892,17197,WILL,IL -2893,17197,WILL,IL -2894,17197,WILL,IL -2895,17197,WILL,IL -2896,17197,WILL,IL -2897,17197,WILL,IL -2898,17197,WILL,IL -2899,17197,WILL,IL -2900,17197,WILL,IL -2901,17197,WILL,IL -2902,17197,WILL,IL -2903,17197,WILL,IL -2904,17197,WILL,IL -2905,17197,WILL,IL -2906,17197,WILL,IL -2907,17197,WILL,IL -2908,17197,WILL,IL -2909,17197,WILL,IL -2910,17197,WILL,IL -2911,17197,WILL,IL -2912,17197,WILL,IL -2913,17197,WILL,IL -2914,17197,WILL,IL -2915,17197,WILL,IL -2916,17197,WILL,IL -2917,17197,WILL,IL -2918,17197,WILL,IL -2919,17197,WILL,IL -2920,17197,WILL,IL -2921,17197,WILL,IL -2922,17197,WILL,IL -2923,17197,WILL,IL -2924,17197,WILL,IL -2925,17197,WILL,IL -2926,17197,WILL,IL -2927,17063,GRUNDY,IL -2928,17063,GRUNDY,IL -2929,17063,GRUNDY,IL -2930,17063,GRUNDY,IL -2931,17063,GRUNDY,IL -2932,17063,GRUNDY,IL -2933,17063,GRUNDY,IL -2934,17063,GRUNDY,IL -2935,17063,GRUNDY,IL -2936,17063,GRUNDY,IL -2937,17063,GRUNDY,IL -2938,17063,GRUNDY,IL -2939,17063,GRUNDY,IL -2940,17063,GRUNDY,IL -2941,17063,GRUNDY,IL -2942,17063,GRUNDY,IL -2943,17063,GRUNDY,IL -2944,17063,GRUNDY,IL -2945,17063,GRUNDY,IL -2946,17063,GRUNDY,IL -2947,17063,GRUNDY,IL -2948,17063,GRUNDY,IL -2949,17063,GRUNDY,IL -2950,17063,GRUNDY,IL -2951,17007,BOONE,IL -2952,17007,BOONE,IL -2953,17007,BOONE,IL -2954,17007,BOONE,IL -2955,17007,BOONE,IL -2956,17007,BOONE,IL -2957,17007,BOONE,IL -2958,17007,BOONE,IL -2959,17007,BOONE,IL -2960,17007,BOONE,IL -2961,17007,BOONE,IL -2962,17007,BOONE,IL -2963,17007,BOONE,IL -2964,17007,BOONE,IL -2965,17007,BOONE,IL -2966,17007,BOONE,IL -2967,17007,BOONE,IL -2968,17007,BOONE,IL -2969,17007,BOONE,IL -2970,17007,BOONE,IL -2971,17007,BOONE,IL -2972,17007,BOONE,IL -2973,17007,BOONE,IL -2974,17007,BOONE,IL -2975,17007,BOONE,IL -2976,17037,DEKALB,IL -2977,17037,DEKALB,IL -2978,17037,DEKALB,IL -2979,17037,DEKALB,IL -2980,17037,DEKALB,IL -2981,17037,DEKALB,IL -2982,17037,DEKALB,IL -2983,17037,DEKALB,IL -2984,17037,DEKALB,IL -2985,17037,DEKALB,IL -2986,17037,DEKALB,IL -2987,17037,DEKALB,IL -2988,17037,DEKALB,IL -2989,17037,DEKALB,IL -2990,17037,DEKALB,IL -2991,17037,DEKALB,IL -2992,17037,DEKALB,IL -2993,17037,DEKALB,IL -2994,17037,DEKALB,IL -2995,17037,DEKALB,IL -2996,17037,DEKALB,IL -2997,17037,DEKALB,IL -2998,17037,DEKALB,IL -2999,17037,DEKALB,IL -3000,17037,DEKALB,IL -3001,17037,DEKALB,IL -3002,17037,DEKALB,IL -3003,17037,DEKALB,IL -3004,17037,DEKALB,IL -3005,17037,DEKALB,IL -3006,17037,DEKALB,IL -3007,17037,DEKALB,IL -3008,17037,DEKALB,IL -3009,17037,DEKALB,IL -3010,17037,DEKALB,IL -3011,17037,DEKALB,IL -3012,17037,DEKALB,IL -3013,17037,DEKALB,IL -3014,17037,DEKALB,IL -3015,17037,DEKALB,IL -3016,17037,DEKALB,IL -3017,17037,DEKALB,IL -3018,17037,DEKALB,IL -3019,17037,DEKALB,IL -3020,17037,DEKALB,IL -3021,17037,DEKALB,IL -3022,17091,KANKAKEE,IL -3023,17091,KANKAKEE,IL -3024,17091,KANKAKEE,IL -3025,17091,KANKAKEE,IL -3026,17091,KANKAKEE,IL -3027,17091,KANKAKEE,IL -3028,17091,KANKAKEE,IL -3029,17091,KANKAKEE,IL -3030,17091,KANKAKEE,IL -3031,17091,KANKAKEE,IL -3032,17091,KANKAKEE,IL -3033,17091,KANKAKEE,IL -3034,17091,KANKAKEE,IL -3035,17091,KANKAKEE,IL -3036,17091,KANKAKEE,IL -3037,17091,KANKAKEE,IL -3038,17091,KANKAKEE,IL -3039,17091,KANKAKEE,IL -3040,17091,KANKAKEE,IL -3041,17091,KANKAKEE,IL -3042,17091,KANKAKEE,IL -3043,17091,KANKAKEE,IL -3044,17091,KANKAKEE,IL -3045,17091,KANKAKEE,IL -3046,17091,KANKAKEE,IL -3047,17091,KANKAKEE,IL -3048,17091,KANKAKEE,IL -3049,17091,KANKAKEE,IL -3050,17091,KANKAKEE,IL -3051,17091,KANKAKEE,IL -3052,17091,KANKAKEE,IL -3053,17091,KANKAKEE,IL -3054,17091,KANKAKEE,IL -3055,17091,KANKAKEE,IL -3056,17091,KANKAKEE,IL -3057,17091,KANKAKEE,IL -3058,17091,KANKAKEE,IL -3059,17091,KANKAKEE,IL -3060,17091,KANKAKEE,IL -3061,17091,KANKAKEE,IL -3062,17091,KANKAKEE,IL -3063,17091,KANKAKEE,IL -3064,17091,KANKAKEE,IL -3065,17091,KANKAKEE,IL -3066,17091,KANKAKEE,IL -3067,17091,KANKAKEE,IL -3068,17091,KANKAKEE,IL -3069,17091,KANKAKEE,IL -3070,17091,KANKAKEE,IL -3071,17091,KANKAKEE,IL -3072,17091,KANKAKEE,IL -3073,17091,KANKAKEE,IL -3074,17099,LASALLE,IL -3075,17099,LASALLE,IL -3076,17099,LASALLE,IL -3077,17099,LASALLE,IL -3078,17099,LASALLE,IL -3079,17099,LASALLE,IL -3080,17099,LASALLE,IL -3081,17099,LASALLE,IL -3082,17099,LASALLE,IL -3083,17099,LASALLE,IL -3084,17099,LASALLE,IL -3085,17099,LASALLE,IL -3086,17099,LASALLE,IL -3087,17099,LASALLE,IL -3088,17099,LASALLE,IL -3089,17099,LASALLE,IL -3090,17099,LASALLE,IL -3091,17099,LASALLE,IL -3092,17099,LASALLE,IL -3093,17099,LASALLE,IL -3094,17099,LASALLE,IL -3095,17099,LASALLE,IL -3096,17099,LASALLE,IL -3097,17099,LASALLE,IL -3098,17099,LASALLE,IL -3099,17099,LASALLE,IL -3100,17099,LASALLE,IL -3101,17099,LASALLE,IL -3102,17099,LASALLE,IL -3103,17099,LASALLE,IL -3104,17099,LASALLE,IL -3105,17099,LASALLE,IL -3106,17099,LASALLE,IL -3107,17099,LASALLE,IL -3108,17099,LASALLE,IL -3109,17099,LASALLE,IL -3110,17099,LASALLE,IL -3111,17099,LASALLE,IL -3112,17099,LASALLE,IL -3113,17099,LASALLE,IL -3114,17099,LASALLE,IL -3115,17099,LASALLE,IL -3116,17099,LASALLE,IL -3117,17099,LASALLE,IL -3118,17099,LASALLE,IL -3119,17099,LASALLE,IL -3120,17099,LASALLE,IL -3121,17099,LASALLE,IL -3122,17099,LASALLE,IL -3123,17099,LASALLE,IL -3124,17099,LASALLE,IL -3125,17099,LASALLE,IL -3126,17099,LASALLE,IL -3127,17099,LASALLE,IL -3128,17099,LASALLE,IL -3129,17099,LASALLE,IL -3130,17099,LASALLE,IL -3131,17099,LASALLE,IL -3132,17099,LASALLE,IL -3133,17099,LASALLE,IL -3134,17099,LASALLE,IL -3135,17099,LASALLE,IL -3136,17099,LASALLE,IL -3137,17099,LASALLE,IL -3138,17099,LASALLE,IL -3139,17099,LASALLE,IL -3140,17099,LASALLE,IL -3141,17099,LASALLE,IL -3142,17099,LASALLE,IL -3143,17099,LASALLE,IL -3144,17099,LASALLE,IL -3145,17099,LASALLE,IL -3146,17103,LEE,IL -3147,17103,LEE,IL -3148,17103,LEE,IL -3149,17103,LEE,IL -3150,17103,LEE,IL -3151,17103,LEE,IL -3152,17141,OGLE,IL -3153,17141,OGLE,IL -3154,17141,OGLE,IL -3155,17141,OGLE,IL -3156,17141,OGLE,IL -3157,17141,OGLE,IL -3158,17141,OGLE,IL -3159,17141,OGLE,IL -3160,17141,OGLE,IL -3161,17141,OGLE,IL -3162,17141,OGLE,IL -3163,17141,OGLE,IL -3164,17141,OGLE,IL -3165,17141,OGLE,IL -3166,17141,OGLE,IL -3167,17141,OGLE,IL -3168,17141,OGLE,IL -3169,17201,WINNEBAGO,IL -3170,17201,WINNEBAGO,IL -3171,17201,WINNEBAGO,IL -3172,17201,WINNEBAGO,IL -3173,17201,WINNEBAGO,IL -3174,17201,WINNEBAGO,IL -3175,17201,WINNEBAGO,IL -3176,17201,WINNEBAGO,IL -3177,17201,WINNEBAGO,IL -3178,17201,WINNEBAGO,IL -3179,17201,WINNEBAGO,IL -3180,17201,WINNEBAGO,IL -3181,17201,WINNEBAGO,IL -3182,17201,WINNEBAGO,IL -3183,17201,WINNEBAGO,IL -3184,17201,WINNEBAGO,IL -3185,17201,WINNEBAGO,IL -3186,17201,WINNEBAGO,IL -3187,17201,WINNEBAGO,IL -3188,17201,WINNEBAGO,IL -3189,17201,WINNEBAGO,IL -3190,17201,WINNEBAGO,IL -3191,17201,WINNEBAGO,IL -3192,17201,WINNEBAGO,IL -3193,17201,WINNEBAGO,IL -3194,17201,WINNEBAGO,IL -3195,17201,WINNEBAGO,IL -3196,17201,WINNEBAGO,IL -3197,17201,WINNEBAGO,IL -3198,17201,WINNEBAGO,IL -3199,17201,WINNEBAGO,IL -3200,17201,WINNEBAGO,IL -3201,17201,WINNEBAGO,IL -3202,17201,WINNEBAGO,IL -3203,17201,WINNEBAGO,IL -3204,17201,WINNEBAGO,IL -3205,17201,WINNEBAGO,IL -3206,17201,WINNEBAGO,IL -3207,17201,WINNEBAGO,IL -3208,17201,WINNEBAGO,IL -3209,17201,WINNEBAGO,IL -3210,17201,WINNEBAGO,IL -3211,17201,WINNEBAGO,IL -3212,17201,WINNEBAGO,IL -3213,17201,WINNEBAGO,IL -3214,17201,WINNEBAGO,IL -3215,17201,WINNEBAGO,IL -3216,17201,WINNEBAGO,IL -3217,17201,WINNEBAGO,IL -3218,17201,WINNEBAGO,IL -3219,17201,WINNEBAGO,IL -3220,17201,WINNEBAGO,IL -3221,17201,WINNEBAGO,IL -3222,17201,WINNEBAGO,IL -3223,17201,WINNEBAGO,IL -3224,17201,WINNEBAGO,IL -3225,17201,WINNEBAGO,IL -3226,17201,WINNEBAGO,IL -3227,17201,WINNEBAGO,IL -3228,17201,WINNEBAGO,IL -3229,17201,WINNEBAGO,IL -3230,17201,WINNEBAGO,IL -3231,17201,WINNEBAGO,IL -3232,17201,WINNEBAGO,IL -3233,17201,WINNEBAGO,IL -3234,17201,WINNEBAGO,IL -3235,17201,WINNEBAGO,IL -3236,17201,WINNEBAGO,IL -3237,17201,WINNEBAGO,IL -3238,17201,WINNEBAGO,IL -3239,17201,WINNEBAGO,IL -3240,17201,WINNEBAGO,IL -3241,17201,WINNEBAGO,IL -3242,17201,WINNEBAGO,IL -3243,17201,WINNEBAGO,IL -3244,17201,WINNEBAGO,IL -3245,17201,WINNEBAGO,IL -3246,17201,WINNEBAGO,IL -3247,17201,WINNEBAGO,IL -3248,18089,LAKE,IN -3249,18089,LAKE,IN -3250,18089,LAKE,IN -3251,18089,LAKE,IN -3252,18089,LAKE,IN -3253,18089,LAKE,IN -3254,18089,LAKE,IN -3255,18089,LAKE,IN -3256,18089,LAKE,IN -3257,18089,LAKE,IN -3258,18089,LAKE,IN -3259,18089,LAKE,IN -3260,18089,LAKE,IN -3261,18089,LAKE,IN -3262,18089,LAKE,IN -3263,18089,LAKE,IN -3264,18089,LAKE,IN -3265,18089,LAKE,IN -3266,18089,LAKE,IN -3267,18089,LAKE,IN -3268,18089,LAKE,IN -3269,18089,LAKE,IN -3270,18089,LAKE,IN -3271,18089,LAKE,IN -3272,18089,LAKE,IN -3273,18089,LAKE,IN -3274,18089,LAKE,IN -3275,18089,LAKE,IN -3276,18089,LAKE,IN -3277,18089,LAKE,IN -3278,18089,LAKE,IN -3279,18089,LAKE,IN -3280,18089,LAKE,IN -3281,18089,LAKE,IN -3282,18089,LAKE,IN -3283,18089,LAKE,IN -3284,18089,LAKE,IN -3285,18089,LAKE,IN -3286,18089,LAKE,IN -3287,18089,LAKE,IN -3288,18089,LAKE,IN -3289,18089,LAKE,IN -3290,18089,LAKE,IN -3291,18089,LAKE,IN -3292,18089,LAKE,IN -3293,18089,LAKE,IN -3294,18089,LAKE,IN -3295,18089,LAKE,IN -3296,18089,LAKE,IN -3297,18089,LAKE,IN -3298,18089,LAKE,IN -3299,18089,LAKE,IN -3300,18089,LAKE,IN -3301,18089,LAKE,IN -3302,18089,LAKE,IN -3303,18089,LAKE,IN -3304,18089,LAKE,IN -3305,18089,LAKE,IN -3306,18089,LAKE,IN -3307,18089,LAKE,IN -3308,18089,LAKE,IN -3309,18089,LAKE,IN -3310,18089,LAKE,IN -3311,18089,LAKE,IN -3312,18089,LAKE,IN -3313,18089,LAKE,IN -3314,18089,LAKE,IN -3315,18089,LAKE,IN -3316,18089,LAKE,IN -3317,18089,LAKE,IN -3318,18089,LAKE,IN -3319,18089,LAKE,IN -3320,18089,LAKE,IN -3321,18089,LAKE,IN -3322,18089,LAKE,IN -3323,18089,LAKE,IN -3324,18089,LAKE,IN -3325,18089,LAKE,IN -3326,18089,LAKE,IN -3327,18089,LAKE,IN -3328,18089,LAKE,IN -3329,18089,LAKE,IN -3330,18089,LAKE,IN -3331,18089,LAKE,IN -3332,18089,LAKE,IN -3333,18089,LAKE,IN -3334,18089,LAKE,IN -3335,18089,LAKE,IN -3336,18089,LAKE,IN -3337,18089,LAKE,IN -3338,18089,LAKE,IN -3339,18089,LAKE,IN -3340,18089,LAKE,IN -3341,18089,LAKE,IN -3342,18089,LAKE,IN -3343,18089,LAKE,IN -3344,18089,LAKE,IN -3345,18091,LAPORTE,IN -3346,18091,LAPORTE,IN -3347,18091,LAPORTE,IN -3348,18091,LAPORTE,IN -3349,18091,LAPORTE,IN -3350,18091,LAPORTE,IN -3351,18091,LAPORTE,IN -3352,18091,LAPORTE,IN -3353,18091,LAPORTE,IN -3354,18091,LAPORTE,IN -3355,18091,LAPORTE,IN -3356,18091,LAPORTE,IN -3357,18091,LAPORTE,IN -3358,18091,LAPORTE,IN -3359,18091,LAPORTE,IN -3360,18091,LAPORTE,IN -3361,18091,LAPORTE,IN -3362,18091,LAPORTE,IN -3363,18091,LAPORTE,IN -3364,18091,LAPORTE,IN -3365,18091,LAPORTE,IN -3366,18091,LAPORTE,IN -3367,18091,LAPORTE,IN -3368,18091,LAPORTE,IN -3369,18091,LAPORTE,IN -3370,18091,LAPORTE,IN -3371,18091,LAPORTE,IN -3372,18091,LAPORTE,IN -3373,18091,LAPORTE,IN -3374,18091,LAPORTE,IN -3375,18091,LAPORTE,IN -3376,18091,LAPORTE,IN -3377,18091,LAPORTE,IN -3378,18091,LAPORTE,IN -3379,18091,LAPORTE,IN -3380,18091,LAPORTE,IN -3381,18091,LAPORTE,IN -3382,18091,LAPORTE,IN -3383,18091,LAPORTE,IN -3384,18091,LAPORTE,IN -3385,18091,LAPORTE,IN -3386,18091,LAPORTE,IN -3387,18091,LAPORTE,IN -3388,18091,LAPORTE,IN -3389,18091,LAPORTE,IN -3390,18091,LAPORTE,IN -3391,18091,LAPORTE,IN -3392,18091,LAPORTE,IN -3393,18091,LAPORTE,IN -3394,18091,LAPORTE,IN -3395,18091,LAPORTE,IN -3396,18091,LAPORTE,IN -3397,18091,LAPORTE,IN -3398,18091,LAPORTE,IN -3399,18091,LAPORTE,IN -3400,18091,LAPORTE,IN -3401,18127,PORTER,IN -3402,18127,PORTER,IN -3403,18127,PORTER,IN -3404,18127,PORTER,IN -3405,18127,PORTER,IN -3406,18127,PORTER,IN -3407,18127,PORTER,IN -3408,18127,PORTER,IN -3409,18127,PORTER,IN -3410,18127,PORTER,IN -3411,18127,PORTER,IN -3412,18127,PORTER,IN -3413,18127,PORTER,IN -3414,18127,PORTER,IN -3415,18127,PORTER,IN -3416,18127,PORTER,IN -3417,18127,PORTER,IN -3418,18127,PORTER,IN -3419,18127,PORTER,IN -3420,18127,PORTER,IN -3421,18127,PORTER,IN -3422,18127,PORTER,IN -3423,18127,PORTER,IN -3424,18127,PORTER,IN -3425,18127,PORTER,IN -3426,18127,PORTER,IN -3427,18127,PORTER,IN -3428,18127,PORTER,IN -3429,18127,PORTER,IN -3430,18127,PORTER,IN -3431,18127,PORTER,IN -3432,18127,PORTER,IN -3433,18127,PORTER,IN -3434,18127,PORTER,IN -3435,18127,PORTER,IN -3436,18127,PORTER,IN -3437,18127,PORTER,IN -3438,18127,PORTER,IN -3439,18127,PORTER,IN -3440,18127,PORTER,IN -3441,18127,PORTER,IN -3442,18127,PORTER,IN -3443,18127,PORTER,IN -3444,18127,PORTER,IN -3445,18127,PORTER,IN -3446,18127,PORTER,IN -3447,18127,PORTER,IN -3448,18127,PORTER,IN -3449,18127,PORTER,IN -3450,18127,PORTER,IN -3451,18127,PORTER,IN -3452,18127,PORTER,IN -3453,18127,PORTER,IN -3454,18127,PORTER,IN -3455,18127,PORTER,IN -3456,18127,PORTER,IN -3457,18127,PORTER,IN -3458,18127,PORTER,IN -3459,18127,PORTER,IN -3460,18127,PORTER,IN -3461,18127,PORTER,IN -3462,18127,PORTER,IN -3463,18127,PORTER,IN -3464,18127,PORTER,IN -3465,18127,PORTER,IN -3466,18127,PORTER,IN -3467,18127,PORTER,IN -3468,55059,KENOSHA,WI -3469,55059,KENOSHA,WI -3470,55059,KENOSHA,WI -3471,55059,KENOSHA,WI -3472,55059,KENOSHA,WI -3473,55059,KENOSHA,WI -3474,55059,KENOSHA,WI -3475,55059,KENOSHA,WI -3476,55059,KENOSHA,WI -3477,55059,KENOSHA,WI -3478,55059,KENOSHA,WI -3479,55059,KENOSHA,WI -3480,55059,KENOSHA,WI -3481,55059,KENOSHA,WI -3482,55059,KENOSHA,WI -3483,55059,KENOSHA,WI -3484,55059,KENOSHA,WI -3485,55059,KENOSHA,WI -3486,55059,KENOSHA,WI -3487,55059,KENOSHA,WI -3488,55059,KENOSHA,WI -3489,55059,KENOSHA,WI -3490,55059,KENOSHA,WI -3491,55059,KENOSHA,WI -3492,55059,KENOSHA,WI -3493,55059,KENOSHA,WI -3494,55059,KENOSHA,WI -3495,55059,KENOSHA,WI -3496,55059,KENOSHA,WI -3497,55059,KENOSHA,WI -3498,55059,KENOSHA,WI -3499,55059,KENOSHA,WI -3500,55059,KENOSHA,WI -3501,55059,KENOSHA,WI -3502,55059,KENOSHA,WI -3503,55059,KENOSHA,WI -3504,55059,KENOSHA,WI -3505,55059,KENOSHA,WI -3506,55059,KENOSHA,WI -3507,55059,KENOSHA,WI -3508,55059,KENOSHA,WI -3509,55059,KENOSHA,WI -3510,55059,KENOSHA,WI -3511,55059,KENOSHA,WI -3512,55059,KENOSHA,WI -3513,55101,RACINE,WI -3514,55101,RACINE,WI -3515,55101,RACINE,WI -3516,55101,RACINE,WI -3517,55101,RACINE,WI -3518,55101,RACINE,WI -3519,55101,RACINE,WI -3520,55101,RACINE,WI -3521,55101,RACINE,WI -3522,55101,RACINE,WI -3523,55101,RACINE,WI -3524,55101,RACINE,WI -3525,55101,RACINE,WI -3526,55101,RACINE,WI -3527,55101,RACINE,WI -3528,55101,RACINE,WI -3529,55101,RACINE,WI -3530,55101,RACINE,WI -3531,55101,RACINE,WI -3532,55101,RACINE,WI -3533,55101,RACINE,WI -3534,55101,RACINE,WI -3535,55101,RACINE,WI -3536,55101,RACINE,WI -3537,55101,RACINE,WI -3538,55101,RACINE,WI -3539,55101,RACINE,WI -3540,55101,RACINE,WI -3541,55101,RACINE,WI -3542,55101,RACINE,WI -3543,55101,RACINE,WI -3544,55101,RACINE,WI -3545,55101,RACINE,WI -3546,55101,RACINE,WI -3547,55101,RACINE,WI -3548,55101,RACINE,WI -3549,55101,RACINE,WI -3550,55101,RACINE,WI -3551,55101,RACINE,WI -3552,55101,RACINE,WI -3553,55101,RACINE,WI -3554,55101,RACINE,WI -3555,55101,RACINE,WI -3556,55101,RACINE,WI -3557,55101,RACINE,WI -3558,55101,RACINE,WI -3559,55101,RACINE,WI -3560,55101,RACINE,WI -3561,55101,RACINE,WI -3562,55101,RACINE,WI -3563,55101,RACINE,WI -3564,55101,RACINE,WI -3565,55101,RACINE,WI -3566,55101,RACINE,WI -3567,55101,RACINE,WI -3568,55101,RACINE,WI -3569,55127,WALWORTH,WI -3570,55127,WALWORTH,WI -3571,55127,WALWORTH,WI -3572,55127,WALWORTH,WI -3573,55127,WALWORTH,WI -3574,55127,WALWORTH,WI -3575,55127,WALWORTH,WI -3576,55127,WALWORTH,WI -3577,55127,WALWORTH,WI -3578,55127,WALWORTH,WI -3579,55127,WALWORTH,WI -3580,55127,WALWORTH,WI -3581,55127,WALWORTH,WI -3582,55127,WALWORTH,WI -3583,55127,WALWORTH,WI -3584,55127,WALWORTH,WI -3585,55127,WALWORTH,WI -3586,55127,WALWORTH,WI -3587,55127,WALWORTH,WI -3588,55127,WALWORTH,WI -3589,55127,WALWORTH,WI -3590,55127,WALWORTH,WI -3591,55127,WALWORTH,WI -3592,55127,WALWORTH,WI -3593,55127,WALWORTH,WI -3594,55127,WALWORTH,WI -3595,55127,WALWORTH,WI -3596,55127,WALWORTH,WI -3597,55127,WALWORTH,WI -3598,55127,WALWORTH,WI -3599,55127,WALWORTH,WI -3600,55127,WALWORTH,WI -3601,55127,WALWORTH,WI -3602,55127,WALWORTH,WI -3603,55127,WALWORTH,WI -3604,55127,WALWORTH,WI -3605,55127,WALWORTH,WI -3606,55127,WALWORTH,WI -3607,55127,WALWORTH,WI -3608,55127,WALWORTH,WI -3609,55127,WALWORTH,WI -3610,55127,WALWORTH,WI -3611,55127,WALWORTH,WI -3612,55127,WALWORTH,WI -3613,55127,WALWORTH,WI -3614,55127,WALWORTH,WI -3615,55127,WALWORTH,WI -3616,55127,WALWORTH,WI -3617,55127,WALWORTH,WI -3618,55127,WALWORTH,WI -3619,55127,WALWORTH,WI -3620,55127,WALWORTH,WI -3621,55127,WALWORTH,WI -3622,55127,WALWORTH,WI -3623,55127,WALWORTH,WI -3624,55127,WALWORTH,WI -3625,55127,WALWORTH,WI -3626,55127,WALWORTH,WI -3627,55127,WALWORTH,WI -3628,55127,WALWORTH,WI -3629,55127,WALWORTH,WI -3630,55127,WALWORTH,WI -3631,55127,WALWORTH,WI -3632,55127,WALWORTH,WI diff --git a/Database/post_macros/createMOVESinputfile.py b/Database/post_macros/createMOVESinputfile.py index 7ada85e..0fd79d1 100644 --- a/Database/post_macros/createMOVESinputfile.py +++ b/Database/post_macros/createMOVESinputfile.py @@ -589,9 +589,14 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): # Load in punchlink for specific scenario year linkdata = pd.read_csv(DB_DIR.joinpath('data', 'punchlink.csv')) - # Merge in zone-county crosswalk - zone_county_cw = pd.read_csv(DB_DIR.joinpath('data', 'zone17_county_crosswalk.csv')) - linkdata = pd.merge(linkdata, zone_county_cw, left_on="zone", right_on="zone17", how = "left").drop("zone17", axis=1) + + # Merge in zone-county crosswalk (GEOG_IN) + zone_county_cw = pd.read_csv(DB_DIR.joinpath("tg", "fortran", "GEOG_IN.txt"), header=None) + zone_county_cw.columns = ['subzone','county','county_name','state','puma','zone','chicago', + 'cbd','row_column','area','cmap'] + ## -> Crosswalk is at subzone level, need to aggregate to zone level + zone_county_cw = zone_county_cw.groupby(["zone", "county", "county_name", "state"]).first() + linkdata = pd.merge(linkdata, zone_county_cw, on="zone", how = "left") # Get clean link data links = clean_linkdata(linkdata) @@ -628,7 +633,6 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): else: im_regions = [("",None)] - # Define output folder out_folder = DB_DIR.joinpath('data', f'MOVES_{model}_scen{scenyear}') @@ -637,7 +641,7 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): if exportAs == "full_region": fallback_data = False else: - fallback_data_path = out_folder.joinpath(f'MOVES_{model}_scen{scenyear}.xlsx') + fallback_data_path = out_folder.joinpath(f'MOVES_{model}_scen{scenyear}_NEW2.xlsx') fallback_data = pd.read_excel(fallback_data_path, sheet_name = None) print(f"Outputting Results to {out_folder}") @@ -660,7 +664,7 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): hpms_annual_vmt = get_hpms_annual_vmt(hpms_daily_vmt, year) # Define filename and export all tabs to excel workbook - file_name = f'MOVES_{model}_scen{scenyear}{county_text}{imarea_text}.xlsx' + file_name = f'MOVES_{model}_scen{scenyear}{county_text}{imarea_text}_testing3.xlsx' out_path = out_folder.joinpath(file_name) out_xlsx = pd.ExcelWriter(out_path) From b57973a40628f7a600442b6920562287b35bcc5c Mon Sep 17 00:00:00 2001 From: Sarah Zebar Date: Wed, 19 Aug 2026 10:56:44 -0500 Subject: [PATCH 13/13] cleaning up output filenames --- Database/post_macros/createMOVESinputfile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Database/post_macros/createMOVESinputfile.py b/Database/post_macros/createMOVESinputfile.py index 0fd79d1..5920235 100644 --- a/Database/post_macros/createMOVESinputfile.py +++ b/Database/post_macros/createMOVESinputfile.py @@ -641,7 +641,7 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): if exportAs == "full_region": fallback_data = False else: - fallback_data_path = out_folder.joinpath(f'MOVES_{model}_scen{scenyear}_NEW2.xlsx') + fallback_data_path = out_folder.joinpath(f'MOVES_{model}_scen{scenyear}.xlsx') fallback_data = pd.read_excel(fallback_data_path, sheet_name = None) print(f"Outputting Results to {out_folder}") @@ -664,7 +664,7 @@ def get_hpms_annual_vmt(hpms_daily_vmt, year): hpms_annual_vmt = get_hpms_annual_vmt(hpms_daily_vmt, year) # Define filename and export all tabs to excel workbook - file_name = f'MOVES_{model}_scen{scenyear}{county_text}{imarea_text}_testing3.xlsx' + file_name = f'MOVES_{model}_scen{scenyear}{county_text}{imarea_text}.xlsx' out_path = out_folder.joinpath(file_name) out_xlsx = pd.ExcelWriter(out_path)