The ModelChain
Endpoint Tutorial
Note
This tutorial assumes you have already set up a Python environment on your machine. If not, see Setting up a Python Environment for help on how to set this up.
Definition
See the ModelChain Endpoint for a definition of this endpoint.
This is the endpoint to use for running 2D calculations. It runs synchronously (you must wait for it to return).
Tutorial
We have provided some files for the tutorial. These were generated from the SolarFarmer desktop application (see Generating API input files from the SolarFarmer desktop application for how to do this yourself).
A fictitious fixed-tilt racks site (near Bern in Switzerland)
3 inverters. Racks are 30 modules long, 3 module high. String length is 30. The 2D view (in SolarFarmer) of the fixed-tilt racks site looks like this:A fictitious single-axis tracker site (near Bern in Switzerland)
4 inverters. 0.5 MW AC. Trackers are 30 modules long, 2 modules high. String length is 30. Tracking algorithm set to backtracking. The 2D view (in SolarFarmer) of the single-axis tracker site looks like this:
Feel free to use the Python script as a starting point for your own scripting journey using the ModelChain
endpoint.
Create a new empty folder (e.g. in
C:\Temp\Tutorials
)Right-click the following link and select 'Save link as': ModelChainEndpointTutorial.py
- Save it as
"ModelChainEndpointTutorial.py"
- Open it in a text editor (e.g., Visual Studio Code or Notepad++)
- Replace the text 'ENTER YOUR API TOKEN HERE!!!' with your personal API token (encase it in single quotes)
- Save it as
Right-click on one of the following input files: InputsFor2D_racks.zip or InputsFor2D_trackers.zip depending on the type of site you are interested in, and save it to the same folder.
- Unzip the contents to an
InputsFor2D
sub-folder (it must be named this as it is referenced in the Python script). This contains the input files needed to run the ModelChain endpoint for this tutorial. - The EnergyCalculationInputs object required was saved to the
"EnergyCalcInputs.json"
file for this tutorial rather than created manually in python. Open it in a text editor to examine its contents.
- Unzip the contents to an
Open a command prompt in the folder.
Type
python ModelChainEndpointTutorial.py
and hit Return to run the script.It may take up to 10 seconds to run, for the fixed-tilt site you should see an output similar to this (note that the numbers will be different for the trackers site):
Sending POST request to https://solarfarmer.dnv.com/latest/api/ModelChain... Request has returned... SUCCESS: Calculation returned successfully Energy yield results totals for year: { "recordCount": 8760, "percentComplete": 99.99999999999983, "averageTemperature": 10.607920426907318, "ghi": 1192.7340000000002, "gi": 1373.3998258765305, "giWithHorizon": 1373.3998258765307, "gainOnTiltedPlane": 0.15147201796589194, "globalEffectiveIrradiance": 1298.0776775552472, "modulePower": 556298.973838618, "modulePowerAtSTC": 578372.3684781528, "nominalEnergy": 578293.605350863, "pdc": 535663.7904797235, "pac": 519353.412220547, "performanceRatio": 0.8218792979786185, "netEnergy": 502.86653814960306, "energyYield": 1128.7688847353597 } Saved annual energy yield results to C:\Temp\Tutorials\Outputs\AnnualEnergyResults.json Sum EOutInv column in PVsyst format results to get total AC annual energy: 519353.579879 kWh Saved PVsyst results file to C:\Temp\Tutorials\Outputs\PVsystResults.csv Saved timeseries results file to C:\Temp\Tutorials\Outputs\TimeSeriesResults.tsv Saved loss tree results file to C:\Temp\Tutorials\Outputs\LossTreeResults.tsv Saved system attributes to C:\Temp\Tutorials\Outputs\System attributes.json
There should be an
Outputs
folder now in your folder. This will contain 5 files containing the results extracted from the ModelChainResponse object returned.See the Outputs section in ModelChain Endpoint for more detailed information on these outputs.
A quick summary:
AnnualEnergyResults.json
- this is the annual energy results for the yearPVsystResults.csv
- the PVsyst results file.- To view in Excel:
- Create a new Excel workbook
- Go to the Data ribbon and click the 'From Text/CSV' button
- Select the
PVsystResults.csv
file that was written and click 'Import' - It should automatically detect that the Semicolon is the delimiter.
- Click 'Load' to load it
- To view in Excel:
TimeSeriesResults.tsv
- time series results file (tab separated data).LossTreeResults.tsv
- loss tree results (tab separated data).System attributes.json
- details of some of the system attributes of the calculation that was run.
If you have this up and running then you can successfully run a simple energy calculation! Well done.
The next step for you will be to start constructing your own inputs and analyzing the output results for yourself. Good luck!
Handling errors
If your calculation inputs have validation errors, or something goes wrong in the calculation, the returned value will be a ProblemDetails structure. You can analyse this to see what the issues are.
An example of a ProblemDetails structure containing a validation error is shown below (when I added an extraOption property that doesn't exist):
{
"type": "https: //tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-df8191bbcb0ca7829adfcf0c7632f208-03b5f2e811862f07-00",
"errors": {
"JSON Validation Error": [
"JSON validation issue: NoAdditionalPropertiesAllowed, Line number 1, Position 2970, Property: extraOption, Path: #/EnergyCalculationOptions.extraOption"
]
}
}
Sometimes an error can appear in the 'detail' property, e.g.,:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Error",
"status": 400,
"detail": "The given key 'CanadianSolar_CS6U-330M_APPA' was not present in the dictionary.",
"traceId": "00-def788d88f66d700587e92d8d8916092-926757f1f8b103b9-00"
}
There is some Python code in the tutorial to help you unpack any errors:
elif (response.status_code >= 400):
print(f"API request failed. Error status code: {response.status_code}")
print(f"Reason: {response.reason}")
try:
# Try and convert the response to a JSON object, which it will be if a ProblemDetails
# object has been returned (e.g. for validation errors)
json_response = response.json()
print(f"Title: {json_response['title']}")
if not (json_response.get('errors') is None):
print("Errors: ")
for errorKey, errors in json_response['errors'].items():
for error in errors:
print(error)
if not (json_response.get('detail') is None):
print(f"Detail: {json_response['detail']}")
except Exception:
# couldn't get JSON from the response. Just print out the text
print(f"Message: {response.text}")