openstudio-calibration 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +29 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +20 -0
- data/Jenkinsfile +6 -0
- data/LICENSE.md +27 -0
- data/README.md +33 -0
- data/Rakefile +50 -0
- data/doc_templates/LICENSE.md +27 -0
- data/doc_templates/README.md.erb +42 -0
- data/doc_templates/copyright_erb.txt +36 -0
- data/doc_templates/copyright_js.txt +4 -0
- data/doc_templates/copyright_ruby.txt +34 -0
- data/lib/files/.gitkeep +0 -0
- data/lib/measures/AddMonthlyJSONUtilityData/LICENSE.md +27 -0
- data/lib/measures/AddMonthlyJSONUtilityData/README.md +96 -0
- data/lib/measures/AddMonthlyJSONUtilityData/README.md.erb +42 -0
- data/lib/measures/AddMonthlyJSONUtilityData/measure.rb +280 -0
- data/lib/measures/AddMonthlyJSONUtilityData/measure.xml +163 -0
- data/lib/measures/AddMonthlyUtilityData/LICENSE.md +27 -0
- data/lib/measures/AddMonthlyUtilityData/README.md +64 -0
- data/lib/measures/AddMonthlyUtilityData/README.md.erb +42 -0
- data/lib/measures/AddMonthlyUtilityData/measure.rb +312 -0
- data/lib/measures/AddMonthlyUtilityData/measure.xml +115 -0
- data/lib/measures/AddMonthlyUtilityData/tests/AddMonthlyUtilityData_Test.rb +88 -0
- data/lib/measures/AddMonthlyUtilityData/tests/electric_billed_usages.json +198 -0
- data/lib/measures/AddMonthlyUtilityData/tests/gas_billed_usages.json +198 -0
- data/lib/measures/CalibrationReports/LICENSE.md +27 -0
- data/lib/measures/CalibrationReports/README.md +26 -0
- data/lib/measures/CalibrationReports/README.md.erb +42 -0
- data/lib/measures/CalibrationReports/measure.rb +511 -0
- data/lib/measures/CalibrationReports/measure.xml +98 -0
- data/lib/measures/CalibrationReports/resources/report.html.in +379 -0
- data/lib/measures/CalibrationReports/tests/CalibrationReports_Test.rb +523 -0
- data/lib/measures/CalibrationReports/tests/ExampleModel.osm +10497 -0
- data/lib/measures/CalibrationReports/tests/ExampleModelNoDemandInput.osm +10560 -0
- data/lib/measures/CalibrationReports/tests/ExampleModelNoGasInput.osm +10456 -0
- data/lib/measures/CalibrationReports/tests/USA_CO_Golden-NREL.724666_TMY3.epw +8768 -0
- data/lib/measures/CalibrationReportsEnhanced/LICENSE.md +27 -0
- data/lib/measures/CalibrationReportsEnhanced/README.md +143 -0
- data/lib/measures/CalibrationReportsEnhanced/README.md.erb +42 -0
- data/lib/measures/CalibrationReportsEnhanced/measure.rb +798 -0
- data/lib/measures/CalibrationReportsEnhanced/measure.xml +372 -0
- data/lib/measures/CalibrationReportsEnhanced/resources/report.html.in +380 -0
- data/lib/measures/CalibrationReportsEnhanced/tests/CalibrationReportsEnhanced_Test.rb +734 -0
- data/lib/measures/CalibrationReportsEnhanced/tests/ExampleModel.osm +10497 -0
- data/lib/measures/CalibrationReportsEnhanced/tests/ExampleModel_FuelOil.osm +12740 -0
- data/lib/measures/CalibrationReportsEnhanced/tests/USA_CO_Golden-NREL.724666_TMY3.epw +8768 -0
- data/lib/measures/CalibrationReportsEnhanced21/LICENSE.md +27 -0
- data/lib/measures/CalibrationReportsEnhanced21/README.md +109 -0
- data/lib/measures/CalibrationReportsEnhanced21/README.md.erb +42 -0
- data/lib/measures/CalibrationReportsEnhanced21/measure.rb +690 -0
- data/lib/measures/CalibrationReportsEnhanced21/measure.xml +269 -0
- data/lib/measures/CalibrationReportsEnhanced21/resources/report.html.in +380 -0
- data/lib/measures/CoilCoolingDXSingleSpeedMultiplier/LICENSE.md +27 -0
- data/lib/measures/CoilCoolingDXSingleSpeedMultiplier/README.md +48 -0
- data/lib/measures/CoilCoolingDXSingleSpeedMultiplier/README.md.erb +42 -0
- data/lib/measures/CoilCoolingDXSingleSpeedMultiplier/measure.rb +237 -0
- data/lib/measures/CoilCoolingDXSingleSpeedMultiplier/measure.xml +93 -0
- data/lib/measures/CoilCoolingDXSingleSpeedPercentChange/LICENSE.md +27 -0
- data/lib/measures/CoilCoolingDXSingleSpeedPercentChange/README.md +48 -0
- data/lib/measures/CoilCoolingDXSingleSpeedPercentChange/README.md.erb +42 -0
- data/lib/measures/CoilCoolingDXSingleSpeedPercentChange/measure.rb +228 -0
- data/lib/measures/CoilCoolingDXSingleSpeedPercentChange/measure.xml +93 -0
- data/lib/measures/CoilCoolingDXTwoSpeedMultiplier/LICENSE.md +27 -0
- data/lib/measures/CoilCoolingDXTwoSpeedMultiplier/README.md +64 -0
- data/lib/measures/CoilCoolingDXTwoSpeedMultiplier/README.md.erb +42 -0
- data/lib/measures/CoilCoolingDXTwoSpeedMultiplier/measure.rb +280 -0
- data/lib/measures/CoilCoolingDXTwoSpeedMultiplier/measure.xml +111 -0
- data/lib/measures/CoilCoolingDXTwoSpeedPercentChange/LICENSE.md +27 -0
- data/lib/measures/CoilCoolingDXTwoSpeedPercentChange/README.md +64 -0
- data/lib/measures/CoilCoolingDXTwoSpeedPercentChange/README.md.erb +42 -0
- data/lib/measures/CoilCoolingDXTwoSpeedPercentChange/measure.rb +270 -0
- data/lib/measures/CoilCoolingDXTwoSpeedPercentChange/measure.xml +111 -0
- data/lib/measures/CoilCoolingWaterMultiplier/LICENSE.md +27 -0
- data/lib/measures/CoilCoolingWaterMultiplier/README.md +80 -0
- data/lib/measures/CoilCoolingWaterMultiplier/README.md.erb +42 -0
- data/lib/measures/CoilCoolingWaterMultiplier/measure.rb +324 -0
- data/lib/measures/CoilCoolingWaterMultiplier/measure.xml +129 -0
- data/lib/measures/CoilCoolingWaterPercentChange/LICENSE.md +27 -0
- data/lib/measures/CoilCoolingWaterPercentChange/README.md +80 -0
- data/lib/measures/CoilCoolingWaterPercentChange/README.md.erb +42 -0
- data/lib/measures/CoilCoolingWaterPercentChange/measure.rb +311 -0
- data/lib/measures/CoilCoolingWaterPercentChange/measure.xml +129 -0
- data/lib/measures/CoilHeatingElectricMultiplier/LICENSE.md +27 -0
- data/lib/measures/CoilHeatingElectricMultiplier/README.md +48 -0
- data/lib/measures/CoilHeatingElectricMultiplier/README.md.erb +42 -0
- data/lib/measures/CoilHeatingElectricMultiplier/measure.rb +240 -0
- data/lib/measures/CoilHeatingElectricMultiplier/measure.xml +93 -0
- data/lib/measures/CoilHeatingElectricPercentChange/LICENSE.md +27 -0
- data/lib/measures/CoilHeatingElectricPercentChange/README.md +48 -0
- data/lib/measures/CoilHeatingElectricPercentChange/README.md.erb +42 -0
- data/lib/measures/CoilHeatingElectricPercentChange/measure.rb +231 -0
- data/lib/measures/CoilHeatingElectricPercentChange/measure.xml +93 -0
- data/lib/measures/CoilHeatingGasMultiplier/LICENSE.md +27 -0
- data/lib/measures/CoilHeatingGasMultiplier/README.md +64 -0
- data/lib/measures/CoilHeatingGasMultiplier/README.md.erb +42 -0
- data/lib/measures/CoilHeatingGasMultiplier/measure.rb +282 -0
- data/lib/measures/CoilHeatingGasMultiplier/measure.xml +111 -0
- data/lib/measures/CoilHeatingGasPercentChange/LICENSE.md +27 -0
- data/lib/measures/CoilHeatingGasPercentChange/README.md +64 -0
- data/lib/measures/CoilHeatingGasPercentChange/README.md.erb +42 -0
- data/lib/measures/CoilHeatingGasPercentChange/measure.rb +271 -0
- data/lib/measures/CoilHeatingGasPercentChange/measure.xml +111 -0
- data/lib/measures/CoilHeatingWaterMultiplier/LICENSE.md +27 -0
- data/lib/measures/CoilHeatingWaterMultiplier/README.md +48 -0
- data/lib/measures/CoilHeatingWaterMultiplier/README.md.erb +42 -0
- data/lib/measures/CoilHeatingWaterMultiplier/measure.rb +235 -0
- data/lib/measures/CoilHeatingWaterMultiplier/measure.xml +93 -0
- data/lib/measures/CoilHeatingWaterPercentChange/LICENSE.md +27 -0
- data/lib/measures/CoilHeatingWaterPercentChange/README.md +48 -0
- data/lib/measures/CoilHeatingWaterPercentChange/README.md.erb +42 -0
- data/lib/measures/CoilHeatingWaterPercentChange/measure.rb +226 -0
- data/lib/measures/CoilHeatingWaterPercentChange/measure.xml +93 -0
- data/lib/measures/ConstructionLayerZeroMaterialProperties/LICENSE.md +27 -0
- data/lib/measures/ConstructionLayerZeroMaterialProperties/README.md +88 -0
- data/lib/measures/ConstructionLayerZeroMaterialProperties/README.md.erb +42 -0
- data/lib/measures/ConstructionLayerZeroMaterialProperties/measure.rb +221 -0
- data/lib/measures/ConstructionLayerZeroMaterialProperties/measure.xml +194 -0
- data/lib/measures/ElectricBaseboardEfficiencyAndCapacity/LICENSE.md +27 -0
- data/lib/measures/ElectricBaseboardEfficiencyAndCapacity/README.md +40 -0
- data/lib/measures/ElectricBaseboardEfficiencyAndCapacity/README.md.erb +42 -0
- data/lib/measures/ElectricBaseboardEfficiencyAndCapacity/measure.rb +102 -0
- data/lib/measures/ElectricBaseboardEfficiencyAndCapacity/measure.xml +78 -0
- data/lib/measures/ExteriorWallThermalPropertiesMultiplier/LICENSE.md +27 -0
- data/lib/measures/ExteriorWallThermalPropertiesMultiplier/README.md +48 -0
- data/lib/measures/ExteriorWallThermalPropertiesMultiplier/README.md.erb +42 -0
- data/lib/measures/ExteriorWallThermalPropertiesMultiplier/measure.rb +263 -0
- data/lib/measures/ExteriorWallThermalPropertiesMultiplier/measure.xml +97 -0
- data/lib/measures/ExteriorWallThermalPropertiesPercentChange/LICENSE.md +27 -0
- data/lib/measures/ExteriorWallThermalPropertiesPercentChange/README.md +48 -0
- data/lib/measures/ExteriorWallThermalPropertiesPercentChange/README.md.erb +42 -0
- data/lib/measures/ExteriorWallThermalPropertiesPercentChange/measure.rb +253 -0
- data/lib/measures/ExteriorWallThermalPropertiesPercentChange/measure.xml +97 -0
- data/lib/measures/FansMultiplier/LICENSE.md +27 -0
- data/lib/measures/FansMultiplier/README.md +64 -0
- data/lib/measures/FansMultiplier/README.md.erb +42 -0
- data/lib/measures/FansMultiplier/measure.rb +297 -0
- data/lib/measures/FansMultiplier/measure.xml +166 -0
- data/lib/measures/FansPercentChange/LICENSE.md +27 -0
- data/lib/measures/FansPercentChange/README.md +64 -0
- data/lib/measures/FansPercentChange/README.md.erb +42 -0
- data/lib/measures/FansPercentChange/measure.rb +286 -0
- data/lib/measures/FansPercentChange/measure.xml +166 -0
- data/lib/measures/GeneralCalibrationMeasureMultiplier/LICENSE.md +27 -0
- data/lib/measures/GeneralCalibrationMeasureMultiplier/README.md +112 -0
- data/lib/measures/GeneralCalibrationMeasureMultiplier/README.md.erb +42 -0
- data/lib/measures/GeneralCalibrationMeasureMultiplier/measure.rb +639 -0
- data/lib/measures/GeneralCalibrationMeasureMultiplier/measure.xml +229 -0
- data/lib/measures/GeneralCalibrationMeasurePercentChange/LICENSE.md +27 -0
- data/lib/measures/GeneralCalibrationMeasurePercentChange/README.md +112 -0
- data/lib/measures/GeneralCalibrationMeasurePercentChange/README.md.erb +42 -0
- data/lib/measures/GeneralCalibrationMeasurePercentChange/measure.rb +756 -0
- data/lib/measures/GeneralCalibrationMeasurePercentChange/measure.xml +229 -0
- data/lib/measures/HardSizeHvac/LICENSE.md +27 -0
- data/lib/measures/HardSizeHvac/README.md +26 -0
- data/lib/measures/HardSizeHvac/README.md.erb +42 -0
- data/lib/measures/HardSizeHvac/measure.rb +88 -0
- data/lib/measures/HardSizeHvac/measure.xml +81 -0
- data/lib/measures/MaalkaMonthlyJSONUtilityData/LICENSE.md +27 -0
- data/lib/measures/MaalkaMonthlyJSONUtilityData/README.md +104 -0
- data/lib/measures/MaalkaMonthlyJSONUtilityData/README.md.erb +42 -0
- data/lib/measures/MaalkaMonthlyJSONUtilityData/measure.rb +304 -0
- data/lib/measures/MaalkaMonthlyJSONUtilityData/measure.xml +216 -0
- data/lib/measures/RValueOfInsulationForConstructionMultiplier/LICENSE.md +27 -0
- data/lib/measures/RValueOfInsulationForConstructionMultiplier/README.md +40 -0
- data/lib/measures/RValueOfInsulationForConstructionMultiplier/README.md.erb +42 -0
- data/lib/measures/RValueOfInsulationForConstructionMultiplier/measure.rb +196 -0
- data/lib/measures/RValueOfInsulationForConstructionMultiplier/measure.xml +132 -0
- data/lib/measures/RValueOfInsulationForConstructionPercentageChange/LICENSE.md +27 -0
- data/lib/measures/RValueOfInsulationForConstructionPercentageChange/README.md +40 -0
- data/lib/measures/RValueOfInsulationForConstructionPercentageChange/README.md.erb +42 -0
- data/lib/measures/RValueOfInsulationForConstructionPercentageChange/measure.rb +189 -0
- data/lib/measures/RValueOfInsulationForConstructionPercentageChange/measure.xml +132 -0
- data/lib/measures/RoofThermalPropertiesMultiplier/LICENSE.md +27 -0
- data/lib/measures/RoofThermalPropertiesMultiplier/README.md +48 -0
- data/lib/measures/RoofThermalPropertiesMultiplier/README.md.erb +42 -0
- data/lib/measures/RoofThermalPropertiesMultiplier/measure.rb +263 -0
- data/lib/measures/RoofThermalPropertiesMultiplier/measure.xml +97 -0
- data/lib/measures/RoofThermalPropertiesPercentChange/LICENSE.md +27 -0
- data/lib/measures/RoofThermalPropertiesPercentChange/README.md +48 -0
- data/lib/measures/RoofThermalPropertiesPercentChange/README.md.erb +42 -0
- data/lib/measures/RoofThermalPropertiesPercentChange/measure.rb +253 -0
- data/lib/measures/RoofThermalPropertiesPercentChange/measure.xml +97 -0
- data/lib/measures/TimeseriesObjectiveFunction/LICENSE.md +27 -0
- data/lib/measures/TimeseriesObjectiveFunction/README.md +207 -0
- data/lib/measures/TimeseriesObjectiveFunction/README.md.erb +42 -0
- data/lib/measures/TimeseriesObjectiveFunction/measure.rb +748 -0
- data/lib/measures/TimeseriesObjectiveFunction/measure.xml +435 -0
- data/lib/measures/TimeseriesObjectiveFunction/resources/report.html.erb +288 -0
- data/lib/measures/TimeseriesPlot/LICENSE.md +27 -0
- data/lib/measures/TimeseriesPlot/README.md +56 -0
- data/lib/measures/TimeseriesPlot/README.md.erb +42 -0
- data/lib/measures/TimeseriesPlot/measure.rb +302 -0
- data/lib/measures/TimeseriesPlot/measure.xml +137 -0
- data/lib/measures/TimeseriesPlot/resources/report.html.erb +270 -0
- data/lib/measures/WaterHeaterMixedMultiplier/LICENSE.md +27 -0
- data/lib/measures/WaterHeaterMixedMultiplier/README.md +64 -0
- data/lib/measures/WaterHeaterMixedMultiplier/README.md.erb +42 -0
- data/lib/measures/WaterHeaterMixedMultiplier/measure.rb +255 -0
- data/lib/measures/WaterHeaterMixedMultiplier/measure.xml +180 -0
- data/lib/measures/WaterHeaterMixedPercentChange/LICENSE.md +27 -0
- data/lib/measures/WaterHeaterMixedPercentChange/README.md +64 -0
- data/lib/measures/WaterHeaterMixedPercentChange/README.md.erb +42 -0
- data/lib/measures/WaterHeaterMixedPercentChange/measure.rb +245 -0
- data/lib/measures/WaterHeaterMixedPercentChange/measure.xml +180 -0
- data/lib/measures/zone_report/LICENSE.md +27 -0
- data/lib/measures/zone_report/README.md +26 -0
- data/lib/measures/zone_report/README.md.erb +42 -0
- data/lib/measures/zone_report/measure.rb +706 -0
- data/lib/measures/zone_report/measure.xml +67 -0
- data/lib/measures/zone_report/resources/report.html.in +342 -0
- data/lib/openstudio-calibration-measures.rb +36 -0
- data/lib/openstudio/calibration_measures.rb +37 -0
- data/lib/openstudio/calibration_measures/extension.rb +49 -0
- data/lib/openstudio/calibration_measures/version.rb +40 -0
- data/openstudio-calibration.gemspec +30 -0
- metadata +331 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC. All rights reserved.
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted
|
|
4
|
+
provided that the following conditions are met:
|
|
5
|
+
|
|
6
|
+
(1) Redistributions of source code must retain the above copyright notice, this list of conditions
|
|
7
|
+
and the following disclaimer.
|
|
8
|
+
|
|
9
|
+
(2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
|
10
|
+
and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
11
|
+
|
|
12
|
+
(3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse
|
|
13
|
+
or promote products derived from this software without specific prior written permission from the
|
|
14
|
+
respective party.
|
|
15
|
+
|
|
16
|
+
(4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other
|
|
17
|
+
derivative works may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar
|
|
18
|
+
designation without specific prior written permission from Alliance for Sustainable Energy, LLC.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
21
|
+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
22
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES GOVERNMENT,
|
|
23
|
+
OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
|
25
|
+
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
26
|
+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
27
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
###### (Automatically generated documentation)
|
|
4
|
+
|
|
5
|
+
# TimeSeries Objective Function
|
|
6
|
+
|
|
7
|
+
## Description
|
|
8
|
+
Creates Objective Function from Timeseries Data
|
|
9
|
+
|
|
10
|
+
## Modeler Description
|
|
11
|
+
Creates Objective Function from Timeseries Data. The measure applies a Norm at each timestep between the difference of CSV metered data and SQL model data. A timeseries plot can also be created. Possible outputs are 'cvrmse', 'nmbe', 'simdata' = sum of the simulated data, 'csvdata' = sum of metered data, 'diff' = P Norm between the metered and simulated data if Norm is 1 or 2, else its just the Difference.
|
|
12
|
+
|
|
13
|
+
## Measure Type
|
|
14
|
+
ReportingMeasure
|
|
15
|
+
|
|
16
|
+
## Taxonomy
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## Arguments
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Path to CSV file for the metered data
|
|
23
|
+
Path to CSV file including file name.
|
|
24
|
+
**Name:** csv_name,
|
|
25
|
+
**Type:** String,
|
|
26
|
+
**Units:** ,
|
|
27
|
+
**Required:** true,
|
|
28
|
+
**Model Dependent:** false
|
|
29
|
+
|
|
30
|
+
### CSV Time Header
|
|
31
|
+
CSV Time Header Value. Used to determine the timestamp column in the CSV file
|
|
32
|
+
**Name:** csv_time_header,
|
|
33
|
+
**Type:** String,
|
|
34
|
+
**Units:** ,
|
|
35
|
+
**Required:** true,
|
|
36
|
+
**Model Dependent:** false
|
|
37
|
+
|
|
38
|
+
### CSV variable name
|
|
39
|
+
CSV variable name. Used to determine the variable column in the CSV file
|
|
40
|
+
**Name:** csv_var,
|
|
41
|
+
**Type:** String,
|
|
42
|
+
**Units:** ,
|
|
43
|
+
**Required:** true,
|
|
44
|
+
**Model Dependent:** false
|
|
45
|
+
|
|
46
|
+
### Convert Units
|
|
47
|
+
Convert Units in Metered Data
|
|
48
|
+
**Name:** convert_data,
|
|
49
|
+
**Type:** Choice,
|
|
50
|
+
**Units:** ,
|
|
51
|
+
**Required:** true,
|
|
52
|
+
**Model Dependent:** false
|
|
53
|
+
|
|
54
|
+
### CSV variable display name
|
|
55
|
+
CSV variable display name. Not yet Implemented
|
|
56
|
+
**Name:** csv_var_dn,
|
|
57
|
+
**Type:** String,
|
|
58
|
+
**Units:** ,
|
|
59
|
+
**Required:** true,
|
|
60
|
+
**Model Dependent:** false
|
|
61
|
+
|
|
62
|
+
### Year in csv data timestamp
|
|
63
|
+
Is the Year in the csv data timestamp => mm:dd:yy or mm:dd (true/false)
|
|
64
|
+
**Name:** year,
|
|
65
|
+
**Type:** Boolean,
|
|
66
|
+
**Units:** ,
|
|
67
|
+
**Required:** true,
|
|
68
|
+
**Model Dependent:** false
|
|
69
|
+
|
|
70
|
+
### Seconds in csv data timestamp
|
|
71
|
+
Is the Seconds in the csv data timestamp => hh:mm:ss or hh:mm (true/false)
|
|
72
|
+
**Name:** seconds,
|
|
73
|
+
**Type:** Boolean,
|
|
74
|
+
**Units:** ,
|
|
75
|
+
**Required:** true,
|
|
76
|
+
**Model Dependent:** false
|
|
77
|
+
|
|
78
|
+
### SQL key value
|
|
79
|
+
SQL key value for the SQL query to find the variable in the SQL file
|
|
80
|
+
**Name:** key_value,
|
|
81
|
+
**Type:** String,
|
|
82
|
+
**Units:** ,
|
|
83
|
+
**Required:** true,
|
|
84
|
+
**Model Dependent:** false
|
|
85
|
+
|
|
86
|
+
### TimeSeries Name
|
|
87
|
+
TimeSeries Name for the SQL query to find the variable in the SQL file
|
|
88
|
+
**Name:** timeseries_name,
|
|
89
|
+
**Type:** String,
|
|
90
|
+
**Units:** ,
|
|
91
|
+
**Required:** true,
|
|
92
|
+
**Model Dependent:** false
|
|
93
|
+
|
|
94
|
+
### Reporting Frequency
|
|
95
|
+
Reporting Frequency for SQL Query
|
|
96
|
+
**Name:** reporting_frequency,
|
|
97
|
+
**Type:** Choice,
|
|
98
|
+
**Units:** ,
|
|
99
|
+
**Required:** true,
|
|
100
|
+
**Model Dependent:** false
|
|
101
|
+
|
|
102
|
+
### Environment Period
|
|
103
|
+
Environment Period for SQL query
|
|
104
|
+
**Name:** environment_period,
|
|
105
|
+
**Type:** String,
|
|
106
|
+
**Units:** ,
|
|
107
|
+
**Required:** true,
|
|
108
|
+
**Model Dependent:** false
|
|
109
|
+
|
|
110
|
+
### Norm of the difference of csv and sql
|
|
111
|
+
Norm of the difference of csv and sql. 1 is absolute value. 2 is euclidean distance. 3 is raw difference.
|
|
112
|
+
**Name:** norm,
|
|
113
|
+
**Type:** Double,
|
|
114
|
+
**Units:** ,
|
|
115
|
+
**Required:** true,
|
|
116
|
+
**Model Dependent:** false
|
|
117
|
+
|
|
118
|
+
### Scale factor to apply to the difference
|
|
119
|
+
Scale factor to apply to the difference (1 is no scale)
|
|
120
|
+
**Name:** scale,
|
|
121
|
+
**Type:** Double,
|
|
122
|
+
**Units:** ,
|
|
123
|
+
**Required:** true,
|
|
124
|
+
**Model Dependent:** false
|
|
125
|
+
|
|
126
|
+
### Find Available data in the SQL file
|
|
127
|
+
Will RegisterInfo all the 'EnvPeriod', 'ReportingFrequencies', 'VariableNames', 'KeyValues' in the SQL file. Useful for debugging SQL issues.
|
|
128
|
+
**Name:** find_avail,
|
|
129
|
+
**Type:** Boolean,
|
|
130
|
+
**Units:** ,
|
|
131
|
+
**Required:** true,
|
|
132
|
+
**Model Dependent:** false
|
|
133
|
+
|
|
134
|
+
### algorithm_download
|
|
135
|
+
Make JSON data available for algorithm_download (true/false)
|
|
136
|
+
**Name:** algorithm_download,
|
|
137
|
+
**Type:** Boolean,
|
|
138
|
+
**Units:** ,
|
|
139
|
+
**Required:** true,
|
|
140
|
+
**Model Dependent:** false
|
|
141
|
+
|
|
142
|
+
### plot_flag timeseries data
|
|
143
|
+
Create plot of timeseries data (true/false)
|
|
144
|
+
**Name:** plot_flag,
|
|
145
|
+
**Type:** Boolean,
|
|
146
|
+
**Units:** ,
|
|
147
|
+
**Required:** true,
|
|
148
|
+
**Model Dependent:** false
|
|
149
|
+
|
|
150
|
+
### Plot name
|
|
151
|
+
Name to include in reporting file name.
|
|
152
|
+
**Name:** plot_name,
|
|
153
|
+
**Type:** String,
|
|
154
|
+
**Units:** ,
|
|
155
|
+
**Required:** true,
|
|
156
|
+
**Model Dependent:** false
|
|
157
|
+
|
|
158
|
+
### verbose_messages
|
|
159
|
+
verbose messages. Useful for debugging but MAJOR Performance Hit.
|
|
160
|
+
**Name:** verbose_messages,
|
|
161
|
+
**Type:** Boolean,
|
|
162
|
+
**Units:** ,
|
|
163
|
+
**Required:** true,
|
|
164
|
+
**Model Dependent:** false
|
|
165
|
+
|
|
166
|
+
### warning_messages
|
|
167
|
+
Warn on missing data.
|
|
168
|
+
**Name:** warning_messages,
|
|
169
|
+
**Type:** Boolean,
|
|
170
|
+
**Units:** ,
|
|
171
|
+
**Required:** true,
|
|
172
|
+
**Model Dependent:** false
|
|
173
|
+
|
|
174
|
+
### add_first_zero_for_plots
|
|
175
|
+
Add a point of zero value to the plot at the beginning of the runperiod.
|
|
176
|
+
**Name:** add_first_zero_for_plots,
|
|
177
|
+
**Type:** Boolean,
|
|
178
|
+
**Units:** ,
|
|
179
|
+
**Required:** true,
|
|
180
|
+
**Model Dependent:** false
|
|
181
|
+
|
|
182
|
+
### add_last_zero_for_plots
|
|
183
|
+
Add a point of zero value to the plot at the end of the runperiod.
|
|
184
|
+
**Name:** add_last_zero_for_plots,
|
|
185
|
+
**Type:** Boolean,
|
|
186
|
+
**Units:** ,
|
|
187
|
+
**Required:** true,
|
|
188
|
+
**Model Dependent:** false
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
## Outputs
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
diff, simdata, csvdata, cvrmse, nmbe
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<%#= README.md.erb is used to auto-generate README.md. %>
|
|
2
|
+
<%#= To manually maintain README.md throw away README.md.erb and manually edit README.md %>
|
|
3
|
+
###### (Automatically generated documentation)
|
|
4
|
+
|
|
5
|
+
# <%= name %>
|
|
6
|
+
|
|
7
|
+
## Description
|
|
8
|
+
<%= description %>
|
|
9
|
+
|
|
10
|
+
## Modeler Description
|
|
11
|
+
<%= modelerDescription %>
|
|
12
|
+
|
|
13
|
+
## Measure Type
|
|
14
|
+
<%= measureType %>
|
|
15
|
+
|
|
16
|
+
## Taxonomy
|
|
17
|
+
<%= taxonomy %>
|
|
18
|
+
|
|
19
|
+
## Arguments
|
|
20
|
+
|
|
21
|
+
<% arguments.each do |argument| %>
|
|
22
|
+
### <%= argument[:display_name] %>
|
|
23
|
+
<%= argument[:description] %>
|
|
24
|
+
**Name:** <%= argument[:name] %>,
|
|
25
|
+
**Type:** <%= argument[:type] %>,
|
|
26
|
+
**Units:** <%= argument[:units] %>,
|
|
27
|
+
**Required:** <%= argument[:required] %>,
|
|
28
|
+
**Model Dependent:** <%= argument[:model_dependent] %>
|
|
29
|
+
<% end %>
|
|
30
|
+
|
|
31
|
+
<% if arguments.size == 0 %>
|
|
32
|
+
<%= "This measure does not have any user arguments" %>
|
|
33
|
+
<% end %>
|
|
34
|
+
|
|
35
|
+
<% if outputs.size > 0 %>
|
|
36
|
+
## Outputs
|
|
37
|
+
<% output_names = [] %>
|
|
38
|
+
<% outputs.each do |output| %>
|
|
39
|
+
<% output_names << output[:display_name] %>
|
|
40
|
+
<% end %>
|
|
41
|
+
<%= output_names.join(", ") %>
|
|
42
|
+
<% end %>
|
|
@@ -0,0 +1,748 @@
|
|
|
1
|
+
# *******************************************************************************
|
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
|
6
|
+
#
|
|
7
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
|
8
|
+
# this list of conditions and the following disclaimer.
|
|
9
|
+
#
|
|
10
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
|
12
|
+
# and/or other materials provided with the distribution.
|
|
13
|
+
#
|
|
14
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
|
15
|
+
# may be used to endorse or promote products derived from this software without
|
|
16
|
+
# specific prior written permission from the respective party.
|
|
17
|
+
#
|
|
18
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
|
19
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
|
20
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
|
21
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
|
22
|
+
#
|
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
|
24
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
25
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
26
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
|
27
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
|
28
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
29
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
30
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
31
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
32
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
33
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
34
|
+
# *******************************************************************************
|
|
35
|
+
|
|
36
|
+
# see the URL below for information on how to write OpenStudio measures
|
|
37
|
+
# http://openstudio.nrel.gov/openstudio-measure-writing-guide
|
|
38
|
+
|
|
39
|
+
require 'csv'
|
|
40
|
+
require 'time'
|
|
41
|
+
require 'json'
|
|
42
|
+
require 'erb'
|
|
43
|
+
|
|
44
|
+
# start the measure
|
|
45
|
+
class TimeseriesObjectiveFunction < OpenStudio::Measure::ReportingMeasure
|
|
46
|
+
# human readable name
|
|
47
|
+
def name
|
|
48
|
+
'TimeSeries Objective Function'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# human readable description
|
|
52
|
+
def description
|
|
53
|
+
'Creates Objective Function from Timeseries Data'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# human readable description of modeling approach
|
|
57
|
+
def modeler_description
|
|
58
|
+
"Creates Objective Function from Timeseries Data. The measure applies a Norm at each timestep between the difference of CSV metered data and SQL model data. A timeseries plot can also be created. Possible outputs are 'cvrmse', 'nmbe', 'simdata' = sum of the simulated data, 'csvdata' = sum of metered data, 'diff' = P Norm between the metered and simulated data if Norm is 1 or 2, else its just the Difference."
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# define the arguments that the user will input
|
|
62
|
+
def arguments
|
|
63
|
+
args = OpenStudio::Measure::OSArgumentVector.new
|
|
64
|
+
|
|
65
|
+
# the name of the sql file
|
|
66
|
+
csv_name = OpenStudio::Measure::OSArgument.makeStringArgument('csv_name', true)
|
|
67
|
+
csv_name.setDisplayName('Path to CSV file for the metered data')
|
|
68
|
+
csv_name.setDescription('Path to CSV file including file name.')
|
|
69
|
+
csv_name.setDefaultValue('../../../lib/resources/mtr.csv')
|
|
70
|
+
args << csv_name
|
|
71
|
+
|
|
72
|
+
csv_time_header = OpenStudio::Measure::OSArgument.makeStringArgument('csv_time_header', true)
|
|
73
|
+
csv_time_header.setDisplayName('CSV Time Header')
|
|
74
|
+
csv_time_header.setDescription('CSV Time Header Value. Used to determine the timestamp column in the CSV file')
|
|
75
|
+
csv_time_header.setDefaultValue('Date/Time')
|
|
76
|
+
args << csv_time_header
|
|
77
|
+
|
|
78
|
+
csv_var = OpenStudio::Measure::OSArgument.makeStringArgument('csv_var', true)
|
|
79
|
+
csv_var.setDisplayName('CSV variable name')
|
|
80
|
+
csv_var.setDescription('CSV variable name. Used to determine the variable column in the CSV file')
|
|
81
|
+
csv_var.setDefaultValue('Whole Building:Facility Total Electric Demand Power [W](TimeStep)')
|
|
82
|
+
args << csv_var
|
|
83
|
+
|
|
84
|
+
convert_data_chs = OpenStudio::StringVector.new
|
|
85
|
+
convert_data_chs << 'F to C'
|
|
86
|
+
convert_data_chs << 'WH to J'
|
|
87
|
+
convert_data_chs << 'CFM to m3/s'
|
|
88
|
+
convert_data_chs << 'PSI to Pa'
|
|
89
|
+
convert_data_chs << 'None'
|
|
90
|
+
convert_data = OpenStudio::Measure::OSArgument.makeChoiceArgument('convert_data', convert_data_chs, true)
|
|
91
|
+
convert_data.setDisplayName('Convert Units')
|
|
92
|
+
convert_data.setDescription('Convert Units in Metered Data')
|
|
93
|
+
convert_data.setDefaultValue('None')
|
|
94
|
+
args << convert_data
|
|
95
|
+
|
|
96
|
+
csv_var_dn = OpenStudio::Measure::OSArgument.makeStringArgument('csv_var_dn', true)
|
|
97
|
+
csv_var_dn.setDisplayName('CSV variable display name')
|
|
98
|
+
csv_var_dn.setDescription('CSV variable display name. Not yet Implemented')
|
|
99
|
+
csv_var_dn.setDefaultValue('')
|
|
100
|
+
args << csv_var_dn
|
|
101
|
+
|
|
102
|
+
years = OpenStudio::Measure::OSArgument.makeBoolArgument('year', true)
|
|
103
|
+
years.setDisplayName('Year in csv data timestamp')
|
|
104
|
+
years.setDescription('Is the Year in the csv data timestamp => mm:dd:yy or mm:dd (true/false)')
|
|
105
|
+
years.setDefaultValue(true)
|
|
106
|
+
args << years
|
|
107
|
+
|
|
108
|
+
seconds = OpenStudio::Measure::OSArgument.makeBoolArgument('seconds', true)
|
|
109
|
+
seconds.setDisplayName('Seconds in csv data timestamp')
|
|
110
|
+
seconds.setDescription('Is the Seconds in the csv data timestamp => hh:mm:ss or hh:mm (true/false)')
|
|
111
|
+
seconds.setDefaultValue(true)
|
|
112
|
+
args << seconds
|
|
113
|
+
|
|
114
|
+
sql_key = OpenStudio::Measure::OSArgument.makeStringArgument('key_value', true)
|
|
115
|
+
sql_key.setDisplayName('SQL key value')
|
|
116
|
+
sql_key.setDescription('SQL key value for the SQL query to find the variable in the SQL file')
|
|
117
|
+
sql_key.setDefaultValue('')
|
|
118
|
+
args << sql_key
|
|
119
|
+
|
|
120
|
+
sql_var = OpenStudio::Measure::OSArgument.makeStringArgument('timeseries_name', true)
|
|
121
|
+
sql_var.setDisplayName('TimeSeries Name')
|
|
122
|
+
sql_var.setDescription('TimeSeries Name for the SQL query to find the variable in the SQL file')
|
|
123
|
+
sql_var.setDefaultValue('Facility Total Electric Demand Power')
|
|
124
|
+
args << sql_var
|
|
125
|
+
|
|
126
|
+
reportfreq_chs = OpenStudio::StringVector.new
|
|
127
|
+
reportfreq_chs << 'Detailed'
|
|
128
|
+
reportfreq_chs << 'Timestep'
|
|
129
|
+
reportfreq_chs << 'Hourly'
|
|
130
|
+
reportfreq_chs << 'Daily'
|
|
131
|
+
reportfreq_chs << 'Monthly'
|
|
132
|
+
reportfreq_chs << 'RunPeriod'
|
|
133
|
+
reporting_frequency = OpenStudio::Measure::OSArgument.makeChoiceArgument('reporting_frequency', reportfreq_chs, true)
|
|
134
|
+
reporting_frequency.setDisplayName('Reporting Frequency')
|
|
135
|
+
reporting_frequency.setDescription('Reporting Frequency for SQL Query')
|
|
136
|
+
reporting_frequency.setDefaultValue('Zone Timestep')
|
|
137
|
+
args << reporting_frequency
|
|
138
|
+
|
|
139
|
+
environment_period = OpenStudio::Measure::OSArgument.makeStringArgument('environment_period', true)
|
|
140
|
+
environment_period.setDisplayName('Environment Period')
|
|
141
|
+
environment_period.setDescription('Environment Period for SQL query')
|
|
142
|
+
environment_period.setDefaultValue('RUN PERIOD 1')
|
|
143
|
+
args << environment_period
|
|
144
|
+
|
|
145
|
+
norm = OpenStudio::Measure::OSArgument.makeDoubleArgument('norm', true)
|
|
146
|
+
norm.setDisplayName('Norm of the difference of csv and sql')
|
|
147
|
+
norm.setDescription('Norm of the difference of csv and sql. 1 is absolute value. 2 is euclidean distance. 3 is raw difference.')
|
|
148
|
+
norm.setDefaultValue(1)
|
|
149
|
+
args << norm
|
|
150
|
+
|
|
151
|
+
scale = OpenStudio::Measure::OSArgument.makeDoubleArgument('scale', true)
|
|
152
|
+
scale.setDisplayName('Scale factor to apply to the difference')
|
|
153
|
+
scale.setDescription('Scale factor to apply to the difference (1 is no scale)')
|
|
154
|
+
scale.setDefaultValue(1)
|
|
155
|
+
args << scale
|
|
156
|
+
|
|
157
|
+
find_avail = OpenStudio::Measure::OSArgument.makeBoolArgument('find_avail', true)
|
|
158
|
+
find_avail.setDisplayName('Find Available data in the SQL file')
|
|
159
|
+
find_avail.setDescription("Will RegisterInfo all the 'EnvPeriod', 'ReportingFrequencies', 'VariableNames', 'KeyValues' in the SQL file. Useful for debugging SQL issues.")
|
|
160
|
+
find_avail.setDefaultValue(true)
|
|
161
|
+
args << find_avail
|
|
162
|
+
|
|
163
|
+
algorithm_download = OpenStudio::Measure::OSArgument.makeBoolArgument('algorithm_download', true)
|
|
164
|
+
algorithm_download.setDisplayName('algorithm_download')
|
|
165
|
+
algorithm_download.setDescription('Make JSON data available for algorithm_download (true/false)')
|
|
166
|
+
algorithm_download.setDefaultValue(false)
|
|
167
|
+
args << algorithm_download
|
|
168
|
+
|
|
169
|
+
plot_flag = OpenStudio::Measure::OSArgument.makeBoolArgument('plot_flag', true)
|
|
170
|
+
plot_flag.setDisplayName('plot_flag timeseries data')
|
|
171
|
+
plot_flag.setDescription('Create plot of timeseries data (true/false)')
|
|
172
|
+
plot_flag.setDefaultValue(true)
|
|
173
|
+
args << plot_flag
|
|
174
|
+
|
|
175
|
+
plot_name = OpenStudio::Measure::OSArgument.makeStringArgument('plot_name', true)
|
|
176
|
+
plot_name.setDisplayName('Plot name')
|
|
177
|
+
plot_name.setDescription('Name to include in reporting file name.')
|
|
178
|
+
plot_name.setDefaultValue('')
|
|
179
|
+
args << plot_name
|
|
180
|
+
|
|
181
|
+
verbose_messages = OpenStudio::Measure::OSArgument.makeBoolArgument('verbose_messages', true)
|
|
182
|
+
verbose_messages.setDisplayName('verbose_messages')
|
|
183
|
+
verbose_messages.setDescription('verbose messages. Useful for debugging but MAJOR Performance Hit.')
|
|
184
|
+
verbose_messages.setDefaultValue(false)
|
|
185
|
+
args << verbose_messages
|
|
186
|
+
|
|
187
|
+
warning_messages = OpenStudio::Measure::OSArgument.makeBoolArgument('warning_messages', true)
|
|
188
|
+
warning_messages.setDisplayName('warning_messages')
|
|
189
|
+
warning_messages.setDescription('Warn on missing data.')
|
|
190
|
+
warning_messages.setDefaultValue(true)
|
|
191
|
+
args << warning_messages
|
|
192
|
+
|
|
193
|
+
add_first_zero_for_plots = OpenStudio::Measure::OSArgument.makeBoolArgument('add_first_zero_for_plots', true)
|
|
194
|
+
add_first_zero_for_plots.setDisplayName('add_first_zero_for_plots')
|
|
195
|
+
add_first_zero_for_plots.setDescription('Add a point of zero value to the plot at the beginning of the runperiod.')
|
|
196
|
+
add_first_zero_for_plots.setDefaultValue(false)
|
|
197
|
+
args << add_first_zero_for_plots
|
|
198
|
+
|
|
199
|
+
add_last_zero_for_plots = OpenStudio::Measure::OSArgument.makeBoolArgument('add_last_zero_for_plots', true)
|
|
200
|
+
add_last_zero_for_plots.setDisplayName('add_last_zero_for_plots')
|
|
201
|
+
add_last_zero_for_plots.setDescription('Add a point of zero value to the plot at the end of the runperiod.')
|
|
202
|
+
add_last_zero_for_plots.setDefaultValue(false)
|
|
203
|
+
args << add_last_zero_for_plots
|
|
204
|
+
|
|
205
|
+
args
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# adds output requests ahead of EnergyPlus simulation
|
|
209
|
+
def energyPlusOutputRequests(runner, user_arguments)
|
|
210
|
+
super(runner, user_arguments)
|
|
211
|
+
|
|
212
|
+
result = OpenStudio::IdfObjectVector.new
|
|
213
|
+
|
|
214
|
+
# use the built-in error checking
|
|
215
|
+
return result unless runner.validateUserArguments(arguments, user_arguments)
|
|
216
|
+
|
|
217
|
+
# gather required values from user arguments
|
|
218
|
+
key = runner.getStringArgumentValue('key_value', user_arguments)
|
|
219
|
+
variable = runner.getStringArgumentValue('timeseries_name', user_arguments)
|
|
220
|
+
timestep = runner.getStringArgumentValue('reporting_frequency', user_arguments)
|
|
221
|
+
|
|
222
|
+
# add output request using values from user argument
|
|
223
|
+
if key == 'no_key' # could also look for variable.include?(":Electricity")
|
|
224
|
+
result << OpenStudio::IdfObject.load("Output:Meter,#{variable},#{timestep};").get
|
|
225
|
+
else
|
|
226
|
+
result << OpenStudio::IdfObject.load("Output:Variable,#{key},#{variable},#{timestep};").get
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
result
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# outputs for PAT
|
|
233
|
+
def outputs
|
|
234
|
+
result = OpenStudio::Measure::OSOutputVector.new
|
|
235
|
+
|
|
236
|
+
# calibration metrics
|
|
237
|
+
result << OpenStudio::Measure::OSOutput.makeDoubleOutput('diff') # kWh
|
|
238
|
+
result << OpenStudio::Measure::OSOutput.makeDoubleOutput('simdata') # kWh
|
|
239
|
+
result << OpenStudio::Measure::OSOutput.makeDoubleOutput('csvdata') # %
|
|
240
|
+
result << OpenStudio::Measure::OSOutput.makeDoubleOutput('cvrmse') # %
|
|
241
|
+
result << OpenStudio::Measure::OSOutput.makeDoubleOutput('nmbe') # kWh
|
|
242
|
+
|
|
243
|
+
result
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# define what happens when the measure is run
|
|
247
|
+
def run(runner, user_arguments)
|
|
248
|
+
super(runner, user_arguments)
|
|
249
|
+
|
|
250
|
+
# use the built-in error checking
|
|
251
|
+
return false unless runner.validateUserArguments(arguments, user_arguments)
|
|
252
|
+
|
|
253
|
+
# get the last model and sql file
|
|
254
|
+
model = runner.lastOpenStudioModel
|
|
255
|
+
if model.empty?
|
|
256
|
+
runner.registerError('Cannot find last model.')
|
|
257
|
+
return false
|
|
258
|
+
end
|
|
259
|
+
model = model.get
|
|
260
|
+
|
|
261
|
+
sqlFile = runner.lastEnergyPlusSqlFile
|
|
262
|
+
if sqlFile.empty?
|
|
263
|
+
runner.registerError('Cannot find last sql file.')
|
|
264
|
+
return false
|
|
265
|
+
end
|
|
266
|
+
sqlFile = sqlFile.get
|
|
267
|
+
model.setSqlFile(sqlFile)
|
|
268
|
+
|
|
269
|
+
# assign the user inputs to variables
|
|
270
|
+
csv_name = runner.getStringArgumentValue('csv_name', user_arguments)
|
|
271
|
+
csv_time_header = runner.getStringArgumentValue('csv_time_header', user_arguments)
|
|
272
|
+
csv_var = runner.getStringArgumentValue('csv_var', user_arguments)
|
|
273
|
+
csv_var_dn = runner.getStringArgumentValue('csv_var_dn', user_arguments)
|
|
274
|
+
years = runner.getBoolArgumentValue('year', user_arguments)
|
|
275
|
+
seconds = runner.getBoolArgumentValue('seconds', user_arguments)
|
|
276
|
+
|
|
277
|
+
sql_key = runner.getStringArgumentValue('key_value', user_arguments)
|
|
278
|
+
# PAT fails on empty string or even a space as string, even though runs fine in OS app, as hack adding "no_key" method which converts to empty string here
|
|
279
|
+
sql_key = '' if sql_key.include?('no_key')
|
|
280
|
+
|
|
281
|
+
sql_var = runner.getStringArgumentValue('timeseries_name', user_arguments)
|
|
282
|
+
norm = runner.getDoubleArgumentValue('norm', user_arguments)
|
|
283
|
+
scale = runner.getDoubleArgumentValue('scale', user_arguments)
|
|
284
|
+
find_avail = runner.getBoolArgumentValue('find_avail', user_arguments)
|
|
285
|
+
verbose_messages = runner.getBoolArgumentValue('verbose_messages', user_arguments)
|
|
286
|
+
warning_messages = runner.getBoolArgumentValue('warning_messages', user_arguments)
|
|
287
|
+
algorithm_download = runner.getBoolArgumentValue('algorithm_download', user_arguments)
|
|
288
|
+
plot_flag = runner.getBoolArgumentValue('plot_flag', user_arguments)
|
|
289
|
+
plot_name = runner.getStringArgumentValue('plot_name', user_arguments)
|
|
290
|
+
environment_period = runner.getStringArgumentValue('environment_period', user_arguments)
|
|
291
|
+
reporting_frequency = runner.getStringArgumentValue('reporting_frequency', user_arguments)
|
|
292
|
+
convert_data = runner.getStringArgumentValue('convert_data', user_arguments)
|
|
293
|
+
last_zero = runner.getBoolArgumentValue('add_last_zero_for_plots', user_arguments)
|
|
294
|
+
first_zero = runner.getBoolArgumentValue('add_first_zero_for_plots', user_arguments)
|
|
295
|
+
@name = plot_name
|
|
296
|
+
# Method to translate from OpenStudio's time formatting
|
|
297
|
+
# to Javascript time formatting
|
|
298
|
+
# OpenStudio time
|
|
299
|
+
# 2009-May-14 00:10:00 Raw string
|
|
300
|
+
# Javascript time
|
|
301
|
+
# 2009/07/12 12:34:56
|
|
302
|
+
def to_JSTime(os_time)
|
|
303
|
+
js_time = os_time.to_s
|
|
304
|
+
# Replace the '-' with '/'
|
|
305
|
+
js_time = js_time.tr('-', '/')
|
|
306
|
+
# Replace month abbreviations with numbers
|
|
307
|
+
js_time = js_time.gsub('Jan', '01')
|
|
308
|
+
js_time = js_time.gsub('Feb', '02')
|
|
309
|
+
js_time = js_time.gsub('Mar', '03')
|
|
310
|
+
js_time = js_time.gsub('Apr', '04')
|
|
311
|
+
js_time = js_time.gsub('May', '05')
|
|
312
|
+
js_time = js_time.gsub('Jun', '06')
|
|
313
|
+
js_time = js_time.gsub('Jul', '07')
|
|
314
|
+
js_time = js_time.gsub('Aug', '08')
|
|
315
|
+
js_time = js_time.gsub('Sep', '09')
|
|
316
|
+
js_time = js_time.gsub('Oct', '10')
|
|
317
|
+
js_time = js_time.gsub('Nov', '11')
|
|
318
|
+
js_time = js_time.gsub('Dec', '12')
|
|
319
|
+
|
|
320
|
+
js_time
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# setup convert
|
|
324
|
+
if convert_data == 'F to C'
|
|
325
|
+
convert = 0.5556
|
|
326
|
+
elsif convert_data == 'WH to J'
|
|
327
|
+
convert = 3600
|
|
328
|
+
elsif convert_data == 'CFM to m3/s'
|
|
329
|
+
convert = 0.00047
|
|
330
|
+
elsif convert_data == 'PSI to Pa'
|
|
331
|
+
convert = 6894.76
|
|
332
|
+
else convert_data == 'None'
|
|
333
|
+
convert = 1
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
diff = 0.0
|
|
337
|
+
simdata = 0.0
|
|
338
|
+
csvdata = 0.0
|
|
339
|
+
ySum = 0.0
|
|
340
|
+
squaredError = 0.0
|
|
341
|
+
sumError = 0.0
|
|
342
|
+
n = 0
|
|
343
|
+
cvrmse = 0
|
|
344
|
+
nmbe = 0
|
|
345
|
+
# map = {'Whole Building:Facility Total Electric Demand Power [W](TimeStep)'=>['Whole Building','Facility Total Electric Demand Power'],'OCCUPIED_TZ:Zone Mean Air Temperature [C](TimeStep)'=>['OCCUPIED_TZ','Zone Mean Air Temperature']}
|
|
346
|
+
|
|
347
|
+
map = { csv_var.to_s => { key: sql_key, var: sql_var, index: 0 } }
|
|
348
|
+
cal = { 1 => 'January', 2 => 'February', 3 => 'March', 4 => 'April', 5 => 'May', 6 => 'June', 7 => 'July', 8 => 'August', 9 => 'September', 10 => 'October', 11 => 'November', 12 => 'December' }
|
|
349
|
+
runner.registerInfo("csv_name: #{csv_name}")
|
|
350
|
+
|
|
351
|
+
csv = CSV.read(csv_name, encoding: 'ISO-8859-1')
|
|
352
|
+
# sql = OpenStudio::SqlFile.new(OpenStudio::Path.new('sim.sql'))
|
|
353
|
+
sql = sqlFile
|
|
354
|
+
# environment_period = sql.availableEnvPeriods[3]
|
|
355
|
+
runner.registerInfo("environment_period: #{environment_period}")
|
|
356
|
+
environment_periods = environment_period.split(',')
|
|
357
|
+
runner.registerInfo("environment_periods: #{environment_periods}")
|
|
358
|
+
runner.registerInfo("map: #{map}")
|
|
359
|
+
runner.registerInfo('')
|
|
360
|
+
|
|
361
|
+
if find_avail
|
|
362
|
+
ts = sql.availableTimeSeries
|
|
363
|
+
runner.registerInfo("available timeseries: #{ts}")
|
|
364
|
+
runner.registerInfo('')
|
|
365
|
+
envs = sql.availableEnvPeriods
|
|
366
|
+
envs.each do |env_s|
|
|
367
|
+
freqs = sql.availableReportingFrequencies(env_s)
|
|
368
|
+
runner.registerInfo("available EnvPeriod: #{env_s}, available ReportingFrequencies: #{freqs}")
|
|
369
|
+
freqs.each do |freq|
|
|
370
|
+
vn = sql.availableVariableNames(env_s, freq.to_s)
|
|
371
|
+
runner.registerInfo("available variable names: #{vn}")
|
|
372
|
+
vn.each do |v|
|
|
373
|
+
kv = sql.availableKeyValues(env_s, freq.to_s, v)
|
|
374
|
+
runner.registerInfo("variable names: #{v}")
|
|
375
|
+
runner.registerInfo("available key value: #{kv}")
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
runner.registerInfo("year: #{years}")
|
|
381
|
+
runner.registerInfo("seconds: #{seconds}")
|
|
382
|
+
if !years && seconds
|
|
383
|
+
# mm:dd hh:mm:ss
|
|
384
|
+
# check day time splits into two valid parts
|
|
385
|
+
if !csv[1][0].split(' ')[0].nil? && !csv[1][0].split(' ')[1].nil?
|
|
386
|
+
# check remaining splits are valid
|
|
387
|
+
if !csv[1][0].split(' ')[0].split('/')[0].nil? && !csv[1][0].split(' ')[0].split('/')[1].nil? && !csv[1][0].split(' ')[1].split(':')[0].nil? && !csv[1][0].split(' ')[1].split(':')[1].nil? && !csv[1][0].split(' ')[1].split(':')[2].nil?
|
|
388
|
+
runner.registerInfo("CSV Time format is correct: #{csv[1][0]} mm:dd hh:mm:ss")
|
|
389
|
+
else
|
|
390
|
+
runner.registerError("CSV Time format not correct: #{csv[1][0]}. Selected format is mm:dd hh:mm:ss")
|
|
391
|
+
return false
|
|
392
|
+
end
|
|
393
|
+
else
|
|
394
|
+
runner.registerError("CSV Time format not correct: #{csv[1][0]}. Does not split into 'day time'. Selected format is mm:dd hh:mm:ss")
|
|
395
|
+
return false
|
|
396
|
+
end
|
|
397
|
+
elsif !years && !seconds
|
|
398
|
+
# mm:dd hh:mm
|
|
399
|
+
# check day time splits into two valid parts
|
|
400
|
+
if !csv[1][0].split(' ')[0].nil? && !csv[1][0].split(' ')[1].nil?
|
|
401
|
+
# check remaining splits are valid
|
|
402
|
+
if !csv[1][0].split(' ')[0].split('/')[0].nil? && !csv[1][0].split(' ')[0].split('/')[1].nil? && !csv[1][0].split(' ')[1].split(':')[0].nil? && !csv[1][0].split(' ')[1].split(':')[1].nil?
|
|
403
|
+
runner.registerInfo("CSV Time format is correct: #{csv[1][0]} mm:dd hh:mm")
|
|
404
|
+
else
|
|
405
|
+
runner.registerError("CSV Time format not correct: #{csv[1][0]}. Selected format is mm:dd hh:mm")
|
|
406
|
+
return false
|
|
407
|
+
end
|
|
408
|
+
else
|
|
409
|
+
runner.registerError("CSV Time format not correct: #{csv[1][0]}. Does not split into 'day time'. Selected format is mm:dd hh:mm")
|
|
410
|
+
return false
|
|
411
|
+
end
|
|
412
|
+
elsif years && !seconds
|
|
413
|
+
# mm:dd:yy hh:mm
|
|
414
|
+
# check day time splits into two valid parts
|
|
415
|
+
if !csv[1][0].split(' ')[0].nil? && !csv[1][0].split(' ')[1].nil?
|
|
416
|
+
# check remaining splits are valid
|
|
417
|
+
if !csv[1][0].split(' ')[0].split('/')[0].nil? && !csv[1][0].split(' ')[0].split('/')[1].nil? && !csv[1][0].split(' ')[0].split('/')[2].nil? && !csv[1][0].split(' ')[1].split(':')[0].nil? && !csv[1][0].split(' ')[1].split(':')[1].nil?
|
|
418
|
+
runner.registerInfo("CSV Time format is correct: #{csv[1][0]} mm:dd:yy hh:mm")
|
|
419
|
+
else
|
|
420
|
+
runner.registerError("CSV Time format not correct: #{csv[1][0]}. Selected format is mm:dd:yy hh:mm")
|
|
421
|
+
return false
|
|
422
|
+
end
|
|
423
|
+
else
|
|
424
|
+
runner.registerError("CSV Time format not correct: #{csv[1][0]}. Does not split into 'day time'. Selected format is mm:dd:yy hh:mm")
|
|
425
|
+
return false
|
|
426
|
+
end
|
|
427
|
+
elsif years && seconds
|
|
428
|
+
# mm:dd:yy hh:mm:ss
|
|
429
|
+
# check day time splits into two valid parts
|
|
430
|
+
if !csv[1][0].split(' ')[0].nil? && !csv[1][0].split(' ')[1].nil?
|
|
431
|
+
# check remaining splits are valid
|
|
432
|
+
if !csv[1][0].split(' ')[0].split('/')[0].nil? && !csv[1][0].split(' ')[0].split('/')[1].nil? && !csv[1][0].split(' ')[0].split('/')[2].nil? && !csv[1][0].split(' ')[1].split(':')[0].nil? && !csv[1][0].split(' ')[1].split(':')[1].nil? && !csv[1][0].split(' ')[1].split(':')[2].nil?
|
|
433
|
+
runner.registerInfo("CSV Time format is correct: #{csv[1][0]} mm:dd:yy hh:mm:ss")
|
|
434
|
+
else
|
|
435
|
+
runner.registerError("CSV Time format not correct: #{csv[1][0]}. Selected format is mm:dd:yy hh:mm:ss")
|
|
436
|
+
return false
|
|
437
|
+
end
|
|
438
|
+
else
|
|
439
|
+
runner.registerError("CSV Time format not correct: #{csv[1][0]}. Does not split into 'day time'. Selected format is mm:dd:yy hh:mm:ss")
|
|
440
|
+
return false
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
temp_sim = []
|
|
445
|
+
temp_mtr = []
|
|
446
|
+
temp_norm = []
|
|
447
|
+
runner.registerInfo('Begin timeseries parsing')
|
|
448
|
+
# get timezone info
|
|
449
|
+
tzs = model.getSite.timeZone.to_s
|
|
450
|
+
runner.registerInfo("timezone = #{tzs}")
|
|
451
|
+
tz = if tzs.to_i >= 0 # positive number
|
|
452
|
+
if tzs.to_i < 10 # one digit
|
|
453
|
+
"+0#{tzs.to_i}:00"
|
|
454
|
+
else # two digit
|
|
455
|
+
"+#{tzs.to_i}:00"
|
|
456
|
+
end
|
|
457
|
+
else # negative number
|
|
458
|
+
if tzs.to_i * -1 < 10 # one digit
|
|
459
|
+
"-0#{tzs.to_i * -1}:00"
|
|
460
|
+
else # two digit
|
|
461
|
+
"-#{tzs.to_i * -1}:00"
|
|
462
|
+
end
|
|
463
|
+
end
|
|
464
|
+
runner.registerInfo("timezone = #{tz}")
|
|
465
|
+
# export for plotting
|
|
466
|
+
all_series = []
|
|
467
|
+
csv[0].each do |hdr|
|
|
468
|
+
if hdr.to_s != csv_time_header.to_s
|
|
469
|
+
unless map.key? hdr
|
|
470
|
+
runner.registerInfo("CSV hdr #{hdr} is not in map: #{map}, skipping") if verbose_messages
|
|
471
|
+
next
|
|
472
|
+
end
|
|
473
|
+
runner.registerInfo("hdr is: #{hdr}")
|
|
474
|
+
runner.registerInfo("csv_var is: #{csv_var}")
|
|
475
|
+
# next unless map.key? hdr
|
|
476
|
+
key = map[hdr][:key]
|
|
477
|
+
var = map[hdr][:var]
|
|
478
|
+
diff_index = map[hdr][:index]
|
|
479
|
+
runner.registerInfo("var: #{var}")
|
|
480
|
+
runner.registerInfo("key: #{key}")
|
|
481
|
+
|
|
482
|
+
# Store the timeseries data to hash for later
|
|
483
|
+
# export to the HTML file
|
|
484
|
+
series = {}
|
|
485
|
+
series['name'] = "#{key} Simulated"
|
|
486
|
+
series['type'] = var.to_s
|
|
487
|
+
series['color'] = 'blue'
|
|
488
|
+
data = []
|
|
489
|
+
series2 = {}
|
|
490
|
+
series2['name'] = "#{key} Metered"
|
|
491
|
+
series2['type'] = var.to_s
|
|
492
|
+
series2['color'] = 'red'
|
|
493
|
+
data2 = []
|
|
494
|
+
environment_periods.each do |environment_p|
|
|
495
|
+
runner.registerInfo("sqlcall: #{environment_p},#{reporting_frequency},#{var},#{key}")
|
|
496
|
+
if sql.timeSeries(environment_p, reporting_frequency, var, key).is_initialized
|
|
497
|
+
ser = sql.timeSeries(environment_p, reporting_frequency, var, key).get
|
|
498
|
+
else
|
|
499
|
+
runner.registerWarning("sql.timeSeries not initialized environment_p: #{environment_p},reporting_frequency: #{reporting_frequency},var: #{var},key: #{key}.")
|
|
500
|
+
next
|
|
501
|
+
end
|
|
502
|
+
date_times = ser.dateTimes
|
|
503
|
+
first_date = date_times[0]
|
|
504
|
+
last_date = date_times[-1]
|
|
505
|
+
if date_times.size >= 2
|
|
506
|
+
delta = OpenStudio::Time.new((date_times[1] - date_times[0]).days, (date_times[1] - date_times[0]).hours, (date_times[1] - date_times[0]).minutes, (date_times[1] - date_times[0]).seconds)
|
|
507
|
+
end
|
|
508
|
+
runner.registerInfo("first_date: #{first_date}") if verbose_messages
|
|
509
|
+
runner.registerInfo("last_date: #{last_date}") if verbose_messages
|
|
510
|
+
# if
|
|
511
|
+
series['units'] = ser.units
|
|
512
|
+
series2['units'] = ser.units
|
|
513
|
+
# end
|
|
514
|
+
# add 0 for plotting
|
|
515
|
+
if first_zero
|
|
516
|
+
runner.registerInfo("adding first_zero: #{first_date - delta}")
|
|
517
|
+
point = {}
|
|
518
|
+
point['y'] = 0.0
|
|
519
|
+
point['time'] = to_JSTime(first_date - delta)
|
|
520
|
+
data << point
|
|
521
|
+
point2 = {}
|
|
522
|
+
point2['y'] = 0.0
|
|
523
|
+
point2['time'] = to_JSTime(first_date - delta)
|
|
524
|
+
data2 << point2
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
csv.each_index do |row|
|
|
528
|
+
next unless row > 0
|
|
529
|
+
if csv[row][0].nil?
|
|
530
|
+
if warning_messages
|
|
531
|
+
runner.registerWarning("empty csv row number #{row}")
|
|
532
|
+
end
|
|
533
|
+
next
|
|
534
|
+
end
|
|
535
|
+
mon = csv[row][0].split(' ')[0].split('/')[0].to_i
|
|
536
|
+
day = csv[row][0].split(' ')[0].split('/')[1].to_i
|
|
537
|
+
year = unless csv[row][0].split(' ')[0].split('/')[2].nil?
|
|
538
|
+
csv[row][0].split(' ')[0].split('/')[2].to_i
|
|
539
|
+
end
|
|
540
|
+
hou = csv[row][0].split(' ')[1].split(':')[0].to_i
|
|
541
|
+
min = csv[row][0].split(' ')[1].split(':')[1].to_i
|
|
542
|
+
sec = unless csv[row][0].split(' ')[1].split(':')[2].nil?
|
|
543
|
+
csv[row][0].split(' ')[1].split(':')[2].to_i
|
|
544
|
+
end
|
|
545
|
+
if year.nil?
|
|
546
|
+
dat = OpenStudio::Date.new(OpenStudio::MonthOfYear.new(cal[mon]), day)
|
|
547
|
+
else
|
|
548
|
+
# dat = OpenStudio::Date.new(OpenStudio::MonthOfYear.new(cal[mon]),day,year)
|
|
549
|
+
# hack since year is not in the sql file correctly
|
|
550
|
+
dat = OpenStudio::Date.new(OpenStudio::MonthOfYear.new(cal[mon]), day)
|
|
551
|
+
end
|
|
552
|
+
tim = if sec.nil?
|
|
553
|
+
OpenStudio::Time.new(0, hou, min, 0)
|
|
554
|
+
else
|
|
555
|
+
OpenStudio::Time.new(0, hou, min, sec)
|
|
556
|
+
end
|
|
557
|
+
dtm = OpenStudio::DateTime.new(dat, tim)
|
|
558
|
+
unless dtm >= first_date && dtm <= last_date
|
|
559
|
+
if warning_messages
|
|
560
|
+
runner.registerWarning("CSV DateTime #{dtm} is not in SQL Timeseries Dates")
|
|
561
|
+
end
|
|
562
|
+
next
|
|
563
|
+
end
|
|
564
|
+
if year.nil?
|
|
565
|
+
etim = if sec.nil?
|
|
566
|
+
Time.new(2009, mon, day, hou, min, 0, tz).to_i * 1000
|
|
567
|
+
else
|
|
568
|
+
Time.new(2009, mon, day, hou, min, sec, tz).to_i * 1000
|
|
569
|
+
end
|
|
570
|
+
else
|
|
571
|
+
etim = if sec.nil?
|
|
572
|
+
# HACK: since year is not in the sql file correctly
|
|
573
|
+
# etim = Time.new(year, mon, day, hou, min, 0, tz).to_i * 1000
|
|
574
|
+
Time.new(2009, mon, day, hou, min, 0, tz).to_i * 1000
|
|
575
|
+
else
|
|
576
|
+
# HACK: since year is not in the sql file correctly
|
|
577
|
+
# etim = Time.new(year, mon, day, hou, min, sec, tz).to_i * 1000
|
|
578
|
+
Time.new(2009, mon, day, hou, min, sec, tz).to_i * 1000
|
|
579
|
+
end
|
|
580
|
+
end
|
|
581
|
+
runner.registerInfo("dtm: #{dtm}") if verbose_messages
|
|
582
|
+
csv[row].each_index do |col|
|
|
583
|
+
next unless col > 0
|
|
584
|
+
mtr = csv[row][col].to_s
|
|
585
|
+
# try converting
|
|
586
|
+
if convert == 0.5556 # this is a temperature
|
|
587
|
+
if mtr != 'NAN'
|
|
588
|
+
mtr = (mtr.to_f - 32) * convert
|
|
589
|
+
else
|
|
590
|
+
next
|
|
591
|
+
# mtr = 0
|
|
592
|
+
end
|
|
593
|
+
else
|
|
594
|
+
if mtr != 'NAN'
|
|
595
|
+
mtr = mtr.to_f * convert
|
|
596
|
+
else
|
|
597
|
+
next
|
|
598
|
+
# mtr = 0
|
|
599
|
+
end
|
|
600
|
+
end
|
|
601
|
+
next unless csv[0][col] == hdr
|
|
602
|
+
sim = ser.value(dtm)
|
|
603
|
+
# store timeseries for plotting
|
|
604
|
+
point = {}
|
|
605
|
+
point['y'] = sim.round(6)
|
|
606
|
+
point['time'] = to_JSTime(dtm)
|
|
607
|
+
data << point
|
|
608
|
+
point2 = {}
|
|
609
|
+
point2['y'] = mtr.to_f.round(6)
|
|
610
|
+
point2['time'] = to_JSTime(dtm)
|
|
611
|
+
data2 << point2
|
|
612
|
+
|
|
613
|
+
dif = if norm == 1
|
|
614
|
+
scale.to_f * (mtr.to_f - sim.to_f).abs
|
|
615
|
+
elsif norm == 2
|
|
616
|
+
(scale.to_f * (mtr.to_f - sim.to_f))**2
|
|
617
|
+
else
|
|
618
|
+
scale.to_f * (mtr.to_f - sim.to_f)
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
squaredError += (mtr.to_f - sim.to_f)**2
|
|
622
|
+
sumError += (mtr.to_f - sim.to_f)
|
|
623
|
+
ySum += mtr.to_f
|
|
624
|
+
n += 1
|
|
625
|
+
|
|
626
|
+
temp_sim << [etim, sim.to_f]
|
|
627
|
+
temp_mtr << [etim, mtr.to_f]
|
|
628
|
+
# temp_norm << [etim,dif.to_f]
|
|
629
|
+
diff += dif.to_f
|
|
630
|
+
simdata += sim.to_f
|
|
631
|
+
csvdata += mtr.to_f
|
|
632
|
+
runner.registerInfo("mtr value is #{mtr}") if verbose_messages
|
|
633
|
+
runner.registerInfo("sim value is #{sim}") if verbose_messages
|
|
634
|
+
runner.registerInfo("dif value is #{dif}") if verbose_messages
|
|
635
|
+
runner.registerInfo("diff value is #{diff.inspect}") if verbose_messages
|
|
636
|
+
end
|
|
637
|
+
end
|
|
638
|
+
# add 0 for plotting
|
|
639
|
+
next unless last_zero
|
|
640
|
+
runner.registerInfo("add last_zero: #{last_date + delta}")
|
|
641
|
+
point = {}
|
|
642
|
+
point['y'] = 0.0
|
|
643
|
+
point['time'] = to_JSTime(last_date + delta)
|
|
644
|
+
data << point
|
|
645
|
+
point2 = {}
|
|
646
|
+
point2['y'] = 0.0
|
|
647
|
+
point2['time'] = to_JSTime(last_date + delta)
|
|
648
|
+
data2 << point2
|
|
649
|
+
end
|
|
650
|
+
series['displayname'] = plot_name
|
|
651
|
+
series2['displayname'] = plot_name
|
|
652
|
+
series['data'] = data
|
|
653
|
+
series2['data'] = data2
|
|
654
|
+
all_series << series
|
|
655
|
+
all_series << series2
|
|
656
|
+
yBar = [ySum / n, 1e-19].max
|
|
657
|
+
cvrmse = 100.0 * Math.sqrt(squaredError / n) / yBar
|
|
658
|
+
nmbe = 100.0 * (sumError / n) / yBar
|
|
659
|
+
series['cvrmse'] = cvrmse.round(6)
|
|
660
|
+
series['nmbe'] = nmbe.round(6)
|
|
661
|
+
series2['cvrmse'] = cvrmse.round(6)
|
|
662
|
+
series2['nmbe'] = nmbe.round(6)
|
|
663
|
+
|
|
664
|
+
if algorithm_download
|
|
665
|
+
require 'csv'
|
|
666
|
+
CSV.open("timeseries#{plot_name}.csv", 'wb') do |csv|
|
|
667
|
+
csv << ['Simulation Time', 'Simulated Value', 'Metered time', 'Metered Value']
|
|
668
|
+
data.size.times do |i|
|
|
669
|
+
csv << [data[i]['time'], data[i]['y'], data2[i]['time'], data2[i]['y']]
|
|
670
|
+
end
|
|
671
|
+
end
|
|
672
|
+
end
|
|
673
|
+
|
|
674
|
+
else
|
|
675
|
+
runner.registerInfo("Found Time Header: #{csv_time_header}")
|
|
676
|
+
end
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
# results = {"metadata" => {"tz" => tzs.to_i, "variables" => {"variable" => csv_var, "variable_display_name" => csv_var_dn}}, "data_mtr" => temp_mtr, "data_sim" => temp_sim, "data_diff" => temp_norm}
|
|
680
|
+
# remove diff norm from results json
|
|
681
|
+
results = { 'metadata' => { 'tz' => tzs.to_i, 'variables' => { 'variable' => csv_var, 'variable_display_name' => csv_var_dn } }, 'data_mtr' => temp_mtr, 'data_sim' => temp_sim }
|
|
682
|
+
runner.registerInfo("Saving timeseries_#{csv_var}.json")
|
|
683
|
+
FileUtils.mkdir_p(File.dirname("timeseries_#{csv_var}.json")) unless Dir.exist?(File.dirname("timeseries_#{csv_var}.json"))
|
|
684
|
+
File.open("timeseries_#{csv_var}.json", 'wb') { |f| f << JSON.pretty_generate(results) }
|
|
685
|
+
FileUtils.mkdir_p(File.dirname("allseries_#{csv_var}.json")) unless Dir.exist?(File.dirname("allseries_#{csv_var}.json"))
|
|
686
|
+
File.open("allseries_#{csv_var}.json", 'wb') { |f| f << JSON.pretty_generate(all_series) }
|
|
687
|
+
# check if analysis directory exists on server
|
|
688
|
+
if algorithm_download
|
|
689
|
+
if File.basename(File.expand_path(File.join(Dir.pwd, '../../../'))).split('_')[0] == 'analysis'
|
|
690
|
+
runner.registerInfo("Copying timeseries_#{csv_var}.json to downloads directory")
|
|
691
|
+
directory_name = File.expand_path(File.join(Dir.pwd, '../../../downloads'))
|
|
692
|
+
Dir.mkdir(directory_name) unless File.exist?(directory_name)
|
|
693
|
+
FileUtils.cp("timeseries_#{csv_var}.json", directory_name)
|
|
694
|
+
FileUtils.cp("allseries_#{csv_var}.json", directory_name)
|
|
695
|
+
FileUtils.cp("timeseries#{plot_name}.csv", directory_name)
|
|
696
|
+
end
|
|
697
|
+
end
|
|
698
|
+
diff = Math.sqrt(diff) if norm == 2
|
|
699
|
+
|
|
700
|
+
runner.registerInfo("results: #{results}") if verbose_messages
|
|
701
|
+
runner.registerValue('diff', diff, '')
|
|
702
|
+
runner.registerValue('simdata', simdata, '')
|
|
703
|
+
runner.registerValue('csvdata', csvdata, '')
|
|
704
|
+
runner.registerValue('cvrmse', cvrmse, '')
|
|
705
|
+
runner.registerValue('nmbe', nmbe, '')
|
|
706
|
+
|
|
707
|
+
if plot_flag
|
|
708
|
+
runner.registerInfo('start plotting')
|
|
709
|
+
all_series = all_series.to_json
|
|
710
|
+
# read in template
|
|
711
|
+
html_in_path = "#{File.dirname(__FILE__)}/resources/report.html.erb"
|
|
712
|
+
html_in_path = if File.exist?(html_in_path)
|
|
713
|
+
html_in_path
|
|
714
|
+
else
|
|
715
|
+
"#{File.dirname(__FILE__)}/report.html.erb"
|
|
716
|
+
end
|
|
717
|
+
html_in = ''
|
|
718
|
+
File.open(html_in_path, 'r') do |file|
|
|
719
|
+
html_in = file.read
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
# configure template with variable values
|
|
723
|
+
renderer = ERB.new(html_in)
|
|
724
|
+
html_out = renderer.result(binding)
|
|
725
|
+
|
|
726
|
+
# write html file
|
|
727
|
+
html_out_path = if plot_name.empty?
|
|
728
|
+
"./report_#{csv_var}.html"
|
|
729
|
+
else
|
|
730
|
+
"./report_#{plot_name}.html"
|
|
731
|
+
end
|
|
732
|
+
File.open(html_out_path, 'w') do |file|
|
|
733
|
+
file << html_out
|
|
734
|
+
# make sure data is written to the disk one way or the other
|
|
735
|
+
begin
|
|
736
|
+
file.fsync
|
|
737
|
+
rescue StandardError
|
|
738
|
+
file.flush
|
|
739
|
+
end
|
|
740
|
+
end
|
|
741
|
+
end
|
|
742
|
+
sql.close
|
|
743
|
+
true
|
|
744
|
+
end
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
# register the measure to be used by the application
|
|
748
|
+
TimeseriesObjectiveFunction.new.registerWithApplication
|