<s> import numpy as np <EOL> import pandas as pd <EOL> import logging <EOL> logger = logging . getLogger ( __name__ ) <EOL> class SqFtProFormaConfig ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . _reset_defaults ( ) <EOL> def _reset_defaults ( self ) : <EOL> self . parcel_sizes = [ <NUM_LIT> ] <EOL> self . fars = [ <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT:1.0> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <EOL> <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <EOL> <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> ] <EOL> self . uses = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> self . residential_uses = [ False , False , False , True ] <EOL> self . forms = { <EOL> '<STR_LIT>' : { <EOL> "<STR_LIT>" : <NUM_LIT:1.0> <EOL> } , <EOL> '<STR_LIT>' : { <EOL> "<STR_LIT>" : <NUM_LIT:1.0> <EOL> } , <EOL> '<STR_LIT>' : { <EOL> "<STR_LIT>" : <NUM_LIT:1.0> <EOL> } , <EOL> '<STR_LIT>' : { <EOL> "<STR_LIT>" : <NUM_LIT:1.0> <EOL> } , <EOL> '<STR_LIT>' : { <EOL> "<STR_LIT>" : <NUM_LIT> , <EOL> "<STR_LIT>" : <NUM_LIT> <EOL> } , <EOL> '<STR_LIT>' : { <EOL> "<STR_LIT>" : <NUM_LIT> , <EOL> "<STR_LIT>" : <NUM_LIT> <EOL> } <EOL> } <EOL> self . profit_factor = <NUM_LIT> <EOL> self . building_efficiency = <NUM_LIT> <EOL> self . parcel_coverage = <NUM_LIT> <EOL> self . cap_rate = <NUM_LIT> <EOL> self . parking_rates = { <EOL> "<STR_LIT>" : <NUM_LIT> , <EOL> "<STR_LIT>" : <NUM_LIT> , <EOL> "<STR_LIT>" : <NUM_LIT:1.0> , <EOL> "<STR_LIT>" : <NUM_LIT:1.0> <EOL> } <EOL> self . sqft_per_rate = <NUM_LIT> <EOL> self . parking_configs = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> self . costs = { <EOL> "<STR_LIT>" : [ <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> ] , <EOL> "<STR_LIT>" : [ <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> ] , <EOL> "<STR_LIT>" : [ <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> ] , <EOL> "<STR_LIT>" : [ <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT> ] <EOL> } <EOL> self . heights_for_costs = [ <NUM_LIT:15> , <NUM_LIT> , <NUM_LIT> , np . inf ] <EOL> self . parking_sqft_d = { <EOL> '<STR_LIT>' : <NUM_LIT> , <EOL> '<STR_LIT>' : <NUM_LIT> , <EOL> '<STR_LIT>' : <NUM_LIT> <EOL> } <EOL> self . parking_cost_d = { <EOL> '<STR_LIT>' : <NUM_LIT:30> , <EOL> '<STR_LIT>' : <NUM_LIT> , <EOL> '<STR_LIT>' : <NUM_LIT> <EOL> } <EOL> self . height_per_story = <NUM_LIT> <EOL> self . max_retail_height = <NUM_LIT> <EOL> self . max_industrial_height = <NUM_LIT> <EOL> def _convert_types ( self ) : <EOL> """<STR_LIT>""" <EOL> self . fars = np . array ( self . fars ) <EOL> self . parking_rates = np . array ( [ self . parking_rates [ use ] for use in self . uses ] ) <EOL> self . res_ratios = { } <EOL> assert len ( self . uses ) == len ( self . residential_uses ) <EOL> for k , v in self . forms . iteritems ( ) : <EOL> self . forms [ k ] = np . array ( [ self . forms [ k ] . get ( use , <NUM_LIT:0.0> ) for use in self . uses ] ) <EOL> self . forms [ k ] /= self . forms [ k ] . sum ( ) <EOL> self . res_ratios [ k ] = pd . Series ( self . forms [ k ] ) [ self . residential_uses ] . sum ( ) <EOL> self . costs = np . transpose ( np . array ( [ self . costs [ use ] for use in self . uses ] ) ) <EOL> @ property <EOL> def tiled_parcel_sizes ( self ) : <EOL> return np . reshape ( np . repeat ( self . parcel_sizes , self . fars . size ) , ( - <NUM_LIT:1> , <NUM_LIT:1> ) ) <EOL> def check_is_reasonable ( self ) : <EOL> fars = pd . Series ( self . fars ) <EOL> assert len ( fars [ fars > <NUM_LIT:20> ] ) == <NUM_LIT:0> <EOL> assert len ( fars [ fars <= <NUM_LIT:0> ] ) == <NUM_LIT:0> <EOL> for k , v in self . forms . iteritems ( ) : <EOL> assert isinstance ( v , dict ) <EOL> for k2 , v2 in self . forms [ k ] . iteritems ( ) : <EOL> assert isinstance ( k2 , str ) <EOL> assert isinstance ( v2 , float ) <EOL> for k2 , v2 in self . forms [ k ] . iteritems ( ) : <EOL> assert isinstance ( k2 , str ) <EOL> assert isinstance ( v2 , float ) <EOL> for k , v in self . parking_rates . iteritems ( ) : <EOL> assert isinstance ( k , str ) <EOL> assert k in self . uses <EOL> assert <NUM_LIT:0> <= v < <NUM_LIT:5> <EOL> for k , v in self . parking_sqft_d . iteritems ( ) : <EOL> assert isinstance ( k , str ) <EOL> assert k in self . parking_configs <EOL> assert <NUM_LIT:50> <= v <= <NUM_LIT:1000> <EOL> for k , v in self . parking_sqft_d . iteritems ( ) : <EOL> assert isinstance ( k , str ) <EOL> assert k in self . parking_cost_d <EOL> assert <NUM_LIT:10> <= v <= <NUM_LIT> <EOL> for v in self . heights_for_costs : <EOL> assert isinstance ( v , int ) or isinstance ( v , float ) <EOL> if np . isinf ( v ) : <EOL> continue <EOL> assert <NUM_LIT:0> <= v <= <NUM_LIT:1000> <EOL> for k , v in self . costs . iteritems ( ) : <EOL> assert isinstance ( k , str ) <EOL> assert k in self . uses <EOL> for i in v : <EOL> assert <NUM_LIT:10> < i < <NUM_LIT:1000> <EOL> class SqFtProForma ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , config = None ) : <EOL> if config is None : <EOL> config = SqFtProFormaConfig ( ) <EOL> config . check_is_reasonable ( ) <EOL> self . config = config <EOL> self . config . _convert_types ( ) <EOL> self . _generate_lookup ( ) <EOL> def _building_cost ( self , use_mix , stories ) : <EOL> """<STR_LIT>""" <EOL> c = self . config <EOL> heights = stories * c . height_per_story <EOL> costs = np . searchsorted ( c . heights_for_costs , heights ) <EOL> costs [ np . isnan ( heights ) ] = <NUM_LIT:0> <EOL> costs = np . dot ( np . squeeze ( c . costs [ costs . astype ( '<STR_LIT>' ) ] ) , use_mix ) <EOL> costs [ np . isnan ( stories ) . flatten ( ) ] = np . nan <EOL> return costs . flatten ( ) <EOL> def _generate_lookup ( self ) : <EOL> """<STR_LIT>""" <EOL> c = self . config <EOL> keys = c . forms . keys ( ) <EOL> keys . sort ( ) <EOL> df_d = { } <EOL> for name in keys : <EOL> uses_distrib = c . forms [ name ] <EOL> for parking_config in c . parking_configs : <EOL> df = pd . DataFrame ( index = c . fars ) <EOL> df [ '<STR_LIT>' ] = c . fars <EOL> df [ '<STR_LIT>' ] = c . tiled_parcel_sizes <EOL> building_bulk = np . reshape ( <EOL> c . parcel_sizes , ( - <NUM_LIT:1> , <NUM_LIT:1> ) ) * np . reshape ( c . fars , ( <NUM_LIT:1> , - <NUM_LIT:1> ) ) <EOL> building_bulk = np . reshape ( building_bulk , ( - <NUM_LIT:1> , <NUM_LIT:1> ) ) <EOL> if parking_config == '<STR_LIT>' : <EOL> building_bulk /= ( <NUM_LIT:1.0> + np . sum ( uses_distrib * c . parking_rates ) * <EOL> c . parking_sqft_d [ parking_config ] / <EOL> c . sqft_per_rate ) <EOL> df [ '<STR_LIT>' ] = building_bulk <EOL> parkingstalls = building_bulk * np . sum ( uses_distrib * c . parking_rates ) / c . sqft_per_rate <EOL> parking_cost = ( c . parking_cost_d [ parking_config ] * <EOL> parkingstalls * <EOL> c . parking_sqft_d [ parking_config ] ) <EOL> df [ '<STR_LIT>' ] = parkingstalls <EOL> if parking_config == '<STR_LIT>' : <EOL> df [ '<STR_LIT>' ] = parkingstalls * c . parking_sqft_d [ parking_config ] <EOL> stories = building_bulk / c . tiled_parcel_sizes <EOL> if parking_config == '<STR_LIT>' : <EOL> df [ '<STR_LIT>' ] = parkingstalls * c . parking_sqft_d [ parking_config ] <EOL> stories = ( ( building_bulk + parkingstalls * <EOL> c . parking_sqft_d [ parking_config ] ) / <EOL> c . tiled_parcel_sizes ) <EOL> if parking_config == '<STR_LIT>' : <EOL> stories = building_bulk / ( c . tiled_parcel_sizes - parkingstalls * <EOL> c . parking_sqft_d [ parking_config ] ) <EOL> df [ '<STR_LIT>' ] = <NUM_LIT:0> <EOL> stories [ stories < <NUM_LIT:0.0> ] = np . nan <EOL> stories [ stories > <NUM_LIT> ] = np . nan <EOL> df [ '<STR_LIT>' ] = df . building_sqft + df . park_sqft <EOL> df [ '<STR_LIT>' ] = df . park_sqft / df . total_built_sqft <EOL> stories /= c . parcel_coverage <EOL> df [ '<STR_LIT>' ] = np . ceil ( stories ) <EOL> df [ '<STR_LIT>' ] = df . stories * c . height_per_story <EOL> df [ '<STR_LIT>' ] = self . _building_cost ( uses_distrib , stories ) <EOL> df [ '<STR_LIT>' ] = df . build_cost_sqft * df . building_sqft <EOL> df [ '<STR_LIT>' ] = parking_cost <EOL> df [ '<STR_LIT>' ] = df . build_cost + df . park_cost <EOL> df [ '<STR_LIT>' ] = ( df . cost / df . total_built_sqft ) * c . profit_factor <EOL> if name == '<STR_LIT>' : <EOL> df [ '<STR_LIT>' ] [ c . fars > c . max_retail_height ] = np . nan <EOL> if name == '<STR_LIT>' : <EOL> df [ '<STR_LIT>' ] [ c . fars > c . max_industrial_height ] = np . nan <EOL> df_d [ ( name , parking_config ) ] = df <EOL> self . dev_d = df_d <EOL> def get_debug_info ( self , form , parking_config ) : <EOL> """<STR_LIT>""" <EOL> return self . dev_d [ ( form , parking_config ) ] <EOL> def get_ave_cost_sqft ( self , form , parking_config ) : <EOL> """<STR_LIT>""" <EOL> return self . dev_d [ ( form , parking_config ) ] . ave_cost_sqft <EOL> def lookup ( self , form , df , only_built = True , pass_through = None ) : <EOL> """<STR_LIT>""" <EOL> df = pd . concat ( self . _lookup_parking_cfg ( form , parking_config , df , only_built , <EOL> pass_through ) <EOL> for parking_config in self . config . parking_configs ) <EOL> if len ( df ) == <NUM_LIT:0> : <EOL> return pd . DataFrame ( ) <EOL> max_profit_ind = df . pivot ( <EOL> columns = "<STR_LIT>" , <EOL> values = "<STR_LIT>" ) . idxmax ( axis = <NUM_LIT:1> ) . to_frame ( "<STR_LIT>" ) <EOL> df . set_index ( [ "<STR_LIT>" ] , append = True , inplace = True ) <EOL> max_profit_ind . set_index ( [ "<STR_LIT>" ] , append = True , inplace = True ) <EOL> return df . loc [ max_profit_ind . index ] . reset_index ( <NUM_LIT:1> ) <EOL> def _lookup_parking_cfg ( self , form , parking_config , df , only_built = True , <EOL> pass_through = None ) : <EOL> dev_info = self . dev_d [ ( form , parking_config ) ] <EOL> cost_sqft_col = np . reshape ( dev_info . ave_cost_sqft . values , ( - <NUM_LIT:1> , <NUM_LIT:1> ) ) <EOL> cost_sqft_index_col = np . reshape ( dev_info . index . values , ( - <NUM_LIT:1> , <NUM_LIT:1> ) ) <EOL> parking_sqft_ratio = np . reshape ( dev_info . parking_sqft_ratio . values , ( - <NUM_LIT:1> , <NUM_LIT:1> ) ) <EOL> heights = np . reshape ( dev_info . height . values , ( - <NUM_LIT:1> , <NUM_LIT:1> ) ) <EOL> df = df . copy ( ) <EOL> c = self . config <EOL> df [ '<STR_LIT>' ] = np . dot ( df [ c . uses ] , c . forms [ form ] ) <EOL> df [ '<STR_LIT>' ] = df . max_height / c . height_per_story * c . parcel_coverage <EOL> if '<STR_LIT>' in df . columns : <EOL> assert '<STR_LIT>' in df . columns <EOL> df [ '<STR_LIT>' ] = df . max_dua * ( df . parcel_size / <NUM_LIT> ) * df . ave_unit_size / self . config . building_efficiency / df . parcel_size <EOL> df [ '<STR_LIT>' ] = df [ [ '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' ] ] . min ( axis = <NUM_LIT:1> ) <EOL> else : <EOL> df [ '<STR_LIT>' ] = df [ [ '<STR_LIT>' , '<STR_LIT>' ] ] . min ( axis = <NUM_LIT:1> ) <EOL> if only_built : <EOL> df = df . query ( '<STR_LIT>' ) <EOL> fars = np . repeat ( cost_sqft_index_col , len ( df . index ) , axis = <NUM_LIT:1> ) <EOL> fars [ fars > df . min_max_fars . values + <NUM_LIT> ] = np . nan <EOL> heights = np . repeat ( heights , len ( df . index ) , axis = <NUM_LIT:1> ) <EOL> fars [ heights > df . max_height . values + <NUM_LIT> ] = np . nan <EOL> building_bulks = fars * df . parcel_size . values <EOL> building_costs = building_bulks * cost_sqft_col <EOL> total_costs = building_costs + df . land_cost . values <EOL> building_revenue = building_bulks * ( <NUM_LIT:1> - parking_sqft_ratio ) * c . building_efficiency * df . weighted_rent . values / c . cap_rate <EOL> profit = building_revenue - total_costs <EOL> profit = profit . astype ( '<STR_LIT:float>' ) <EOL> profit [ np . isnan ( profit ) ] = - np . inf <EOL> maxprofitind = np . argmax ( profit , axis = <NUM_LIT:0> ) <EOL> def twod_get ( indexes , arr ) : <EOL> return arr [ indexes , np . arange ( indexes . size ) ] . astype ( '<STR_LIT:float>' ) <EOL> outdf = pd . DataFrame ( { <EOL> '<STR_LIT>' : twod_get ( maxprofitind , building_bulks ) , <EOL> '<STR_LIT>' : twod_get ( maxprofitind , building_costs ) , <EOL> '<STR_LIT>' : parking_sqft_ratio [ maxprofitind ] . flatten ( ) , <EOL> '<STR_LIT>' : twod_get ( maxprofitind , heights ) / c . height_per_story , <EOL> '<STR_LIT>' : twod_get ( maxprofitind , total_costs ) , <EOL> '<STR_LIT>' : twod_get ( maxprofitind , building_revenue ) , <EOL> '<STR_LIT>' : twod_get ( maxprofitind , fars ) , <EOL> '<STR_LIT>' : twod_get ( maxprofitind , profit ) , <EOL> '<STR_LIT>' : parking_config <EOL> } , index = df . index ) <EOL> if pass_through : <EOL> outdf [ pass_through ] = df [ pass_through ] <EOL> resratio = c . res_ratios [ form ] <EOL> nonresratio = <NUM_LIT:1.0> - resratio <EOL> outdf [ "<STR_LIT>" ] = outdf . building_sqft * c . building_efficiency * resratio <EOL> outdf [ "<STR_LIT>" ] = outdf . building_sqft * c . building_efficiency * nonresratio <EOL> if only_built : <EOL> outdf = outdf . query ( '<STR_LIT>' ) . copy ( ) <EOL> else : <EOL> outdf = outdf . loc [ outdf . max_profit != - np . inf ] . copy ( ) <EOL> return outdf <EOL> def _debug_output ( self ) : <EOL> """<STR_LIT>""" <EOL> import matplotlib <EOL> matplotlib . use ( '<STR_LIT>' ) <EOL> import matplotlib . pyplot as plt <EOL> c = self . config <EOL> df_d = self . dev_d <EOL> keys = df_d . keys ( ) <EOL> keys . sort ( ) <EOL> for key in keys : <EOL> logger . debug ( "<STR_LIT:\n>" + str ( key ) + "<STR_LIT:\n>" ) <EOL> logger . debug ( df_d [ key ] ) <EOL> for form in self . config . forms : <EOL> logger . debug ( "<STR_LIT:\n>" + str ( key ) + "<STR_LIT:\n>" ) <EOL> logger . debug ( self . get_ave_cost_sqft ( form , "<STR_LIT>" ) ) <EOL> keys = c . forms . keys ( ) <EOL> keys . sort ( ) <EOL> cnt = <NUM_LIT:1> <EOL> share = None <EOL> fig = plt . figure ( figsize = ( <NUM_LIT:12> , <NUM_LIT:3> * len ( keys ) ) ) <EOL> fig . suptitle ( '<STR_LIT>' , fontsize = <NUM_LIT> ) <EOL> for name in keys : <EOL> sumdf = None <EOL> for parking_config in c . parking_configs : <EOL> df = df_d [ ( name , parking_config ) ] <EOL> if sumdf is None : <EOL> sumdf = pd . DataFrame ( df [ '<STR_LIT>' ] ) <EOL> sumdf [ parking_config ] = df [ '<STR_LIT>' ] <EOL> far = sumdf [ '<STR_LIT>' ] <EOL> del sumdf [ '<STR_LIT>' ] <EOL> if share is None : <EOL> share = plt . subplot ( len ( keys ) / <NUM_LIT:2> , <NUM_LIT:2> , cnt ) <EOL> else : <EOL> plt . subplot ( len ( keys ) / <NUM_LIT:2> , <NUM_LIT:2> , cnt , sharex = share , sharey = share ) <EOL> handles = plt . plot ( far , sumdf ) <EOL> plt . ylabel ( '<STR_LIT>' ) <EOL> plt . xlabel ( '<STR_LIT>' ) <EOL> plt . title ( '<STR_LIT>' % name ) <EOL> plt . legend ( <EOL> handles , c . parking_configs , loc = '<STR_LIT>' , <EOL> title = '<STR_LIT>' ) <EOL> cnt += <NUM_LIT:1> <EOL> plt . savefig ( '<STR_LIT>' , bbox_inches = <NUM_LIT:0> ) </s>
