def test_cost_func(): # test cost_func: cost # Input # stand info area = 66.3709 elevation = 141.034205761 slope = 21.74728843 stand_wkt = u'POLYGON ((-13809080.891332019 5330620.9753014417,-13808943.708174769 5331066.8205624959,-13808393.373740762 5330897.4868904939,-13808530.556898013 5330451.6416294342,-13809080.891332019 5330620.9753014417))' # harvest info RemovalsCT = 200.0 TreeVolCT = 5.0 RemovalsSLT = 100.0 TreeVolSLT = 70.0 RemovalsLLT = 20.0 TreeVolLLT = 200.0 HdwdFractionCT = 0.15 HdwdFractionSLT = 0.0 HdwdFractionLLT = 0.0 PartialCut = 0 # routing info landing_coords = (-124.04858, 43.12776) haulDist = 8.674960531 haulTime = 32.92 coord_mill = (-124.161246, 43.106512) # Expected Output cost = {'slope': 21.75, 'skid_distance': 999.69, 'mill_coordinates': (-124.161246, 43.106512), 'elevation': 141.03, 'total_harvest_cost': 314598.0, 'haul_distance_ow': 8.94, 'total_cost': 350309.0, 'haul_cost_min': 0.604, 'total_area': 66.37, 'harvest_cost_ft3': 0.395, 'haul_distance_extension': 0.269, 'total_haul_trips': 898.0, 'haul_time_ow': 32.92, 'total_haul_cost': 35711.0, 'harvest_system': 'GroundBasedMechWT', 'landing_coordinates': (-124.04706351844823, 43.125146208049415), 'total_volume': 796450.8} assert(main_model.cost_func( # stand info area, elevation, slope, stand_wkt, # harvest info RemovalsCT, TreeVolCT, RemovalsSLT, TreeVolSLT, RemovalsLLT, TreeVolLLT, HdwdFractionCT, HdwdFractionSLT, HdwdFractionLLT, PartialCut, # routing info landing_coords, haulDist, haulTime, coord_mill )) == cost
def main(): scenario = Scenario.objects.get(id=122) sql = """SELECT ss.id AS sstand_id, a.cond, a.rx, a.year, a.offset, ss.acres AS acres, a.total_stand_carbon AS total_carbon, a.agl AS agl_carbon, a.removed_merch_bdft / 1000.0 AS harvested_timber, -- convert to mbf a.after_merch_bdft / 1000.0 AS standing_timber, -- convert to mbf ST_AsText(ss.geometry_final) AS stand_wkt, a.LG_CF AS LG_CF, a.LG_HW AS LG_HW, a.LG_TPA AS LG_TPA, a.SM_CF AS SM_CF, a.SM_HW AS SM_HW, a.SM_TPA AS SM_TPA, a.CH_CF AS CH_CF, a.CH_HW AS CH_HW, a.CH_TPA AS CH_TPA, stand.elevation AS elev, stand.slope AS slope, a.CUT_TYPE AS CUT_TYPE FROM trees_fvsaggregate a JOIN trees_scenariostand ss ON a.cond = ss.cond_id AND a.rx = ss.rx_internal_num AND a.offset = ss.offset JOIN trees_stand stand ON ss.stand_id = stand.id -- WHERE a.site = 2 -- TODO if we introduce multiple site classes, we need to fix WHERE var = '%s' -- get from current property AND ss.scenario_id = %d -- get from current scenario ORDER BY a.year, ss.id;""" % (scenario.input_property.variant.code, scenario.id) cursor = connection.cursor() cursor.execute(sql) data = dictfetchall(cursor) # Mill information mill_shp = 'Data/mills.shp' # Landing Coordinates center = scenario.input_property.geometry_final.point_on_surface centroid_coords = center.transform(4326, clone=True).tuple landing_coords = landing.landing(centroid_coords=centroid_coords) haulDist, haulTime, coord_mill = r.routing( landing_coords, mill_shp=mill_shp ) annual_total_cost = defaultdict(float) annual_haul_cost = defaultdict(float) annual_heli_harvest_cost = defaultdict(float) annual_ground_harvest_cost = defaultdict(float) annual_cable_harvest_cost = defaultdict(float) used_records = 0 skip_noharvest = 0 skip_error = 0 year = None years = [] for row in data: ### GIS Data stand_wkt = row['stand_wkt'] area = row['acres'] if year != int(row['year']): year = int(row['year']) print "Calculating cost per stand in year", year years.append(year) annual_total_cost[year] += 0 annual_haul_cost[year] += 0 annual_heli_harvest_cost[year] += 0 annual_ground_harvest_cost[year] += 0 annual_cable_harvest_cost[year] += 0 # NOTE: elevation and slope come directly from stand # if we use spatial contrainsts to chop scenariostands, # will need to recalc zonal stats elevation = row['elev'] slope = row['slope'] ### Tree Data ### # Cut type code indicating type of harvest implemented. # 0 = no harvest, 1 = pre-commercial thin, # 2 = commercial thin, 3 = regeneration harvest try: cut_type = int(row['cut_type']) except: # no harvest so don't attempt to calculate cut_type = 0 # PartialCut(clear cut = 0, partial cut = 1) if cut_type == 3: PartialCut = 0 elif cut_type in [1, 2]: PartialCut = 1 else: # no harvest so don't attempt to calculate skip_noharvest += 1 continue # Hardwood Fraction # Chip Trees RemovalsCT = row['ch_tpa'] TreeVolCT = row['ch_cf'] HdwdFractionCT = row['ch_hw'] # Small Log Trees RemovalsSLT = row['sm_tpa'] TreeVolSLT = row['sm_cf'] HdwdFractionSLT = row['sm_hw'] # Large Log Trees RemovalsLLT = row['lg_tpa'] TreeVolLLT = row['lg_cf'] HdwdFractionLLT = row['lg_hw'] cost_args = ( # stand info area, elevation, slope, stand_wkt, # harvest info RemovalsCT, TreeVolCT, RemovalsSLT, TreeVolSLT, RemovalsLLT, TreeVolLLT, HdwdFractionCT, HdwdFractionSLT, HdwdFractionLLT, PartialCut, # routing info landing_coords, haulDist, haulTime, coord_mill ) try: result = m.cost_func(*cost_args) annual_haul_cost[year] += result['total_haul_cost'] annual_total_cost[year] += result['total_cost'] system = result['harvest_system'] if system.startswith("Helicopter"): annual_heli_harvest_cost[year] += result['total_harvest_cost'] elif system.startswith("Ground"): annual_ground_harvest_cost[year] += result['total_harvest_cost'] elif system.startswith("Cable"): annual_cable_harvest_cost[year] += result['total_harvest_cost'] else: # TODO annual_cable_harvest_cost[year] += result['total_harvest_cost'] #raise ValueError used_records += 1 except (ZeroDivisionError, ValueError): skip_error += 1 # import traceback # print cost_args # print traceback.format_exc() def ordered_costs(x): sorted_x = sorted(x.iteritems(), key=operator.itemgetter(0)) return [-1 * z[1] for z in sorted_x] print "--------" print " var heli =", json.dumps(ordered_costs(annual_heli_harvest_cost)), ";" print " var cable =", json.dumps(ordered_costs(annual_cable_harvest_cost)), ";" print " var ground =", json.dumps(ordered_costs(annual_ground_harvest_cost)), ";" print " var haul =", json.dumps(ordered_costs(annual_haul_cost)), ";" print " var years =", json.dumps(sorted(annual_haul_cost.keys())), ";" # RANDOMLY determine a revenue w/in % of total cost; HACK rev = [-1 * x * (1.0 + (0.35 - (random.random() * 0.5))) for x in ordered_costs(annual_total_cost)] #rev = [-1 * x for x in ordered_costs(annual_total_cost)] print " var revenue =", json.dumps(rev), ";" # determine profit profit = [revenue + cost for revenue, cost in zip(rev, ordered_costs(annual_total_cost))] print " var profit =", json.dumps(profit), ";" print "--------" print "year, heliHarvestCost, cableHarvestCost, groundHarvestCost, transportationCost" for year in sorted(dict(annual_haul_cost).keys()): print ", ".join(str(x) for x in [ year, annual_heli_harvest_cost[year], annual_cable_harvest_cost[year], annual_ground_harvest_cost[year], annual_haul_cost[year] ] ) print "--------" print "used records:", used_records print "skipped (no harvest):", skip_noharvest print "skipped (errors):", skip_error
def main(): scenario = Scenario.objects.get(id=122) sql = """SELECT ss.id AS sstand_id, a.cond, a.rx, a.year, a.offset, ss.acres AS acres, a.total_stand_carbon AS total_carbon, a.agl AS agl_carbon, a.removed_merch_bdft / 1000.0 AS harvested_timber, -- convert to mbf a.after_merch_bdft / 1000.0 AS standing_timber, -- convert to mbf ST_AsText(ss.geometry_final) AS stand_wkt, a.LG_CF AS LG_CF, a.LG_HW AS LG_HW, a.LG_TPA AS LG_TPA, a.SM_CF AS SM_CF, a.SM_HW AS SM_HW, a.SM_TPA AS SM_TPA, a.CH_CF AS CH_CF, a.CH_HW AS CH_HW, a.CH_TPA AS CH_TPA, stand.elevation AS elev, stand.slope AS slope, a.CUT_TYPE AS CUT_TYPE FROM trees_fvsaggregate a JOIN trees_scenariostand ss ON a.cond = ss.cond_id AND a.rx = ss.rx_internal_num AND a.offset = ss.offset JOIN trees_stand stand ON ss.stand_id = stand.id -- WHERE a.site = 2 -- TODO if we introduce multiple site classes, we need to fix WHERE var = '%s' -- get from current property AND ss.scenario_id = %d -- get from current scenario ORDER BY a.year, ss.id;""" % (scenario.input_property.variant.code, scenario.id) cursor = connection.cursor() cursor.execute(sql) data = dictfetchall(cursor) # Mill information mill_shp = 'Data/mills.shp' # Landing Coordinates center = scenario.input_property.geometry_final.point_on_surface centroid_coords = center.transform(4326, clone=True).tuple landing_coords = landing.landing(centroid_coords=centroid_coords) haulDist, haulTime, coord_mill = r.routing(landing_coords, mill_shp=mill_shp) annual_total_cost = defaultdict(float) annual_haul_cost = defaultdict(float) annual_heli_harvest_cost = defaultdict(float) annual_ground_harvest_cost = defaultdict(float) annual_cable_harvest_cost = defaultdict(float) used_records = 0 skip_noharvest = 0 skip_error = 0 year = None years = [] for row in data: ### GIS Data stand_wkt = row['stand_wkt'] area = row['acres'] if year != int(row['year']): year = int(row['year']) print "Calculating cost per stand in year", year years.append(year) annual_total_cost[year] += 0 annual_haul_cost[year] += 0 annual_heli_harvest_cost[year] += 0 annual_ground_harvest_cost[year] += 0 annual_cable_harvest_cost[year] += 0 # NOTE: elevation and slope come directly from stand # if we use spatial contrainsts to chop scenariostands, # will need to recalc zonal stats elevation = row['elev'] slope = row['slope'] ### Tree Data ### # Cut type code indicating type of harvest implemented. # 0 = no harvest, 1 = pre-commercial thin, # 2 = commercial thin, 3 = regeneration harvest try: cut_type = int(row['cut_type']) except: # no harvest so don't attempt to calculate cut_type = 0 # PartialCut(clear cut = 0, partial cut = 1) if cut_type == 3: PartialCut = 0 elif cut_type in [1, 2]: PartialCut = 1 else: # no harvest so don't attempt to calculate skip_noharvest += 1 continue # Hardwood Fraction # Chip Trees RemovalsCT = row['ch_tpa'] TreeVolCT = row['ch_cf'] HdwdFractionCT = row['ch_hw'] # Small Log Trees RemovalsSLT = row['sm_tpa'] TreeVolSLT = row['sm_cf'] HdwdFractionSLT = row['sm_hw'] # Large Log Trees RemovalsLLT = row['lg_tpa'] TreeVolLLT = row['lg_cf'] HdwdFractionLLT = row['lg_hw'] cost_args = ( # stand info area, elevation, slope, stand_wkt, # harvest info RemovalsCT, TreeVolCT, RemovalsSLT, TreeVolSLT, RemovalsLLT, TreeVolLLT, HdwdFractionCT, HdwdFractionSLT, HdwdFractionLLT, PartialCut, # routing info landing_coords, haulDist, haulTime, coord_mill) try: result = m.cost_func(*cost_args) annual_haul_cost[year] += result['total_haul_cost'] annual_total_cost[year] += result['total_cost'] system = result['harvest_system'] if system.startswith("Helicopter"): annual_heli_harvest_cost[year] += result['total_harvest_cost'] elif system.startswith("Ground"): annual_ground_harvest_cost[year] += result[ 'total_harvest_cost'] elif system.startswith("Cable"): annual_cable_harvest_cost[year] += result['total_harvest_cost'] else: # TODO annual_cable_harvest_cost[year] += result['total_harvest_cost'] #raise ValueError used_records += 1 except (ZeroDivisionError, ValueError): skip_error += 1 # import traceback # print cost_args # print traceback.format_exc() def ordered_costs(x): sorted_x = sorted(x.iteritems(), key=operator.itemgetter(0)) return [-1 * z[1] for z in sorted_x] print "--------" print " var heli =", json.dumps( ordered_costs(annual_heli_harvest_cost)), ";" print " var cable =", json.dumps( ordered_costs(annual_cable_harvest_cost)), ";" print " var ground =", json.dumps( ordered_costs(annual_ground_harvest_cost)), ";" print " var haul =", json.dumps(ordered_costs(annual_haul_cost)), ";" print " var years =", json.dumps(sorted(annual_haul_cost.keys())), ";" # RANDOMLY determine a revenue w/in % of total cost; HACK rev = [ -1 * x * (1.0 + (0.35 - (random.random() * 0.5))) for x in ordered_costs(annual_total_cost) ] #rev = [-1 * x for x in ordered_costs(annual_total_cost)] print " var revenue =", json.dumps(rev), ";" # determine profit profit = [ revenue + cost for revenue, cost in zip(rev, ordered_costs(annual_total_cost)) ] print " var profit =", json.dumps(profit), ";" print "--------" print "year, heliHarvestCost, cableHarvestCost, groundHarvestCost, transportationCost" for year in sorted(dict(annual_haul_cost).keys()): print ", ".join( str(x) for x in [ year, annual_heli_harvest_cost[year], annual_cable_harvest_cost[year], annual_ground_harvest_cost[year], annual_haul_cost[year] ]) print "--------" print "used records:", used_records print "skipped (no harvest):", skip_noharvest print "skipped (errors):", skip_error
def test_cost_func(): # test cost_func: cost # Input # stand info area = 66.3709 elevation = 141.034205761 slope = 21.74728843 stand_wkt = u'POLYGON ((-13809080.891332019 5330620.9753014417,-13808943.708174769 5331066.8205624959,-13808393.373740762 5330897.4868904939,-13808530.556898013 5330451.6416294342,-13809080.891332019 5330620.9753014417))' # harvest info RemovalsCT = 200.0 TreeVolCT = 5.0 RemovalsSLT = 100.0 TreeVolSLT = 70.0 RemovalsLLT = 20.0 TreeVolLLT = 200.0 HdwdFractionCT = 0.15 HdwdFractionSLT = 0.0 HdwdFractionLLT = 0.0 PartialCut = 0 # routing info landing_coords = (-124.04858, 43.12776) haulDist = 8.674960531 haulTime = 32.92 coord_mill = (-124.161246, 43.106512) # Expected Output cost = { 'slope': 21.75, 'skid_distance': 999.69, 'mill_coordinates': (-124.161246, 43.106512), 'elevation': 141.03, 'total_harvest_cost': 314598.0, 'haul_distance_ow': 8.94, 'total_cost': 350309.0, 'haul_cost_min': 0.604, 'total_area': 66.37, 'harvest_cost_ft3': 0.395, 'haul_distance_extension': 0.269, 'total_haul_trips': 898.0, 'haul_time_ow': 32.92, 'total_haul_cost': 35711.0, 'harvest_system': 'GroundBasedMechWT', 'landing_coordinates': (-124.04706351844823, 43.125146208049415), 'total_volume': 796450.8 } assert (main_model.cost_func( # stand info area, elevation, slope, stand_wkt, # harvest info RemovalsCT, TreeVolCT, RemovalsSLT, TreeVolSLT, RemovalsLLT, TreeVolLLT, HdwdFractionCT, HdwdFractionSLT, HdwdFractionLLT, PartialCut, # routing info landing_coords, haulDist, haulTime, coord_mill)) == cost
TreeVolLLT = 100.00 cost = m.cost_func( # stand info area, elevation, slope, stand_wkt, # harvest info RemovalsCT, TreeVolCT, RemovalsSLT, TreeVolSLT, RemovalsLLT, TreeVolLLT, HdwdFractionCT, HdwdFractionSLT, HdwdFractionLLT, PartialCut, # road construction info lengthNewRoad, totaltravelCostNewRoad, standCount, # routing info coords_landing_stand, coords_landing_road, haulDist, haulTime, coord_mill, ) pprint(cost)
mill_shp=mill_shp ) cost = m.cost_func( # stand info area, elevation, slope, stand_wkt, # harvest info RemovalsCT, TreeVolCT, RemovalsSLT, TreeVolSLT, RemovalsLLT, TreeVolLLT, HdwdFractionCT, HdwdFractionSLT, HdwdFractionLLT, PartialCut, # routing info landing_coords, haulDist, haulTime, coord_mill, # options True, 0.5 ) pprint(cost)
haulDist, haulTime, coord_mill = r.routing(landing_coords, mill_shp=mill_shp) cost = m.cost_func( # stand info area, elevation, slope, stand_wkt, # harvest info RemovalsCT, TreeVolCT, RemovalsSLT, TreeVolSLT, RemovalsLLT, TreeVolLLT, HdwdFractionCT, HdwdFractionSLT, HdwdFractionLLT, PartialCut, # routing info landing_coords, haulDist, haulTime, coord_mill, # options True, 0.5) pprint(cost)
for field in fields: val = row[field] try: val = float(val) except ValueError: if "|" in val: # randomly sample from uniform distribution low, high = [float(x) for x in val.split("|")] val = random.uniform(low, high) args.append(val) if row['PartialCut'] == 1: haulprop = 0.5 else: haulprop = 1.0 val = row['skid_distance'] try: skid_distance = float(val) except ValueError: if "|" in val: # randomly sample from uniform distribution low, high = [float(x) for x in val.split("|")] skid_distance = random.uniform(low, high) #print args results = main_model.cost_func(*args, Helicopter=False, HaulProportion=haulprop, skid_distance=skid_distance) print ",".join(str(x) for x in [row['name'], row['actual_cost'], results['total_cost']]) print "\n"
import traceback import glob import shutil #from IPython.core import ultratb #sys.excepthook = ultratb.FormattedTB(mode='Verbose', color_scheme='Linux', call_pdb=1) good = bad = 0 for txt in glob.glob("*.txt"): moveit = False with open(txt, 'r') as fh: lines = fh.readlines() args = eval(lines[6]) try: print main_model.cost_func(*args) good += 1 #moveit = True except: bad += 1 print "-----" print txt print print traceback.format_exc() if moveit: shutil.move(txt, "good/" + txt) print "##### GOOD", good print "##### BAD", bad