Module: Cdss::Climate

Includes:
Utils
Included in:
Client
Defined in:
lib/cdss/climate.rb

Overview

Provides methods for accessing climate data from the CDSS API.

This module includes functionality for retrieving climate stations, frost dates, and time series data at various time scales.

Instance Method Summary collapse

Methods included from Utils

#batch_dates, #build_query, #fetch_paginated_data, #format_date, #format_query_param, #parse_timestamp, #safe_float, #safe_integer

Instance Method Details

#get_climate_frost_dates(station_number:, start_date: nil, end_date: nil) ⇒ Array<Reading>

Fetches frost dates for a specific climate station.

Parameters:

  • station_number (String)

    Station number to fetch frost dates for.

  • start_date (Date, nil) (defaults to: nil)

    Start date for frost dates data.

  • end_date (Date, nil) (defaults to: nil)

    End date for frost dates data.

Returns:

  • (Array<Reading>)

    Array of frost date readings.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/cdss/climate.rb', line 60

def get_climate_frost_dates(station_number:, start_date: nil, end_date: nil)
  query_params = {
    dateFormat: "spaceSepToSeconds",
    stationNum: station_number
  }

  query_params[:"min-calYear"] = start_date.strftime("%Y") if start_date
  query_params[:"max-calYear"] = end_date.strftime("%Y") if end_date

  fetch_paginated_data(
    endpoint: "/climatedata/climatestationfrostdates/",
    query: query_params
  ) { |data| Parser.parse_climate_readings(data, type: :frost_dates) }
end

#get_climate_stations(aoi: nil, radius: nil, county: nil, division: nil, station_name: nil, site_id: nil, water_district: nil) ⇒ Array<Station>

Fetches climate stations based on various filtering criteria.

Examples:

Fetch stations in Denver county

get_climate_stations(county: 'Denver')

Parameters:

  • aoi (Hash, Array, nil) (defaults to: nil)

    Area of interest for spatial searches. If hash, must contain :latitude and :longitude keys. If array, must contain [longitude, latitude].

  • radius (Integer, nil) (defaults to: nil)

    Radius in miles for spatial search around aoi. Defaults to 20 if aoi is provided.

  • county (String, nil) (defaults to: nil)

    County name to filter stations.

  • division (Integer, nil) (defaults to: nil)

    Water division number to filter stations.

  • station_name (String, nil) (defaults to: nil)

    Name of the station to filter by.

  • site_id (String, nil) (defaults to: nil)

    Station site ID to filter by.

  • water_district (Integer, nil) (defaults to: nil)

    Water district number to filter stations.

Returns:

  • (Array<Station>)

    Array of matching climate station objects.

Raises:

  • (ArgumentError)

    If aoi parameter is provided but invalid.



25
26
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/cdss/climate.rb', line 25

def get_climate_stations(aoi: nil, radius: nil, county: nil, division: nil, station_name: nil, site_id: nil,
                         water_district: nil)
  query_params = {
    dateFormat: "spaceSepToSeconds",
    units: "miles",
    county: county,
    division: division,
    stationName: station_name,
    siteId: site_id,
    waterDistrict: water_district
  }

  if aoi
    if aoi.is_a?(Hash) && aoi[:latitude] && aoi[:longitude]
      query_params.merge!(longitude: aoi[:longitude], latitude: aoi[:latitude])
    elsif aoi.is_a?(Array) && aoi.count == 2
      query_params.merge!(longitude: aoi[0], latitude: aoi[1])
    else
      raise ArgumentError, "Invalid 'aoi' parameter"
    end
    query_params[:radius] = radius || 20
  end

  fetch_paginated_data(
    endpoint: "/climatedata/climatestations/",
    query: query_params
  ) { |data| Parser.parse_climate_stations(data) }
end

#get_climate_ts(station_number: nil, site_id: nil, param: nil, start_date: nil, end_date: nil, timescale: "day") ⇒ Array<Reading>

Fetches climate time series data for specified stations.

