Class: URBANopt::Reporting::DefaultReports::TimeseriesCSV

Inherits:
Object
  • Object
show all
Defined in:
lib/urbanopt/reporting/default_reports/timeseries_csv.rb

Overview

TimeseriesCSV include timesries reults reported in a CSV file.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hash = {}) ⇒ TimeseriesCSV

TimeseriesCSV class initializes timeseries csv attributes: :path , :first_report_datetime , :column_names

hash - Hash - A hash which may contain a deserialized timeseries_csv.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 62

def initialize(hash = {})
  hash.delete_if { |k, v| v.nil? }
  hash = defaults.merge(hash)

  @run_dir = ''

  @path = hash[:path]
  @first_report_datetime = hash[:first_report_datetime]

  # from scenario csv shema get required reults to be aggregated
  @required_column_names = load_scenario_csv_schema_headers

  @column_names = hash[:column_names]
  @column_names.delete_if { |x| !@required_column_names.include? x.split('(')[0] }

  # hash of column_name to array of values, does not get serialized to hash
  @mutex = Mutex.new
  @data = nil

  # initialize class variables @@validator and @@schema
  @@validator ||= Validator.new
  @@schema ||= @@validator.schema

  # initialize @@logger
  @@logger ||= URBANopt::Reporting::DefaultReports.logger
end

Instance Attribute Details

#column_namesObject

:nodoc:



55
56
57
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 55

def column_names
  @column_names
end

#first_report_datetimeObject

:nodoc:



55
56
57
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 55

def first_report_datetime
  @first_report_datetime
end

#pathObject

:nodoc:



55
56
57
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 55

def path
  @path
end

Instance Method Details

#add_timeseries_csv(other) ⇒ Object

Merges timeseries csv to each other.

  • initialize first_report_datetime with the incoming first_report_datetime if its nil.

  • checks if first_report_datetime are identical.

  • merge the column names

  • merge the column data

parameters:

other - TimeseriesCSV - An object of TimeseriesCSV class.



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 254

def add_timeseries_csv(other)
  # initialize first_report_datetime with the incoming first_report_datetime if its nil.
  if @first_report_datetime.nil? || @first_report_datetime == ''
    @first_report_datetime = other.first_report_datetime
  end

  # checks if first_report_datetime are identical.
  if @first_report_datetime != other.first_report_datetime
    raise "first_report_datetime '#{@first_report_datetime}' does not match other.first_report_datetime '#{other.first_report_datetime}'"
  end

  # merge the column names
  other_column_names = []
  other.column_names.each do |n|
    if !n[0, 4].casecmp('ZONE').zero?
      other_column_names << n
    end
  end

  @column_names = @column_names.concat(other_column_names).uniq

  # merge the column data
  other.column_names.each do |column_name|
    if !column_name[0, 4].casecmp('ZONE').zero?
      if !@column_names.include? column_name
        @column_names.push column_name
      end

      new_values = other.get_data(column_name)

      if @data.nil?
        @data = {}
      end

      current_values = @data[column_name]

      if current_values
        if current_values.size != new_values.size
          raise 'Values of different sizes in add_timeseries_csv'
        end
        new_values.each_with_index do |value, i|
          # aggregate all columns except Datime column
          if column_name != 'Datetime'
            new_values[i] = value.to_f + current_values[i].to_f
          end
        end
        @data[column_name] = new_values
      else
        @data[column_name] = new_values
      end
    end
  end
end

#defaultsObject

Assigns default values if values does not exist.



110
111
112
113
114
115
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 110

def defaults
  hash = {}
  hash[:path] = nil
  hash[:column_names] = []
  return hash
end

#get_data(column_name) ⇒ Object

Gets data for each column name in the CSV file.

parameters:

column_name - String - The header of each column in the CSV file.



208
209
210
211
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 208

def get_data(column_name)
  load_data
  return @data[column_name].clone
end

#load_dataObject

Loads data from the CSV file.



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 181

def load_data
  @mutex.synchronize do
    if @data.nil?
      @data = {}
      @column_names = []
      CSV.foreach(@path) do |row|
        if @column_names.empty?
          @column_names = row
          @column_names.each do |column_name|
            @data[column_name] = []
          end
        else
          row.each_with_index do |value, i|
            @data[@column_names[i]] << value
          end
        end
      end
    end
  end
end

#load_scenario_csv_schema_headersObject

load required scenario report csv headers from reports schema



92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 92

def load_scenario_csv_schema_headers
  # rubocop: disable Security/Open
  scenario_csv_schema = open(File.expand_path('../default_reports/schema/scenario_csv_columns.txt', File.dirname(__FILE__)))
  # rubocop: enable Security/Open

  scenario_csv_schema_headers = []
  File.readlines(scenario_csv_schema).each do |line|
    l = line.delete("\n")
    a = l.delete("\t")
    r = a.delete("\r")
    scenario_csv_schema_headers << r
  end
  return scenario_csv_schema_headers
end

#reload_data(new_data) ⇒ Object

Reloads data from the CSV file.



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 155

def reload_data(new_data)
  @mutex.synchronize do
    @data = {}
    @column_names = []
    new_data.each do |row|
      if @column_names.empty?
        @column_names = row
        @column_names.each do |column_name|
          @data[column_name] = []
        end
      else
        row.each_with_index do |value, i|
          if i == 0
            @data[@column_names[i]] << value
          else
            @data[@column_names[i]] << value.to_f
          end
        end
      end
    end
  end
end

#run_dir_name(name) ⇒ Object

Gets run directory.

parameters:

name - String - The name of the scenario (directory_name).



123
124
125
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 123

def run_dir_name(name)
  @run_dir = name
end

#save_data(path = nil) ⇒ Object

Saves data to the the scenario report CSV file.

parameters:

path - String - The path of the scenario report CSV (default_scenario_report.csv).



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 219

def save_data(path = nil)
  if path.nil?
    path = @path
  end

  File.open(path, 'w') do |f|
    f.puts @column_names.join(',')
    n = @data[@column_names[0]].size - 1

    (0..n).each do |i|
      line = []
      @column_names.each do |column_name|
        line << @data[column_name][i]
      end
      f.puts line.join(',')
    end
    begin
      f.fsync
    rescue StandardError
      f.flush
    end
  end
end

#to_hashObject

Converts to a Hash equivalent for JSON serialization.

  • Exclude attributes with nil values.

  • Validate reporting_period hash properties against schema.



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 133

def to_hash
  result = {}
  directory_path = Pathname.new File.expand_path(@run_dir.to_s, File.dirname(__FILE__)) if @run_dir
  csv_path = Pathname.new @path if @path

  relative_path = csv_path.to_s.sub(directory_path.to_s, '')

  result[:path] = relative_path if @path
  result[:first_report_datetime] = @first_report_datetime if @first_report_datetime
  result[:column_names] = @column_names if @column_names

  # validate timeseries_csv properties against schema
  if @@validator.validate(@@schema[:definitions][:TimeseriesCSV][:properties], result).any?
    raise "scenario_report properties does not match schema: #{@@validator.validate(@@schema[:definitions][:TimeseriesCSV][:properties], result)}"
  end

  return result
end