Class: Forecaster::Forecast

Inherits:
Object
  • Object
show all
Defined in:
lib/forecaster/forecast.rb

Instance Method Summary collapse

Constructor Details

#initialize(year, month, day, hour_of_run, hour_of_forecast) ⇒ Forecast

Returns a new instance of Forecast.



5
6
7
8
9
10
11
# File 'lib/forecaster/forecast.rb', line 5

def initialize(year, month, day, hour_of_run, hour_of_forecast)
  @year = year
  @month = month
  @day = day
  @hour_of_run = hour_of_run
  @hour_of_forecast = hour_of_forecast
end

Instance Method Details

#dirnameObject



13
14
15
16
17
18
# File 'lib/forecaster/forecast.rb', line 13

def dirname
  subdir = "%04d%02d%02d%02d" % [
    @year, @month, @day, @hour_of_run
  ]
  File.join(Forecaster.configuration.cache_dir, subdir)
end

#fetchObject

This method will save the forecast file in the cache directory. But only the parts of the file containing the fields defined in the configuration will be downloaded.



40
41
42
43
44
45
46
47
48
49
50
51
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
78
79
# File 'lib/forecaster/forecast.rb', line 40

def fetch
  return self if fetched?

  curl = Forecaster.configuration.curl_path

  FileUtils.mkpath(File.join(dirname))

  path = File.join(dirname, filename)

  # puts "Downloading '#{url}.idx' ..."
  cmd = "#{curl} -fsS -o #{path}.idx #{url}.idx"
  raise "Download of '#{url}.idx' failed" unless system(cmd)

  lines = IO.readlines("#{path}.idx")
  n = lines.count
  ranges = lines.each_index.reduce([]) do |r, i|
    records = Forecaster.configuration.records
    if records.values.any? { |record| lines[i].include?(record) }
      first = lines[i].split(":")[1].to_i
      last = ""

      j = i
      while (j += 1) < n
        last = lines[j].split(":")[1].to_i - 1
        break if last != first - 1
      end

      r << "#{first}-#{last}" # cURL syntax for a range
    else
      r
    end
  end
  system("rm #{path}.idx")

  # puts "Downloading '#{url}' ..."
  cmd = "#{curl} -fsS -r #{ranges.join(",")} -o #{path} #{url}"
  raise "Download of '#{url}' failed" unless system(cmd)

  self
end

#fetched?Boolean

Returns:

  • (Boolean)


33
34
35
# File 'lib/forecaster/forecast.rb', line 33

def fetched?
  File.exist?(File.join(dirname, filename))
end

#filenameObject



20
21
22
23
24
# File 'lib/forecaster/forecast.rb', line 20

def filename
  "gfs.t%02dz.pgrb2.0p25.f%03d" % [
    @hour_of_run, @hour_of_forecast
  ]
end

#read(field, latitude: 0.0, longitude: 0.0) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/forecaster/forecast.rb', line 81

def read(field, latitude: 0.0, longitude: 0.0)
  wgrib2 = Forecaster.configuration.wgrib2_path
  record = Forecaster.configuration.records[field]
  path = File.join(dirname, filename)

  raise "'#{path}' not found" unless File.exists?(path)

  coords = "#{longitude} #{latitude}"
  output = `#{wgrib2} #{path} -lon #{coords} -match "#{record}"`

  raise "Could not read '#{record}' in '#{path}'" if output.empty?

  fields = output.split("\n").first.split(":")
  params = Hash[*fields.last.split(",").map { |s| s.split("=") }.flatten]

  params["val"]
end

#urlObject



26
27
28
29
30
31
# File 'lib/forecaster/forecast.rb', line 26

def url
  server = Forecaster.configuration.server
  "%s/gfs.%04d%02d%02d%02d/%s" % [
    server, @year, @month, @day, @hour_of_run, filename
  ]
end