diff --git a/omf/models/hostingCapacity.py b/omf/models/hostingCapacity.py
index ebf5d4f82..16f033365 100644
--- a/omf/models/hostingCapacity.py
+++ b/omf/models/hostingCapacity.py
@@ -1,5 +1,4 @@
-''' Calculate solar photovoltaic system output using PVWatts. '''
-
+''' Calculate hosting capacity using traditional and/or AMI-based methods. '''
import base64
import shutil
from os.path import join as pJoin
@@ -14,155 +13,133 @@
import omf
from omf.models import __neoMetaModel__
from omf.models.__neoMetaModel__ import *
-from omf.models import derInterconnection
+from omf.solvers import opendss
# Model metadata:
-tooltip = "The hostingCapacity model calculates the kW hosting capacity available at each meter in the provided AMI data."
+tooltip = "Calculate hosting capacity using traditional and/or AMI-based methods."
modelName, template = __neoMetaModel__.metadata(__file__)
hidden = False
def work(modelDir, inputDict):
- outData = {}
- import mohca_cl
-
- with open(pJoin(modelDir,inputDict['inputDataFileName']),'w', newline='') as pv_stream:
- pv_stream.write(inputDict['inputDataFileContent'])
-
- inputPath = pJoin(modelDir, inputDict['inputDataFileName'])
- outputPath = pJoin(modelDir, 'mohcaOutput.csv')
-
- mohcaOutput = []
- if inputDict[ "mohcaAlgorithm" ] == "sandia1":
- mohcaOutput = mohca_cl.sandia1( inputPath, outputPath )
- elif inputDict[ "mohcaAlgorithm" ] == "sandia2":
- mohcaOutput = mohca_cl.sandia2( inputPath, outputPath )
- else:
- errorMessage = "Algorithm name error"
- raise Exception(errorMessage)
-
- mohcaResults = mohcaOutput[0].rename(columns={'kW_hostable': 'voltage_cap_kW'})
-
- mohcaHistogramFigure = px.histogram( mohcaResults, x='voltage_cap_kW', template="simple_white", color_discrete_sequence=["MediumPurple"] )
- mohcaHistogramFigure.update_layout(bargap=0.5)
-
- barChartDF = mohcaResults
- barChartDF['thermal_cap'] = [1]
- barChartDF['max_cap_kW'] = np.minimum( barChartDF['voltage_cap_kW'], barChartDF['thermal_cap'])
-
- mohcaBarChartFigure = px.bar(barChartDF, x='busname', y=['voltage_cap_kW', 'thermal_cap', 'max_cap_kW'], barmode='group', color_discrete_sequence=["green", "lightblue", "MediumPurple"], template="simple_white" )
- # mohcaBarChartFigure.update_layout()
-
- # Line graph of the data
- # timeSeriesFigure = px.line( mohcaResults.sort_values( by="kW_hostable", ascending=False, ignore_index=True ), x='busname', y='kW_hostable', markers=True, color_discrete_sequence=['purple', "blue", "green"])
- # timeSeriesFigure.update_yaxes(rangemode="tozero") # This line sets the base of the y axis to be 0.
-
- # traditional hosting capacity
- # if they uploaded an omd circuit file
- circuitFileStatus = inputDict.get('optionalCircuitFile', 0)
- print('STATUS!', circuitFileStatus, inputDict.get('optionalCircuitFile', 0))
- if ( circuitFileStatus == 'on' ):
- feederName = [x for x in os.listdir(modelDir) if x.endswith('.omd')][0]
- inputDict['feederName1'] = feederName
- omd = json.load(open(pJoin(modelDir, feederName)))
- tree = omd.get('tree',{})
- #for k, v in omd['tree'].items():
-
- # once we take the omd file and convert it to a tree, we can loop through the objects to find all the 'bus' objects, that can be our second input
- # then there are option inputs for the step and kw for the user to put in? idk
- # print( os.path.abspath(feederName) ) why is this in the omf directory and not the modelDir?
- traditionalHCResults = omf.solvers.opendss.hosting_capacity_verbose(pJoin(modelDir, feederName), modelDir, ['701', '730', '703', '724'], int( inputDict["traditionalHCSteps"] ), int( inputDict["traditionalHCkW"] ))
- tradHCDF = traditionalHCResults[0]
- print( tradHCDF )
-
- omf.geo.map_omd(pJoin(modelDir, feederName), modelDir, open_browser=False )
- # outData['traditionalHCMap'] = pJoin( modelDir, 'geoJson_offline.html')
- outData['traditionalHCMap'] = open( pJoin( modelDir, "geoJson_offline.html"), 'r' ).read()
-
- traditionalHCFigure = make_subplots(specs=[[{"secondary_y": True }]])
- traditionalHCFigure.add_trace(
- go.Scatter( x = tradHCDF.index, y = tradHCDF["kw_add"], name= "kw_add"),
- secondary_y=False
- )
- traditionalHCFigure.add_trace(
- go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_pu1"], name= "v_max_pu1"),
- secondary_y=True
- )
- traditionalHCFigure.add_trace(
- go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_pu2"], name= "v_max_pu2"),
- secondary_y=True
- )
- traditionalHCFigure.add_trace(
- go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_pu3"], name= "v_max_pu3"),
- secondary_y=True
- )
- traditionalHCFigure.add_trace(
- go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_all_pu"], name= "v_max_all_pu"),
- secondary_y=True
- )
- traditionalHCFigure.update_yaxes( title_text="Voltage ( PU )", secondary_y = False)
- traditionalHCFigure.update_yaxes( title_text="Total Additional Generation Added ( kW ) ", secondary_y = True)
- outData['traditionalGraphData'] = json.dumps( traditionalHCFigure, cls=py.utils.PlotlyJSONEncoder )
- outData['traditionalHCTableHeadings'] = traditionalHCResults[0].columns.values.tolist()
- outData['traditionalHCTableValues'] = ( list( traditionalHCResults[0].itertuples(index=False, name=None)))
-
- # Stdout/stderr.
- outData['stdout'] = "Success"
- outData['stderr'] = ""
- outData['mohcaHistogramFigure'] = json.dumps( mohcaHistogramFigure, cls=py.utils.PlotlyJSONEncoder )
- outData['mohcaBarChartFigure'] = json.dumps( mohcaBarChartFigure, cls=py.utils.PlotlyJSONEncoder )
- outData['mohcaHCTableHeadings'] = mohcaResults.columns.values.tolist()
- outData['mohcaHCTableValues'] = ( list(mohcaResults.sort_values( by="voltage_cap_kW", ascending=False, ignore_index=True ).itertuples(index=False, name=None)) ) #NOTE: kW_hostable
-
- # Stdout/stderr.
- outData['stdout'] = "Success"
- outData['stderr'] = ""
- return outData
+ outData = {}
+ import mohca_cl
+ with open(pJoin(modelDir,inputDict['inputDataFileName']),'w', newline='') as pv_stream:
+ pv_stream.write(inputDict['inputDataFileContent'])
+ inputPath = pJoin(modelDir, inputDict['inputDataFileName'])
+ outputPath = pJoin(modelDir, 'mohcaOutput.csv')
+ mohcaOutput = []
+ if inputDict[ "mohcaAlgorithm" ] == "sandia1":
+ mohcaOutput = mohca_cl.sandia1( inputPath, outputPath )
+ elif inputDict[ "mohcaAlgorithm" ] == "sandia2":
+ mohcaOutput = mohca_cl.sandia2( inputPath, outputPath )
+ else:
+ errorMessage = "Algorithm name error"
+ raise Exception(errorMessage)
+ mohcaResults = mohcaOutput[0].rename(columns={'kW_hostable': 'voltage_cap_kW'})
+ mohcaHistogramFigure = px.histogram( mohcaResults, x='voltage_cap_kW', template="simple_white", color_discrete_sequence=["MediumPurple"] )
+ mohcaHistogramFigure.update_layout(bargap=0.5)
+ barChartDF = mohcaResults
+ barChartDF['thermal_cap'] = [1]
+ barChartDF['max_cap_kW'] = np.minimum( barChartDF['voltage_cap_kW'], barChartDF['thermal_cap'])
+ mohcaBarChartFigure = px.bar(barChartDF, x='busname', y=['voltage_cap_kW', 'thermal_cap', 'max_cap_kW'], barmode='group', color_discrete_sequence=["green", "lightblue", "MediumPurple"], template="simple_white" )
+ # mohcaBarChartFigure.update_layout()
+ # Line graph of the data
+ # timeSeriesFigure = px.line( mohcaResults.sort_values( by="kW_hostable", ascending=False, ignore_index=True ), x='busname', y='kW_hostable', markers=True, color_discrete_sequence=['purple', "blue", "green"])
+ # timeSeriesFigure.update_yaxes(rangemode="tozero") # This line sets the base of the y axis to be 0.
+ # traditional hosting capacity
+ # if they uploaded an omd circuit file
+ circuitFileStatus = inputDict.get('optionalCircuitFile', 0)
+ print('STATUS!', circuitFileStatus, inputDict.get('optionalCircuitFile', 0))
+ if ( circuitFileStatus == 'on' ):
+ feederName = [x for x in os.listdir(modelDir) if x.endswith('.omd')][0]
+ inputDict['feederName1'] = feederName
+ tree = opendss.dssConvert.omdToTree(pJoin(modelDir, feederName))
+ opendss.dssConvert.treeToDss(tree, pJoin(modelDir, 'circuit.dss'))
+ traditionalHCResults = opendss.hosting_capacity_all(pJoin(modelDir, 'circuit.dss'), int(inputDict["traditionalHCSteps"]), int(inputDict["traditionalHCkW"]))
+ tradHCDF = pd.DataFrame(traditionalHCResults)
+ print('TRADREZ', traditionalHCResults)
+ omf.geo.map_omd(pJoin(modelDir, feederName), modelDir, open_browser=False )
+ outData['traditionalHCMap'] = open( pJoin( modelDir, "geoJson_offline.html"), 'r' ).read()
+ traditionalHCFigure = make_subplots(specs=[[{"secondary_y": True }]])
+ traditionalHCFigure.add_trace(
+ go.Scatter( x = tradHCDF.index, y = tradHCDF["max_kw"], name= "max_kw"),
+ secondary_y=False
+ )
+ # traditionalHCFigure.add_trace(
+ # go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_pu1"], name= "v_max_pu1"),
+ # secondary_y=True
+ # )
+ # traditionalHCFigure.add_trace(
+ # go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_pu2"], name= "v_max_pu2"),
+ # secondary_y=True
+ # )
+ # traditionalHCFigure.add_trace(
+ # go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_pu3"], name= "v_max_pu3"),
+ # secondary_y=True
+ # )
+ # traditionalHCFigure.add_trace(
+ # go.Scatter( x = tradHCDF.index, y = tradHCDF["v_max_all_pu"], name= "v_max_all_pu"),
+ # secondary_y=True
+ # )
+ # traditionalHCFigure.update_yaxes( title_text="Voltage ( PU )", secondary_y = False)
+ traditionalHCFigure.update_yaxes( title_text="Total Additional Generation Added ( kW ) ", secondary_y = True)
+ outData['traditionalGraphData'] = json.dumps( traditionalHCFigure, cls=py.utils.PlotlyJSONEncoder )
+ # outData['traditionalHCTableHeadings'] = traditionalHCResults[0].columns.values.tolist()
+ # outData['traditionalHCTableValues'] = ( list( traditionalHCResults[0].itertuples(index=False, name=None)))
+ # Stdout/stderr.
+ outData['stdout'] = "Success"
+ outData['stderr'] = ""
+ outData['mohcaHistogramFigure'] = json.dumps( mohcaHistogramFigure, cls=py.utils.PlotlyJSONEncoder )
+ outData['mohcaBarChartFigure'] = json.dumps( mohcaBarChartFigure, cls=py.utils.PlotlyJSONEncoder )
+ outData['mohcaHCTableHeadings'] = mohcaResults.columns.values.tolist()
+ outData['mohcaHCTableValues'] = ( list(mohcaResults.sort_values( by="voltage_cap_kW", ascending=False, ignore_index=True ).itertuples(index=False, name=None)) ) #NOTE: kW_hostable
+ return outData
def runtimeEstimate(modelDir):
- ''' Estimated runtime of model in minutes. '''
- return 0.5
+ ''' Estimated runtime of model in minutes. '''
+ return 0.5
def new(modelDir):
- ''' Create a new instance of this model. Returns true on success, false on failure. '''
- test_file_name = 'sandia_loc1_test_data.csv'
- test_file_path = pJoin(omf.omfDir,'static','testFiles', test_file_name)
- test_circuit_name = "ieee37_LBL"
- test_file_contents = open(test_file_path).read()
- defaultInputs = {
- "mohcaAlgorithm": 'sandia1',
- "feederName1": test_circuit_name,
- "inputDataFileName": test_file_name,
- "inputDataFileContent": test_file_contents,
- "modelType": modelName,
- "traditionalHCSteps": 10,
- "optionalCircuitFile": 'on',
- "traditionalHCkW": 1
- }
- creationCode = __neoMetaModel__.new(modelDir, defaultInputs)
- try:
- shutil.copyfile(pJoin(__neoMetaModel__._omfDir, "static", "hostingcapacityfiles", defaultInputs["feederName1"]+'.omd'), pJoin(modelDir, defaultInputs["feederName1"]+'.omd'))
- except:
- return False
- return creationCode
+ ''' Create a new instance of this model. Returns true on success, false on failure. '''
+ meter_file_name = 'sandia_loc1_test_data.csv'
+ meter_file_path = pJoin(omf.omfDir,'static','testFiles', meter_file_name)
+ meter_file_contents = open(meter_file_path).read()
+ defaultInputs = {
+ "modelType": modelName,
+ "mohcaAlgorithm": 'sandia1',
+ "inputDataFileName": meter_file_name,
+ "inputDataFileContent": meter_file_contents,
+ "feederName1": 'ieee37_LBL',
+ "traditionalHCSteps": 10,
+ "optionalCircuitFile": 'on',
+ "traditionalHCkW": 1
+ }
+ creationCode = __neoMetaModel__.new(modelDir, defaultInputs)
+ try:
+ shutil.copyfile(
+ pJoin(__neoMetaModel__._omfDir, "static", "hostingcapacityfiles", defaultInputs["feederName1"]+'.omd'),
+ pJoin(modelDir, defaultInputs["feederName1"]+'.omd'))
+ except:
+ return False
+ return creationCode
@neoMetaModel_test_setup
def _disabled_tests():
- # Location
- modelLoc = pJoin(__neoMetaModel__._omfDir,"data","Model","admin","Automated Testing of " + modelName)
- # Blow away old test results if necessary.
- try:
- shutil.rmtree(modelLoc)
- except:
- # No previous test results.
- pass
- # Create New.
- new(modelLoc)
- # Pre-run.
- __neoMetaModel__.renderAndShow(modelLoc)
- # Run the model.
- __neoMetaModel__.runForeground(modelLoc)
- # Show the output.
- __neoMetaModel__.renderAndShow(modelLoc)
+ # Location
+ modelLoc = pJoin(__neoMetaModel__._omfDir,"data","Model","admin","Automated Testing of " + modelName)
+ # Blow away old test results if necessary.
+ try:
+ shutil.rmtree(modelLoc)
+ except:
+ pass # No previous test results.
+ # Create New.
+ new(modelLoc)
+ # Pre-run.
+ __neoMetaModel__.renderAndShow(modelLoc)
+ # Run the model.
+ __neoMetaModel__.runForeground(modelLoc)
+ # Show the output.
+ __neoMetaModel__.renderAndShow(modelLoc)
if __name__ == '__main__':
- _disabled_tests()
+ _disabled_tests()
\ No newline at end of file