def work(modelDir, inputDict): """ Run the model in its directory.""" outData = {} rawData = [] actual = [] # write input file to modelDir sans carriage returns with open(pJoin(modelDir, "demandTemp.csv"), "w") as demandTempFile: demandTempFile.write(inputDict["demandTemp"].replace("\r", "")) try: with open(pJoin(modelDir, 'hist.csv'), 'w') as f: f.write(inputDict['nn'].replace('\r', '')) df = pd.read_csv(pJoin(modelDir, 'hist.csv')) assert df.shape[0] >= 26280 # must be longer than 3 years if 'dates' not in df.columns: df['dates'] = df.apply(lambda x: dt(int(x['year']), int(x[ 'month']), int(x['day']), int(x['hour'])), axis=1) except: raise Exception("Neural Net CSV file is incorrect format.") # neural net time all_X = loadForecast.makeUsefulDf(df) all_y = df["load"] nn_pred, nn_accuracy = loadForecast.neural_net_predictions(all_X, all_y) outData["actual_nn"] = df['load'][-8760:].tolist() # read it in as a list of lists try: with open(pJoin(modelDir, "demandTemp.csv")) as inFile: df = pd.read_csv(inFile, header=None) df.columns = ["load", "tempc"] df["dates"] = pd.date_range(start=inputDict["simStartDate"], freq="H", periods=df.shape[0]) print df.shape[0] except ZeroDivisionError: errorMessage = "CSV file is incorrect format. Please see valid format definition at <a target='_blank' href = 'https://github.com/dpinney/omf/wiki/Models-~-storagePeakShave#demand-file-csv-format'>\nOMF Wiki storagePeakShave - Demand File CSV Format</a>" raise Exception(errorMessage) rawData = df[["load", "tempc"]].fillna(0).values.tolist() del df """ # None -> 0, float-> string for i in range(len(rawData)): rawData[i] = [a if a else 0 for a in rawData[i]] rawData = list(np.float_(rawData)) """ # populate actual list for x in range(len(rawData)): actual.append(float(rawData[x][0])) (forecasted, MAPE) = loadForecast.rollingDylanForecast(rawData, float(inputDict["upBound"]), float(inputDict["lowBound"])) (exp, exp_MAPE) = loadForecast.exponentiallySmoothedForecast( rawData, float(inputDict["alpha"]), float(inputDict["beta"])) # parse json params for nextDayPeakKatrina try: params = json.loads(inputDict.get("katSpec", "{}")) except ValueError: params = {} pred_demand = loadForecast.nextDayPeakKatrinaForecast( rawData, inputDict["simStartDate"], modelDir, params) pred_demand = np.transpose(np.array(pred_demand)).tolist() # zucc it up prophet_partitions = int(inputDict.get("prophet", 0)) if prophet_partitions > 1: prophet, prophet_low, prophet_high = loadForecast.prophetForecast( rawData, inputDict["simStartDate"], modelDir, inputDict["prophet"]) # write our outData outData["startDate"] = inputDict["simStartDate"] outData["actual"] = actual outData["forecasted"] = forecasted outData["doubleExp"] = exp outData["neuralNet"] = nn_pred outData["MAPE"] = "%0.2f%%" % (MAPE * 100) outData["MAPE_exp"] = "%0.2f%%" % (exp_MAPE * 100) outData["MAPE_nn"] = "%0.2f%%" % nn_accuracy["test"] outData["peakDemand"] = pred_demand if prophet_partitions > 1: outData["prophet"] = prophet outData["prophetLow"] = prophet_low outData["prophetHigh"] = prophet_high return outData
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 forecastWork(modelDir, ind): import tensorflow as tf ''' 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')) assert df.shape[0] >= 26280 # must be longer than 3 years if df.shape[1] == 6: df['dates'] = df.apply(lambda x: dt(int(x['year']), int(x[ 'month']), int(x['day']), int(x['hour'])), axis=1) else: df = pd.read_csv(pJoin(modelDir, 'hist.csv'), parse_dates=['dates']) df['month'] = df.dates.dt.month df['dayOfYear'] = df['dates'].dt.dayofyear except: raise Exception("CSV file is incorrect format.") # ---------------------- MAKE PREDICTIONS ------------------------------- # # train model on previous data all_X = fc.makeUsefulDf(df) all_y = df['load'] if ind['newModel'] == 'True': model = None else: with open(pJoin(modelDir, 'neural_net.h5'), 'wb') as f: f.write(ind['model'].decode('base64')) model = tf.keras.models.load_model(pJoin(modelDir, 'neural_net.h5')) # model = tf.keras.models.load_model(ind['model']) predictions, accuracy = fc.neural_net_predictions( all_X, all_y, epochs=int(ind['epochs']), model=model, save_file=pJoin(modelDir, 'neural_net_model.h5')) 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) ] # decide to implement VBAT every day for a year VB_power, VB_energy = [], [] for i, (load24, temp24) in enumerate( zip(dailyLoadPredictions, dailyWeatherPredictions)): vbp, vbe = pulp24hrBattery(load24, dischargeRate * cellQuantity, cellCapacity * cellQuantity, battEff) VB_power.extend(vbp) VB_energy.extend(vbe) # -------------------- MODEL ACCURACY ANALYSIS -------------------------- # o['predictedLoad'] = predictions o['trainAccuracy'] = 100 - round(accuracy['train'], 1) o['testAccuracy'] = 100 - round(accuracy['test'], 1) # ---------------------- 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(df['load'][-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] # 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']) o['batterySoc'] = SoC = [100 - (e / battCapacity * 100) for e in VB_energy] 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 + 10) # Cash Flow Graph cashFlowCurve = [sum(o['ps']) * demandCharge for year in range(projYears)] cashFlowCurve.insert(0, -1 * cellCost * cellQuantity) # insert initial investment 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 + 10) model # Other o['startDate'] = '2011-01-01' o['stderr'] = '' o['stdout'] = 'Success' return o