Skip to content

Commit

Permalink
Added stub for new model: omf.restoration
Browse files Browse the repository at this point in the history
  • Loading branch information
LMSlaugh committed Jul 31, 2023
1 parent 5da545d commit 91e2d7c
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 1 deletion.
3 changes: 2 additions & 1 deletion omf/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@
from omf.models import outageCost
from omf.models import faultAnalysis
from omf.models import vbatStacked
from omf.models import disaggregation
from omf.models import disaggregation
from omf.models import restoration
99 changes: 99 additions & 0 deletions omf/models/restoration.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<head>
{{ omfHeaders }}
<script src="{{pathPrefix}}/static/highcharts4.src.js"></script>
{% macro insert_file_upload_block(fileName, dataVariableName) -%}
<input id="{{dataVariableName}}Handler" type="file" style="display:none" onchange="handle_files(this.files,'{{dataVariableName}}','{{fileName}}')">
<input id="{{dataVariableName}}" name="{{dataVariableName}}" value="{{allInputDataDict[dataVariableName]}}" type="hidden">
<div>
<label for="{{dataVariableName}}Handler" class="fileButton">Choose File</label>
<input id="{{fileName}}" name="{{fileName}}" value="{{allInputDataDict[fileName]}}" readonly class="uploadFileName">
</div>
{%- endmacro %}
</head>
<body>
{{ omfModelTitle }}
<p class="reportTitle">Model Input</p>
<div id="input" class="content">
<form name="inputForm" action="/runModel/" onsubmit="event.preventDefault(); return isFormValid();" method="post">
<div class="shortInput">
<label>Model Type <a href="https://github.com/dpinney/omf/wiki/Models-~-cyberInverters" target="blank">Help?</a></label>
<input type="text" id="modelType" name="modelType" value="{{allInputDataDict.modelType}}" readonly/>
</div>
<div class="shortInput">
<label>Model Name</label>
<input type="text" id="modelName" name="modelName" value="{{allInputDataDict.modelName}}" required="required" pattern="^[\w\s]+$"/></td>
</div>
<div class="shortInput">
<label>Created</label>
<input type="text" id="created" name="created" value="{{allInputDataDict.created}}" readonly/></td>
</div>
<div class="shortInput">
<label>User</label>
<input type="text" id="user" name="user" value="{{allInputDataDict.user}}" readonly/></td>
</div>
{% if modelStatus == 'finished' %}
<div class="shortInput">
<label>Run Time</label>
<input type="text" id="runTime" name="runTime" value="{{allInputDataDict.runTime}}" readonly/></td>
</div>
{% endif %}
<div class="wideInput">
<p class="inputSectionHeader">System Specifications</p>
</div>
<hr>
<div class="shortInput">
<label>Date Input (YYYY-MM-DDTHH:mm:SSZ)</label>
<input type="text" id="date" name="date" value="{{allInputDataDict.date}}" required="required" pattern="^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(Z|(\+|-)\d\d:\d\d)$"/>
</div>
<div class="shortInput">
<label class="tooltip">Circuit Editor<span class="classic">Use a visual interface to upload, view, and manipulate a .dss circuit file.</span></label>
<button id="feederButton" type="button" onclick="editFeeder('{{allInputDataDict.modelName}}',1)" style="display:block;width:125px;">Open Editor</button>
</div>
<div class="shortInput" style="display:none">
<input type="text" id="feederName1" name="feederName1" value="{{allInputDataDict.feederName1}}">
</div>
<div class="shortInput">
<label class="tooltip">Example File Input<span class="classic">Import a [format extension] file that describes [insert content]</span></label>
<div>{{ insert_file_upload_block('exampleFileName','exampleFileContent') }}</div>
</div>


