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

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

Overview

TimeseriesCSV include timesries results 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.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 27

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 results 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:



20
21
22
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 20

def column_names
  @column_names
end

#first_report_datetimeObject

:nodoc:



20
21
22
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 20

def first_report_datetime
  @first_report_datetime
end

#pathObject

:nodoc:



20
21
22
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 20

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.



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
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
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 219

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.



75
76
77
78
79
80
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 75

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.



173
174
175
176
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 173

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

#load_dataObject

Loads data from the CSV file.



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

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



57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 57

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.



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

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



88
89
90
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 88

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



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 184

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.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/urbanopt/reporting/default_reports/timeseries_csv.rb', line 98

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