class URBANopt::Reporting::DefaultReports::TimeseriesCSV

TimeseriesCSV include timesries reults reported in a CSV file.

Public Class Methods

new(hash = {}) click to toggle source

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

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

# 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 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

Public Instance Methods

add_timeseries_csv(other) click to toggle source

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.

# 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
defaults() click to toggle source

Assigns default values if values does not exist.

# 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) click to toggle source

Gets data for each column name in the CSV file.

parameters:

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

# 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_data() click to toggle source

Loads data from the CSV file.

# 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_headers() click to toggle source

load required scenario report csv headers from reports schema

# 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) click to toggle source

Reloads data from the CSV file.

# 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) click to toggle source

Gets run directory.

parameters:

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

# File lib/urbanopt/reporting/default_reports/timeseries_csv.rb, line 88
def run_dir_name(name)
  @run_dir = name
end
save_data(path = nil) click to toggle source

Saves data to the the scenario report CSV file.

parameters:

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

# 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_hash() click to toggle source

Converts to a Hash equivalent for JSON serialization.

  • Exclude attributes with nil values.

  • Validate reporting_period hash properties against schema.

# 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