<div class="wideInput">
<p class="inputSectionHeader">[Other] Specifications</p>
</div>
<hr>
<div class="shortInput">
<label class="tooltip">Generic Numerical Input 1<span class="classic">An example of numerical input.</span></label>
<input type="number" id="number1" name="number1" value="{{allInputDataDict.number1}}"/>
</div>
<div class="shortInput">
<label class="tooltip">Generic Numerical Input 2<span class="classic">An example of numerical input.</span></label>
<input type="number" id="number2" name="number2" value="{{allInputDataDict.number2}}"/>
</div>
{{ omfModelButtons }}
</form>
</div>
{{ omfRunDebugBlock }}
{% if modelStatus == 'finished' %}
<div id="output">
<!-- Insert visualizations here (for examples, see other models such as cyberinverters) -->
<!-- Integer Sum Table -->
<p class="reportTitle">Example Output</p>
<div id="analysisSummary" class="content">
<div class="shortInput">
<strong>Input 1</strong>
<p id="input1Out">{{allInputDataDict.number1}}</p>
</div>
<div class="shortInput">
<strong>Input 2</strong>
<p id="input2Out">{{allInputDataDict.number2}}</p>
</div>
<div class="shortInput">
<strong>Sum of Input 1 and Input 2</strong>
<p id="sumOut">{{allOutputDataDict.output}}</p>
</div>
</div>
{{rawOutputFiles}}
</div>
{% endif %}
</body>
90 changes: 90 additions & 0 deletions omf/models/restoration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import os, shutil
from os.path import join as pJoin

# OMF imports
from omf.models import __neoMetaModel__
from omf.models.__neoMetaModel__ import *

# Model metadata:
modelName, template = __neoMetaModel__.metadata(__file__)
tooltip = "This is a stub for the creation of new models. Update this description to match your model's purpose."
hidden = True # Change to False to make visible in the omf's "new model" list
hidden = False

def castAddInputs(val1,val2):
''' Casts string inputs to appropriate type and returns their sum.
If inputs are cast to floats, rounds their sum to avoid float subtraction errors.'''
try:
cast1 = int(val1)
cast2 = int(val2)
return cast1+cast2
except ValueError:
try:
cast1 = float(val1)
cast2 = float(val2)
#Find longest decimal place of the numbers and round their sum to that place to avoid float arithmetic errors
decPl1 = val1.strip()[::-1].find('.')
decPl2 = val2.strip()[::-1].find('.')
#valX.strip() used instead of str(castX) because str(castX) may return scientific notation
roundedSum = round(cast1+cast2,max(decPl1,decPl2,1))
return roundedSum
except ValueError:
return val1+val2

def work(modelDir, inputDict):
''' Run the model in its directory. '''
# Delete output file every run if it exists
outData = {}

# Model operations goes here.
inputOne = inputDict.get("number1", 123)
inputTwo = inputDict.get("number2", 867)
outData["output"] = castAddInputs(inputOne, inputTwo)
# Model operations typically end here.

# Stdout/stderr.
outData["stdout"] = "Success"
outData["stderr"] = ""
return outData


def new(modelDir):
''' Create a new instance of this model. Returns true on success, false on failure. '''
omd_fn = "ieee240.dss.omd"
ex_fn = "example.csv" # example file input

with open(pJoin(omf.omfDir, "static", "testFiles", "restoration", ex_fn)) as ex_stream:
ex_ins = ex_stream.read()

defaultInputs = {
"modelType": modelName,
"date": "2019-07-01T00:00:00Z",
"number1": "123",
"number2": "987",
"feederName1": omd_fn,
"exampleFileName": ex_fn,
"exampleFileContent": ex_ins,
}
return __neoMetaModel__.new(modelDir, defaultInputs)

@neoMetaModel_test_setup
def _debugging():
# 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)

if __name__ == '__main__':
_debugging()
6 changes: 6 additions & 0 deletions omf/static/testFiles/restoration/example.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
s701a_pv,s730c_pv
0.982467298,0.985155168
1.012467298,1.015155168
1.012467298,1.015155168
1.042467298,1.045155168
1.062467298,1.065155168

0 comments on commit 91e2d7c

Please sign in to comment.