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.
Files changed (218) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +29 -0
  3. data/CHANGELOG.md +14 -0
  4. data/Gemfile +20 -0
  5. data/Jenkinsfile +6 -0
  6. data/LICENSE.md +27 -0
  7. data/README.md +33 -0
  8. data/Rakefile +50 -0
  9. data/doc_templates/LICENSE.md +27 -0
  10. data/doc_templates/README.md.erb +42 -0
  11. data/doc_templates/copyright_erb.txt +36 -0
  12. data/doc_templates/copyright_js.txt +4 -0
  13. data/doc_templates/copyright_ruby.txt +34 -0
  14. data/lib/files/.gitkeep +0 -0
  15. data/lib/measures/AddMonthlyJSONUtilityData/LICENSE.md +27 -0
  16. data/lib/measures/AddMonthlyJSONUtilityData/README.md +96 -0
  17. data/lib/measures/AddMonthlyJSONUtilityData/README.md.erb +42 -0
  18. data/lib/measures/AddMonthlyJSONUtilityData/measure.rb +280 -0
  19. data/lib/measures/AddMonthlyJSONUtilityData/measure.xml +163 -0
  20. data/lib/measures/AddMonthlyUtilityData/LICENSE.md +27 -0
  21. data/lib/measures/AddMonthlyUtilityData/README.md +64 -0
  22. data/lib/measures/AddMonthlyUtilityData/README.md.erb +42 -0
  23. data/lib/measures/AddMonthlyUtilityData/measure.rb +312 -0
  24. data/lib/measures/AddMonthlyUtilityData/measure.xml +115 -0
  25. data/lib/measures/AddMonthlyUtilityData/tests/AddMonthlyUtilityData_Test.rb +88 -0
  26. data/lib/measures/AddMonthlyUtilityData/tests/electric_billed_usages.json +198 -0
  27. data/lib/measures/AddMonthlyUtilityData/tests/gas_billed_usages.json +198 -0
  28. data/lib/measures/CalibrationReports/LICENSE.md +27 -0
  29. data/lib/measures/CalibrationReports/README.md +26 -0
  30. data/lib/measures/CalibrationReports/README.md.erb +42 -0
  31. data/lib/measures/CalibrationReports/measure.rb +511 -0
  32. data/lib/measures/CalibrationReports/measure.xml +98 -0
  33. data/lib/measures/CalibrationReports/resources/report.html.in +379 -0
  34. data/lib/measures/CalibrationReports/tests/CalibrationReports_Test.rb +523 -0
  35. data/lib/measures/CalibrationReports/tests/ExampleModel.osm +10497 -0
  36. data/lib/measures/CalibrationReports/tests/ExampleModelNoDemandInput.osm +10560 -0
  37. data/lib/measures/CalibrationReports/tests/ExampleModelNoGasInput.osm +10456 -0
  38. data/lib/measures/CalibrationReports/tests/USA_CO_Golden-NREL.724666_TMY3.epw +8768 -0
  39. data/lib/measures/CalibrationReportsEnhanced/LICENSE.md +27 -0
  40. data/lib/measures/CalibrationReportsEnhanced/README.md +143 -0
  41. data/lib/measures/CalibrationReportsEnhanced/README.md.erb +42 -0
  42. data/lib/measures/CalibrationReportsEnhanced/measure.rb +798 -0
  43. data/lib/measures/CalibrationReportsEnhanced/measure.xml +372 -0
  44. data/lib/measures/CalibrationReportsEnhanced/resources/report.html.in +380 -0
  45. data/lib/measures/CalibrationReportsEnhanced/tests/CalibrationReportsEnhanced_Test.rb +734 -0
  46. data/lib/measures/CalibrationReportsEnhanced/tests/ExampleModel.osm +10497 -0
  47. data/lib/measures/CalibrationReportsEnhanced/tests/ExampleModel_FuelOil.osm +12740 -0
  48. data/lib/measures/CalibrationReportsEnhanced/tests/USA_CO_Golden-NREL.724666_TMY3.epw +8768 -0
  49. data/lib/measures/CalibrationReportsEnhanced21/LICENSE.md +27 -0
  50. data/lib/measures/CalibrationReportsEnhanced21/README.md +109 -0
  51. data/lib/measures/CalibrationReportsEnhanced21/README.md.erb +42 -0
  52. data/lib/measures/CalibrationReportsEnhanced21/measure.rb +690 -0
  53. data/lib/measures/CalibrationReportsEnhanced21/measure.xml +269 -0
  54. data/lib/measures/CalibrationReportsEnhanced21/resources/report.html.in +380 -0
  55. data/lib/measures/CoilCoolingDXSingleSpeedMultiplier/LICENSE.md +27 -0
  56. data/lib/measures/CoilCoolingDXSingleSpeedMultiplier/README.md +48 -0
  57. data/lib/measures/CoilCoolingDXSingleSpeedMultiplier/README.md.erb +42 -0
  58. data/lib/measures/CoilCoolingDXSingleSpeedMultiplier/measure.rb +237 -0
  59. data/lib/measures/CoilCoolingDXSingleSpeedMultiplier/measure.xml +93 -0
  60. data/lib/measures/CoilCoolingDXSingleSpeedPercentChange/LICENSE.md +27 -0
  61. data/lib/measures/CoilCoolingDXSingleSpeedPercentChange/README.md +48 -0
  62. data/lib/measures/CoilCoolingDXSingleSpeedPercentChange/README.md.erb +42 -0
  63. data/lib/measures/CoilCoolingDXSingleSpeedPercentChange/measure.rb +228 -0
  64. data/lib/measures/CoilCoolingDXSingleSpeedPercentChange/measure.xml +93 -0
  65. data/lib/measures/CoilCoolingDXTwoSpeedMultiplier/LICENSE.md +27 -0
  66. data/lib/measures/CoilCoolingDXTwoSpeedMultiplier/README.md +64 -0
  67. data/lib/measures/CoilCoolingDXTwoSpeedMultiplier/README.md.erb +42 -0
  68. data/lib/measures/CoilCoolingDXTwoSpeedMultiplier/measure.rb +280 -0
  69. data/lib/measures/CoilCoolingDXTwoSpeedMultiplier/measure.xml +111 -0
  70. data/lib/measures/CoilCoolingDXTwoSpeedPercentChange/LICENSE.md +27 -0
  71. data/lib/measures/CoilCoolingDXTwoSpeedPercentChange/README.md +64 -0
  72. data/lib/measures/CoilCoolingDXTwoSpeedPercentChange/README.md.erb +42 -0
  73. data/lib/measures/CoilCoolingDXTwoSpeedPercentChange/measure.rb +270 -0
  74. data/lib/measures/CoilCoolingDXTwoSpeedPercentChange/measure.xml +111 -0
  75. data/lib/measures/CoilCoolingWaterMultiplier/LICENSE.md +27 -0
  76. data/lib/measures/CoilCoolingWaterMultiplier/README.md +80 -0
  77. data/lib/measures/CoilCoolingWaterMultiplier/README.md.erb +42 -0
  78. data/lib/measures/CoilCoolingWaterMultiplier/measure.rb +324 -0
  79. data/lib/measures/CoilCoolingWaterMultiplier/measure.xml +129 -0
  80. data/lib/measures/CoilCoolingWaterPercentChange/LICENSE.md +27 -0
  81. data/lib/measures/CoilCoolingWaterPercentChange/README.md +80 -0
  82. data/lib/measures/CoilCoolingWaterPercentChange/README.md.erb +42 -0
  83. data/lib/measures/CoilCoolingWaterPercentChange/measure.rb +311 -0
  84. data/lib/measures/CoilCoolingWaterPercentChange/measure.xml +129 -0
  85. data/lib/measures/CoilHeatingElectricMultiplier/LICENSE.md +27 -0
  86. data/lib/measures/CoilHeatingElectricMultiplier/README.md +48 -0
  87. data/lib/measures/CoilHeatingElectricMultiplier/README.md.erb +42 -0
  88. data/lib/measures/CoilHeatingElectricMultiplier/measure.rb +240 -0
  89. data/lib/measures/CoilHeatingElectricMultiplier/measure.xml +93 -0
  90. data/lib/measures/CoilHeatingElectricPercentChange/LICENSE.md +27 -0
  91. data/lib/measures/CoilHeatingElectricPercentChange/README.md +48 -0
  92. data/lib/measures/CoilHeatingElectricPercentChange/README.md.erb +42 -0
  93. data/lib/measures/CoilHeatingElectricPercentChange/measure.rb +231 -0
  94. data/lib/measures/CoilHeatingElectricPercentChange/measure.xml +93 -0
  95. data/lib/measures/CoilHeatingGasMultiplier/LICENSE.md +27 -0
  96. data/lib/measures/CoilHeatingGasMultiplier/README.md +64 -0
  97. data/lib/measures/CoilHeatingGasMultiplier/README.md.erb +42 -0
  98. data/lib/measures/CoilHeatingGasMultiplier/measure.rb +282 -0
  99. data/lib/measures/CoilHeatingGasMultiplier/measure.xml +111 -0
  100. data/lib/measures/CoilHeatingGasPercentChange/LICENSE.md +27 -0
  101. data/lib/measures/CoilHeatingGasPercentChange/README.md +64 -0
  102. data/lib/measures/CoilHeatingGasPercentChange/README.md.erb +42 -0
  103. data/lib/measures/CoilHeatingGasPercentChange/measure.rb +271 -0
  104. data/lib/measures/CoilHeatingGasPercentChange/measure.xml +111 -0
  105. data/lib/measures/CoilHeatingWaterMultiplier/LICENSE.md +27 -0
  106. data/lib/measures/CoilHeatingWaterMultiplier/README.md +48 -0
  107. data/lib/measures/CoilHeatingWaterMultiplier/README.md.erb +42 -0
  108. data/lib/measures/CoilHeatingWaterMultiplier/measure.rb +235 -0
  109. data/lib/measures/CoilHeatingWaterMultiplier/measure.xml +93 -0
  110. data/lib/measures/CoilHeatingWaterPercentChange/LICENSE.md +27 -0
  111. data/lib/measures/CoilHeatingWaterPercentChange/README.md +48 -0
  112. data/lib/measures/CoilHeatingWaterPercentChange/README.md.erb +42 -0
  113. data/lib/measures/CoilHeatingWaterPercentChange/measure.rb +226 -0
  114. data/lib/measures/CoilHeatingWaterPercentChange/measure.xml +93 -0
  115. data/lib/measures/ConstructionLayerZeroMaterialProperties/LICENSE.md +27 -0
  116. data/lib/measures/ConstructionLayerZeroMaterialProperties/README.md +88 -0
  117. data/lib/measures/ConstructionLayerZeroMaterialProperties/README.md.erb +42 -0
  118. data/lib/measures/ConstructionLayerZeroMaterialProperties/measure.rb +221 -0
  119. data/lib/measures/ConstructionLayerZeroMaterialProperties/measure.xml +194 -0
  120. data/lib/measures/ElectricBaseboardEfficiencyAndCapacity/LICENSE.md +27 -0
  121. data/lib/measures/ElectricBaseboardEfficiencyAndCapacity/README.md +40 -0
  122. data/lib/measures/ElectricBaseboardEfficiencyAndCapacity/README.md.erb +42 -0
  123. data/lib/measures/ElectricBaseboardEfficiencyAndCapacity/measure.rb +102 -0
  124. data/lib/measures/ElectricBaseboardEfficiencyAndCapacity/measure.xml +78 -0
  125. data/lib/measures/ExteriorWallThermalPropertiesMultiplier/LICENSE.md +27 -0
  126. data/lib/measures/ExteriorWallThermalPropertiesMultiplier/README.md +48 -0
  127. data/lib/measures/ExteriorWallThermalPropertiesMultiplier/README.md.erb +42 -0
  128. data/lib/measures/ExteriorWallThermalPropertiesMultiplier/measure.rb +263 -0
  129. data/lib/measures/ExteriorWallThermalPropertiesMultiplier/measure.xml +97 -0
  130. data/lib/measures/ExteriorWallThermalPropertiesPercentChange/LICENSE.md +27 -0
  131. data/lib/measures/ExteriorWallThermalPropertiesPercentChange/README.md +48 -0
  132. data/lib/measures/ExteriorWallThermalPropertiesPercentChange/README.md.erb +42 -0
  133. data/lib/measures/ExteriorWallThermalPropertiesPercentChange/measure.rb +253 -0
  134. data/lib/measures/ExteriorWallThermalPropertiesPercentChange/measure.xml +97 -0
  135. data/lib/measures/FansMultiplier/LICENSE.md +27 -0
  136. data/lib/measures/FansMultiplier/README.md +64 -0
  137. data/lib/measures/FansMultiplier/README.md.erb +42 -0
  138. data/lib/measures/FansMultiplier/measure.rb +297 -0
  139. data/lib/measures/FansMultiplier/measure.xml +166 -0
  140. data/lib/measures/FansPercentChange/LICENSE.md +27 -0
  141. data/lib/measures/FansPercentChange/README.md +64 -0
  142. data/lib/measures/FansPercentChange/README.md.erb +42 -0
  143. data/lib/measures/FansPercentChange/measure.rb +286 -0
  144. data/lib/measures/FansPercentChange/measure.xml +166 -0
  145. data/lib/measures/GeneralCalibrationMeasureMultiplier/LICENSE.md +27 -0
  146. data/lib/measures/GeneralCalibrationMeasureMultiplier/README.md +112 -0
  147. data/lib/measures/GeneralCalibrationMeasureMultiplier/README.md.erb +42 -0
  148. data/lib/measures/GeneralCalibrationMeasureMultiplier/measure.rb +639 -0
  149. data/lib/measures/GeneralCalibrationMeasureMultiplier/measure.xml +229 -0
  150. data/lib/measures/GeneralCalibrationMeasurePercentChange/LICENSE.md +27 -0
  151. data/lib/measures/GeneralCalibrationMeasurePercentChange/README.md +112 -0
  152. data/lib/measures/GeneralCalibrationMeasurePercentChange/README.md.erb +42 -0
  153. data/lib/measures/GeneralCalibrationMeasurePercentChange/measure.rb +756 -0
  154. data/lib/measures/GeneralCalibrationMeasurePercentChange/measure.xml +229 -0
  155. data/lib/measures/HardSizeHvac/LICENSE.md +27 -0
  156. data/lib/measures/HardSizeHvac/README.md +26 -0
  157. data/lib/measures/HardSizeHvac/README.md.erb +42 -0
  158. data/lib/measures/HardSizeHvac/measure.rb +88 -0
  159. data/lib/measures/HardSizeHvac/measure.xml +81 -0
  160. data/lib/measures/MaalkaMonthlyJSONUtilityData/LICENSE.md +27 -0
  161. data/lib/measures/MaalkaMonthlyJSONUtilityData/README.md +104 -0
  162. data/lib/measures/MaalkaMonthlyJSONUtilityData/README.md.erb +42 -0
  163. data/lib/measures/MaalkaMonthlyJSONUtilityData/measure.rb +304 -0
  164. data/lib/measures/MaalkaMonthlyJSONUtilityData/measure.xml +216 -0
  165. data/lib/measures/RValueOfInsulationForConstructionMultiplier/LICENSE.md +27 -0
  166. data/lib/measures/RValueOfInsulationForConstructionMultiplier/README.md +40 -0
  167. data/lib/measures/RValueOfInsulationForConstructionMultiplier/README.md.erb +42 -0
  168. data/lib/measures/RValueOfInsulationForConstructionMultiplier/measure.rb +196 -0
  169. data/lib/measures/RValueOfInsulationForConstructionMultiplier/measure.xml +132 -0
  170. data/lib/measures/RValueOfInsulationForConstructionPercentageChange/LICENSE.md +27 -0
  171. data/lib/measures/RValueOfInsulationForConstructionPercentageChange/README.md +40 -0
  172. data/lib/measures/RValueOfInsulationForConstructionPercentageChange/README.md.erb +42 -0
  173. data/lib/measures/RValueOfInsulationForConstructionPercentageChange/measure.rb +189 -0
  174. data/lib/measures/RValueOfInsulationForConstructionPercentageChange/measure.xml +132 -0
  175. data/lib/measures/RoofThermalPropertiesMultiplier/LICENSE.md +27 -0
  176. data/lib/measures/RoofThermalPropertiesMultiplier/README.md +48 -0
  177. data/lib/measures/RoofThermalPropertiesMultiplier/README.md.erb +42 -0
  178. data/lib/measures/RoofThermalPropertiesMultiplier/measure.rb +263 -0
  179. data/lib/measures/RoofThermalPropertiesMultiplier/measure.xml +97 -0
  180. data/lib/measures/RoofThermalPropertiesPercentChange/LICENSE.md +27 -0
  181. data/lib/measures/RoofThermalPropertiesPercentChange/README.md +48 -0
  182. data/lib/measures/RoofThermalPropertiesPercentChange/README.md.erb +42 -0
  183. data/lib/measures/RoofThermalPropertiesPercentChange/measure.rb +253 -0
  184. data/lib/measures/RoofThermalPropertiesPercentChange/measure.xml +97 -0
  185. data/lib/measures/TimeseriesObjectiveFunction/LICENSE.md +27 -0
  186. data/lib/measures/TimeseriesObjectiveFunction/README.md +207 -0
  187. data/lib/measures/TimeseriesObjectiveFunction/README.md.erb +42 -0
  188. data/lib/measures/TimeseriesObjectiveFunction/measure.rb +748 -0
  189. data/lib/measures/TimeseriesObjectiveFunction/measure.xml +435 -0
  190. data/lib/measures/TimeseriesObjectiveFunction/resources/report.html.erb +288 -0
  191. data/lib/measures/TimeseriesPlot/LICENSE.md +27 -0
  192. data/lib/measures/TimeseriesPlot/README.md +56 -0
  193. data/lib/measures/TimeseriesPlot/README.md.erb +42 -0
  194. data/lib/measures/TimeseriesPlot/measure.rb +302 -0
  195. data/lib/measures/TimeseriesPlot/measure.xml +137 -0
  196. data/lib/measures/TimeseriesPlot/resources/report.html.erb +270 -0
  197. data/lib/measures/WaterHeaterMixedMultiplier/LICENSE.md +27 -0
  198. data/lib/measures/WaterHeaterMixedMultiplier/README.md +64 -0
  199. data/lib/measures/WaterHeaterMixedMultiplier/README.md.erb +42 -0
  200. data/lib/measures/WaterHeaterMixedMultiplier/measure.rb +255 -0
  201. data/lib/measures/WaterHeaterMixedMultiplier/measure.xml +180 -0
  202. data/lib/measures/WaterHeaterMixedPercentChange/LICENSE.md +27 -0
  203. data/lib/measures/WaterHeaterMixedPercentChange/README.md +64 -0
  204. data/lib/measures/WaterHeaterMixedPercentChange/README.md.erb +42 -0
  205. data/lib/measures/WaterHeaterMixedPercentChange/measure.rb +245 -0
  206. data/lib/measures/WaterHeaterMixedPercentChange/measure.xml +180 -0
  207. data/lib/measures/zone_report/LICENSE.md +27 -0
  208. data/lib/measures/zone_report/README.md +26 -0
  209. data/lib/measures/zone_report/README.md.erb +42 -0
  210. data/lib/measures/zone_report/measure.rb +706 -0
  211. data/lib/measures/zone_report/measure.xml +67 -0
  212. data/lib/measures/zone_report/resources/report.html.in +342 -0
  213. data/lib/openstudio-calibration-measures.rb +36 -0
  214. data/lib/openstudio/calibration_measures.rb +37 -0
  215. data/lib/openstudio/calibration_measures/extension.rb +49 -0
  216. data/lib/openstudio/calibration_measures/version.rb +40 -0
  217. data/openstudio-calibration.gemspec +30 -0
  218. 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