def forecastWork(modelDir, ind): ''' Run the model in its directory.''' (cellCapacity, dischargeRate, chargeRate, cellQuantity, cellCost) = \ [float(ind[x]) for x in ('cellCapacity', 'dischargeRate', 'chargeRate', 'cellQuantity', 'cellCost')] demandCharge = float(ind['demandCharge']) retailCost = float(ind['retailCost']) battEff = float(ind.get("batteryEfficiency")) / 100.0 dodFactor = float(ind.get('dodFactor')) / 100.0 projYears = int(ind.get('projYears')) batteryCycleLife = int(ind.get('batteryCycleLife')) battCapacity = cellQuantity * float(ind['cellCapacity']) * dodFactor o = {} try: with open(pJoin(modelDir, 'hist.csv'), 'w') as f: f.write(ind['histCurve'].replace('\r', '')) df = pd.read_csv(pJoin(modelDir, 'hist.csv'), parse_dates=['dates']) df['month'] = df['dates'].dt.month df['dayOfYear'] = df['dates'].dt.dayofyear assert df.shape[0] >= 26280 # must be longer than 3 years assert df.shape[1] == 5 except: raise Exception("CSV file is incorrect format.") confidence = float(ind['confidence']) / 100 # ---------------------- MAKE PREDICTIONS ------------------------------- # # train model on previous data all_X = fc.makeUsefulDf(df) all_y = df['load'] predictions = fc.neural_net_predictions(all_X, all_y) dailyLoadPredictions = [ predictions[i:i + 24] for i in range(0, len(predictions), 24) ] weather = df['tempc'][-8760:] dailyWeatherPredictions = [ weather[i:i + 24] for i in range(0, len(weather), 24) ] month = df['month'][-8760:] dispatched = [False] * 365 # decide to implement VBAT every day for a year VB_power, VB_energy = [], [] for i, (load24, temp24, m) in enumerate( zip(dailyLoadPredictions, dailyWeatherPredictions, month)): peak = max(load24) if fc.shouldDispatchPS(peak, m, df, confidence): dispatched[i] = True vbp, vbe = fc.pulp24hrBattery(load24, dischargeRate * cellQuantity, cellCapacity * cellQuantity, battEff) VB_power.extend(vbp) VB_energy.extend(vbe) else: VB_power.extend([0] * 24) VB_energy.extend([0] * 24) # -------------------- MODEL ACCURACY ANALYSIS -------------------------- # o['predictedLoad'] = predictions o['trainAccuracy'] = 0 #round(model.score(X_train, y_train) * 100, 2) o['testAccuracy'] = 0 #round(model.score(X_test, y_test) * 100, 2) # PRECISION AND RECALL maxDays = [] for month in range(1, 13): test = df[df['month'] == month] maxDays.append(test.loc[test['load'].idxmax()]['dayOfYear']) shouldHaveDispatched = [False] * 365 for day in maxDays: shouldHaveDispatched[day] = True truePositive = len([ b for b in [i and j for (i, j) in zip(dispatched, shouldHaveDispatched)] if b ]) falsePositive = len([ b for b in [i and (not j) for (i, j) in zip(dispatched, shouldHaveDispatched)] if b ]) falseNegative = len([ b for b in [(not i) and j for (i, j) in zip(dispatched, shouldHaveDispatched)] if b ]) o['precision'] = round( truePositive / float(truePositive + falsePositive) * 100, 2) o['recall'] = round( truePositive / float(truePositive + falseNegative) * 100, 2) o['number_of_dispatches'] = len([i for i in dispatched if i]) o['MAE'] = round( sum([ abs(l - m) / m * 100 for l, m in zip(predictions, list(all_y[-8760:])) ]) / 8760., 2) # ---------------------- FINANCIAL ANALYSIS ----------------------------- # # Calculate monthHours year = df[-8760:].copy() year.reset_index(inplace=True) year['hour'] = list(year.index) start = list(year.groupby('month').first()['hour']) finish = list(year.groupby('month').last()['hour']) monthHours = [(s, f + 1) for (s, f) in zip(start, finish)] demand = list(all_y[-8760:]) peakDemand = [max(demand[s:f]) for s, f in monthHours] demandAdj = [d + p for d, p in zip(demand, VB_power)] peakDemandAdj = [max(demandAdj[s:f]) for s, f in monthHours] discharges = [f if f < 0 else 0 for f in VB_power] # Monthly Cost Comparison Table o['monthlyDemand'] = peakDemand o['monthlyDemandRed'] = peakDemandAdj o['ps'] = [p - s for p, s in zip(peakDemand, peakDemandAdj)] o['benefitMonthly'] = [x * demandCharge for x in o['ps']] # Demand Before and After Storage Graph o['demand'] = demand o['demandAfterBattery'] = demandAdj o['batteryDischargekW'] = VB_power o['batteryDischargekWMax'] = max(VB_power) batteryCycleLife = float(ind['batteryCycleLife']) # Battery State of Charge Graph # Turn dc's SoC into a percentage, with dodFactor considered. o['batterySoc'] = SoC = [100 - (e / battCapacity * 100) for e in VB_energy] # Estimate number of cyles the battery went through. Sums the percent of SoC. cycleEquivalents = sum([ SoC[i] - SoC[i + 1] for i, x in enumerate(SoC[:-1]) if SoC[i + 1] < SoC[i] ]) / 100.0 o['cycleEquivalents'] = cycleEquivalents o['batteryLife'] = batteryCycleLife / cycleEquivalents # Cash Flow Graph # inserting battery efficiency only into the cashflow calculation # cashFlowCurve is $ in from peak shaving minus the cost to recharge the battery every day of the year cashFlowCurve = [sum(o['ps']) * demandCharge for year in range(projYears)] cashFlowCurve.insert(0, -1 * cellCost * cellQuantity) # insert initial investment # simplePayback is also affected by the cost to recharge the battery every day of the year o['SPP'] = (cellCost * cellQuantity) / (sum(o['ps']) * demandCharge) o['netCashflow'] = cashFlowCurve o['cumulativeCashflow'] = [ sum(cashFlowCurve[:i + 1]) for i, d in enumerate(cashFlowCurve) ] o['NPV'] = npv(float(ind['discountRate']), cashFlowCurve) battCostPerCycle = cellQuantity * cellCost / batteryCycleLife lcoeTotCost = cycleEquivalents * retailCost + battCostPerCycle * cycleEquivalents o['LCOE'] = lcoeTotCost / (cycleEquivalents * battCapacity) # Other o['startDate'] = '2011-01-01' # dc[0]['datetime'].isoformat() o['stderr'] = '' # Seemingly unimportant. Ask permission to delete. o['stdout'] = 'Success' o['months'] = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ] return o
def workForecast(modelDir, ind): ''' Run the model in its directory.''' o = {} # Grab data from CSV, try: with open(pJoin(modelDir, 'hist.csv'), 'w') as f: f.write(ind['histCurve'].replace('\r', '')) df = pd.read_csv(pJoin(modelDir, 'hist.csv'), parse_dates=['dates']) df['month'] = df['dates'].dt.month df['dayOfYear'] = df['dates'].dt.dayofyear assert df.shape[0] >= 26280 # must be longer than 3 years assert df.shape[1] == 5 except: raise Exception("CSV file is incorrect format.") # train model on previous data all_X = fc.makeUsefulDf(df) all_y = df['load'] X_train, y_train = all_X[:-8760], all_y[:-8760] clf = linear_model.SGDRegressor(max_iter=10000, tol=1e-4) clf.fit(X_train, y_train) # ---------------------- MAKE PREDICTIONS ------------------------------- # X_test, y_test = all_X[-8760:], all_y[-8760:] predictions = clf.predict(X_test) dailyLoadPredictions = [ predictions[i:i + 24] for i in range(0, len(predictions), 24) ] P_lower, P_upper, E_UL = vbat24hr(ind, df['tempc'][-8760:]) dailyPl = [P_lower[i:i + 24] for i in range(0, len(P_lower), 24)] dailyPu = [P_upper[i:i + 24] for i in range(0, len(P_upper), 24)] dailyEu = [E_UL[i:i + 24] for i in range(0, len(E_UL), 24)] vbp, vbe = [], [] dispatched_d = [False] * 365 # Decide what days to dispatch zipped = zip(dailyLoadPredictions, df['month'][-8760:], dailyPl, dailyPu, dailyEu) for i, (load, m, pl, pu, eu) in enumerate(zipped): peak = max(load) if fc.shouldDispatchPS(peak, m, df, float(ind['confidence']) / 100): dispatched_d[i] = True p, e = fc.pulp24hrVbat(ind, load, pl, pu, eu) vbp.extend(p) vbe.extend(e) else: vbp.extend([0] * 24) vbe.extend([0] * 24) ### TESTING FOR ACCURACY ### assert len(dailyPl) == 365 assert all([len(i) == 24 for i in dailyPl]) VB_power, VB_energy = vbp, vbe # -------------------- MODEL ACCURACY ANALYSIS -------------------------- # o['predictedLoad'] = list(clf.predict(X_test)) o['trainAccuracy'] = round(clf.score(X_train, y_train) * 100, 2) o['testAccuracy'] = round(clf.score(X_test, y_test) * 100, 2) # PRECISION AND RECALL maxDays = [] for month in range(1, 13): test = df[df['month'] == month] maxDays.append(test.loc[test['load'].idxmax()]['dayOfYear']) shouldHaveDispatched = [False] * 365 for day in maxDays: shouldHaveDispatched[day] = True truePositive = len([ b for b in [i and j for (i, j) in zip(dispatched_d, shouldHaveDispatched)] if b ]) falsePositive = len([ b for b in [i and (not j) for (i, j) in zip(dispatched_d, shouldHaveDispatched)] if b ]) falseNegative = len([ b for b in [(not i) and j for (i, j) in zip(dispatched_d, shouldHaveDispatched)] if b ]) o['confidence'] = ind['confidence'] o['precision'] = round( truePositive / float(truePositive + falsePositive) * 100, 2) o['recall'] = round( truePositive / float(truePositive + falseNegative) * 100, 2) o['number_of_dispatches'] = len([i for i in dispatched_d if i]) o['MAE'] = round( sum([abs(l - m) / m * 100 for l, m in zip(predictions, list(y_test))]) / 8760., 2) # ---------------------- FINANCIAL ANALYSIS ----------------------------- # o['VBpower'], o['VBenergy'] = list(VB_power), list(VB_energy) # Calculate monthHours year = df[-8760:].copy() year.reset_index(inplace=True) year['hour'] = list(year.index) start = list(year.groupby('month').first()['hour']) finish = list(year.groupby('month').last()['hour']) monthHours = [(s, f + 1) for (s, f) in zip(start, finish)] demand = list(y_test) peakDemand = [max(demand[s:f]) for s, f in monthHours] energyMonthly = [sum(demand[s:f]) for s, f in monthHours] demandAdj = [d + p for d, p in zip(demand, o['VBpower'])] peakAdjustedDemand = [max(demandAdj[s:f]) for s, f in monthHours] energyAdjustedMonthly = [sum(demandAdj[s:f]) for s, f in monthHours] o['demand'] = demand o['peakDemand'] = peakDemand o['energyMonthly'] = energyMonthly o['demandAdjusted'] = demandAdj o['peakAdjustedDemand'] = peakAdjustedDemand o['energyAdjustedMonthly'] = energyAdjustedMonthly cellCost = float(ind['unitDeviceCost']) * float(ind['number_devices']) eCost = float(ind['electricityCost']) dCharge = float(ind['demandChargeCost']) o['VBdispatch'] = [dal - d for dal, d in zip(demandAdj, demand)] o['energyCost'] = [em * eCost for em in energyMonthly] o['energyCostAdjusted'] = [eam * eCost for eam in energyAdjustedMonthly] o['demandCharge'] = [peak * dCharge for peak in peakDemand] o['demandChargeAdjusted'] = [ pad * dCharge for pad in o['peakAdjustedDemand'] ] o['totalCost'] = [ ec + dcm for ec, dcm in zip(o['energyCost'], o['demandCharge']) ] o['totalCostAdjusted'] = [ eca + dca for eca, dca in zip(o['energyCostAdjusted'], o['demandChargeAdjusted']) ] o['savings'] = [ tot - tota for tot, tota in zip(o['totalCost'], o['totalCostAdjusted']) ] annualEarnings = sum(o['savings']) - float(ind['unitUpkeepCost']) * float( ind['number_devices']) cashFlowList = [annualEarnings] * int(ind['projectionLength']) cashFlowList.insert(0, -1 * cellCost) o['NPV'] = np.npv(float(ind['discountRate']) / 100, cashFlowList) o['SPP'] = cellCost / annualEarnings o['netCashflow'] = cashFlowList o['cumulativeCashflow'] = [ sum(cashFlowList[:i + 1]) for i, d in enumerate(cashFlowList) ] o['stdout'] = 'Success' return o
def work(modelDir, ind): #print(ind) ''' Run the model in its directory.''' # drop inverter efficiency # drop DoD (cellCapacity, dischargeRate, chargeRate, cellQuantity, cellCost) = \ [float(ind[x]) for x in ('cellCapacity', 'dischargeRate', 'chargeRate', 'cellQuantity', 'cellCost')] battEff = float(ind.get("batteryEfficiency")) / 100.0 dodFactor = float(ind.get('dodFactor')) / 100.0 projYears = int(ind.get('projYears')) batteryCycleLife = int(ind.get('batteryCycleLife')) o = {} try: with open(pJoin(modelDir, 'hist.csv'), 'w') as f: f.write(ind['historicalData'].replace('\r', '')) df = pd.read_csv(pJoin(modelDir, 'hist.csv'), parse_dates=['dates']) df['month'] = df['dates'].dt.month df['dayOfYear'] = df['dates'].dt.dayofyear assert df.shape[0] >= 26280 # must be longer than 3 years assert df.shape[1] == 5 except: raise Exception("CSV file is incorrect format.") # retrieve goal goal = ind['goal'] threshold = float(ind['transformerThreshold']) * 1000 confidence = float(ind['confidence']) / 100 # train model on previous data all_X = fc.makeUsefulDf(df) all_y = df['load'] X_train, y_train = all_X[:-8760], all_y[:-8760] clf = linear_model.SGDRegressor(max_iter=10000, tol=1e-4) clf.fit(X_train, y_train) # ---------------------- MAKE PREDICTIONS ------------------------------- # X_test, y_test = all_X[-8760:], all_y[-8760:] # Collect data necessary for dispatch calculations predictions = clf.predict(X_test) dailyLoadPredictions = [ predictions[i:i + 24] for i in range(0, len(predictions), 24) ] weather = df['tempc'][-8760:] dailyWeatherPredictions = [ weather[i:i + 24] for i in range(0, len(weather), 24) ] month = df['month'][-8760:] dispatched = [False] * 365 # decide to implement VBAT every day for a year VB_power, VB_energy = [], [] for i, (load24, temp24, m) in enumerate( zip(dailyLoadPredictions, dailyWeatherPredictions, month)): peak = max(load24) if fc.shouldDispatchPS(peak, m, df, confidence): dispatched[i] = True vbp, vbe = fc.pulp24hrBattery(load24, dischargeRate * cellQuantity, cellCapacity * cellQuantity, battEff) VB_power.extend(vbp) VB_energy.extend(vbe) else: VB_power.extend([0] * 24) VB_energy.extend([0] * 24) # -------------------- MODEL ACCURACY ANALYSIS -------------------------- # o['predictedLoad'] = list(clf.predict(X_test)) o['trainAccuracy'] = round(clf.score(X_train, y_train) * 100, 2) o['testAccuracy'] = round(clf.score(X_test, y_test) * 100, 2) # PRECISION AND RECALL maxDays = [] for month in range(1, 13): test = df[df['month'] == month] maxDays.append(test.loc[test['load'].idxmax()]['dayOfYear']) shouldHaveDispatched = [False] * 365 for day in maxDays: shouldHaveDispatched[day] = True truePositive = len([ b for b in [i and j for (i, j) in zip(dispatched, shouldHaveDispatched)] if b ]) falsePositive = len([ b for b in [i and (not j) for (i, j) in zip(dispatched, shouldHaveDispatched)] if b ]) falseNegative = len([ b for b in [(not i) and j for (i, j) in zip(dispatched, shouldHaveDispatched)] if b ]) o['precision'] = round( truePositive / float(truePositive + falsePositive) * 100, 2) o['recall'] = round( truePositive / float(truePositive + falseNegative) * 100, 2) o['number_of_dispatches'] = len([i for i in dispatched if i]) o['MAE'] = round( sum([abs(l - m) / m * 100 for l, m in zip(predictions, list(y_test))]) / 8760., 2) # ---------------------- FINANCIAL ANALYSIS ----------------------------- # o['VBpower'], o['VBenergy'] = list(VB_power), list(VB_energy) # Calculate monthHours year = df[-8760:].copy() year.reset_index(inplace=True) year['hour'] = list(year.index) start = list(year.groupby('month').first()['hour']) finish = list(year.groupby('month').last()['hour']) monthHours = [(s, f + 1) for (s, f) in zip(start, finish)] demand = list(y_test) peakDemand = [max(demand[s:f]) for s, f in monthHours] energyMonthly = [sum(demand[s:f]) for s, f in monthHours] demandAdj = [d + p for d, p in zip(demand, o['VBpower'])] peakAdjustedDemand = [max(demandAdj[s:f]) for s, f in monthHours] energyAdjustedMonthly = [sum(demandAdj[s:f]) for s, f in monthHours] o['demand'] = demand o['peakDemand'] = peakDemand o['energyMonthly'] = energyMonthly o['demandAdjusted'] = demandAdj o['peakAdjustedDemand'] = peakAdjustedDemand o['energyAdjustedMonthly'] = energyAdjustedMonthly initInvestment = cellCost * cellQuantity eCost = float(ind['electricityCost']) dCharge = float(ind['demandChargeCost']) o['VBdispatch'] = [dal - d for dal, d in zip(demandAdj, demand)] o['energyCost'] = [em * eCost for em in energyMonthly] o['energyCostAdjusted'] = [eam * eCost for eam in energyAdjustedMonthly] o['demandCharge'] = [peak * dCharge for peak in peakDemand] o['demandChargeAdjusted'] = [ pad * dCharge for pad in o['peakAdjustedDemand'] ] o['totalCost'] = [ ec + dcm for ec, dcm in zip(o['energyCost'], o['demandCharge']) ] o['totalCostAdjusted'] = [ eca + dca for eca, dca in zip(o['energyCostAdjusted'], o['demandChargeAdjusted']) ] o['savings'] = [ tot - tota for tot, tota in zip(o['totalCost'], o['totalCostAdjusted']) ] annualEarnings = sum(o['savings']) # - something! cashFlowList = [annualEarnings] * int(ind['projectionLength']) cashFlowList.insert(0, -1 * initInvestment) o['NPV'] = np.npv(float(ind['discountRate']) / 100, cashFlowList) o['SPP'] = initInvestment / annualEarnings o['netCashflow'] = cashFlowList o['cumulativeCashflow'] = [ sum(cashFlowList[:i + 1]) for i, d in enumerate(cashFlowList) ] o['dataCheck'] = 'Threshold exceeded' if any( [threshold > i for i in demandAdj]) and goal == 'deferral' else '' o['transformerThreshold'] = threshold if goal == 'deferral' else None o['stdout'] = 'Success' return o