Parameters:

  • station_number (String, nil) (defaults to: nil)

    Station number

  • site_id (String, nil) (defaults to: nil)

    Site ID

  • param (String) (defaults to: nil)

    Climate parameter to retrieve (Evap, FrostDate, MaxTemp, etc.)

  • start_date (Date, nil) (defaults to: nil)

    Start date for time series data

  • end_date (Date, nil) (defaults to: nil)

    End date for time series data

  • timescale (String) (defaults to: "day")

    Time interval for data aggregation (‘day’ or ‘month’). Defaults to ‘day’

Returns:

  • (Array<Reading>)

    Array of time series reading objects

Raises:

  • (ArgumentError)

    If an invalid parameter or timescale is provided



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/cdss/climate.rb', line 135

def get_climate_ts(station_number: nil, site_id: nil, param: nil, start_date: nil, end_date: nil, timescale: "day")
  valid_params = %w[Evap FrostDate MaxTemp MeanTemp MinTemp Precip Snow SnowDepth SnowSWE Solar VP Wind]
  raise ArgumentError, "Invalid parameter: '#{param}'. Valid values are: #{valid_params.join(', ')}" unless valid_params.include?(param)

  day_formats = %w[day days daily d]
  month_formats = %w[month months monthly mon m]
  timescale = timescale.to_s.downcase

  case timescale
  when *day_formats
    get_climate_ts_day(station_number: station_number, site_id: site_id, param: param,
                       start_date: start_date, end_date: end_date)
  when *month_formats
    get_climate_ts_month(station_number: station_number, site_id: site_id, param: param,
                         start_date: start_date, end_date: end_date)
  else
    raise ArgumentError, "Invalid timescale: '#{timescale}'. Use 'day' or 'month'."
  end
end

#get_climate_ts_day(param:, station_number: nil, site_id: nil, start_date: nil, end_date: nil) ⇒ Array<Reading>

Fetches daily climate time series data.

Parameters:

  • param (String)

    Climate parameter type to retrieve

  • station_number (String, nil) (defaults to: nil)

    Station number

  • site_id (String, nil) (defaults to: nil)

    Site ID

  • start_date (Date, nil) (defaults to: nil)

    Start date for time series data

  • end_date (Date, nil) (defaults to: nil)

    End date for time series data

Returns:

  • (Array<Reading>)

    Array of daily climate readings



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/cdss/climate.rb', line 83

def get_climate_ts_day(param:, station_number: nil, site_id: nil, start_date: nil, end_date: nil)
  query_params = {
    dateFormat: "spaceSepToSeconds",
    measType: param,
    stationNum: station_number,
    siteId: site_id
  }

  query_params[:"min-measDate"] = start_date.strftime("%m-%d-%Y") if start_date
  query_params[:"max-measDate"] = end_date.strftime("%m-%d-%Y") if end_date

  fetch_paginated_data(
    endpoint: "/climatedata/climatestationtsday/",
    query: query_params
  ) { |data| Parser.parse_climate_readings(data, type: :daily) }
end

#get_climate_ts_month(param:, station_number: nil, site_id: nil, start_date: nil, end_date: nil) ⇒ Array<Reading>

Fetches monthly climate time series data.

Parameters:

  • param (String)

    Climate parameter type to retrieve

  • station_number (String, nil) (defaults to: nil)

    Station number

  • site_id (String, nil) (defaults to: nil)

    Site ID

  • start_date (Date, nil) (defaults to: nil)

    Start date for time series data

  • end_date (Date, nil) (defaults to: nil)

    End date for time series data

Returns:

  • (Array<Reading>)

    Array of monthly climate readings



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/cdss/climate.rb', line 108

def get_climate_ts_month(param:, station_number: nil, site_id: nil, start_date: nil, end_date: nil)
  query_params = {
    dateFormat: "spaceSepToSeconds",
    measType: param,
    stationNum: station_number,
    siteId: site_id
  }

  query_params[:"min-calYear"] = start_date.strftime("%Y") if start_date
  query_params[:"max-calYear"] = end_date.strftime("%Y") if end_date

  fetch_paginated_data(
    endpoint: "/climatedata/climatestationtsmonth/",
    query: query_params
  ) { |data| Parser.parse_climate_readings(data, type: :monthly) }
end