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.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 52

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:



45
46
47
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 45

def column_names
  @column_names
end

#first_report_datetimeObject

:nodoc:



45
46
47
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 45

def first_report_datetime
  @first_report_datetime
end

#pathObject

:nodoc:



45
46
47
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 45

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.



244
245
246
247
248
249
250
251
252
253
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
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 244

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.



100
101
102
103
104
105
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 100

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.



198
199
200
201
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 198

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

#load_dataObject

Loads data from the CSV file.



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 171

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



82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 82

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.



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 145

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).



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

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).



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 209

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.



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 123

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