Skip to content

Instantly share code, notes, and snippets.

@eidge
Created June 27, 2016 12:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eidge/0bc450350b9eaeaccc64e09f4c0bf3ac to your computer and use it in GitHub Desktop.
Save eidge/0bc450350b9eaeaccc64e09f4c0bf3ac to your computer and use it in GitHub Desktop.
defmodule Weather.NOAA.Forecast.PathBuilder do
@moduledoc """
Contains helper functions to build paths for retrieving NOAA forecasts.
"""
use Timex
alias Weather.NOAA.Forecast.Params
@nomads_url "http://nomads.ncep.noaa.gov/cgi-bin/"
@gfs_models [
gfs_0p25_hourly: [
name: "filter_gfs_0p25_1hr",
precision: "0p25",
],
gfs_0p25: [
name: "filter_gfs_0p25",
precision: "0p25",
],
gfs_1p00: [
name: "filter_gfs_1p00",
precision: "1p00",
]
]
@doc """
Returns the path for the directory listing of a given model.
Args:
- model_name - One of [:gfs_0p25_hourly, :gfs_0p25, :gfs_1p00], atom
"""
def directory_path_for(model_name) when is_atom(model_name) do
model = Keyword.fetch! @gfs_models, model_name
@nomads_url <> model[:name] <> ".pl"
end
@doc """
Builds a path to retrive a forecast based on the model name.
Args:
- params - %Weather.NOAA.ForecastParams
"""
def path_for(%Params{} = params) do
model = Keyword.fetch! @gfs_models, params.model_name
@nomads_url <>
"#{model[:name]}.pl?file=#{file_name(model, params.cycle, params.hour_delta)}" <>
variables_query <>
"&#{bounding_box_query_str(params.bounding_box)}" <>
"&dir=#{dir_name(params.date, params.cycle)}"
end
defp file_name(model, cycle, hour_delta) do
formatted_hour_delta = format_hour_delta(hour_delta)
formatted_cycle = format_cycle(cycle)
"gfs.t#{formatted_cycle}z.pgrb2.#{model[:precision]}.#{formatted_hour_delta}"
end
defp format_hour_delta(nil), do: "anl"
defp format_hour_delta("anl"), do: "anl"
defp format_hour_delta(hour_delta) when hour_delta < 10, do: "f00#{hour_delta}"
defp format_hour_delta(hour_delta) when hour_delta < 100, do: "f0#{hour_delta}"
defp format_hour_delta(hour_delta) when hour_delta < 1000, do: "f#{hour_delta}"
defp format_cycle(nil), do: format_cycle(0)
defp format_cycle(cycle) when cycle < 10, do: "0#{cycle}"
defp format_cycle(cycle) when cycle < 24, do: "#{cycle}"
defp variables_query do
"&lev_1000_mb=on&lev_100_mb=on&lev_150_mb=on&lev_200_mb=on&lev_250_mb=on&lev_300_mb=on" <>
"&lev_350_mb=on&lev_400_mb=on&lev_450_mb=on&lev_500_mb=on&lev_550_mb=on&lev_600_mb=on" <>
"&lev_650_mb=on&lev_700_mb=on&lev_750_mb=on&lev_800_mb=on&lev_850_mb=on&lev_900_mb=on" <>
"&lev_925_mb=on&lev_950_mb=on&lev_975_mb=on&lev_high_cloud_layer=on" <>
"&lev_low_cloud_layer=on&lev_mean_sea_level=on&lev_middle_cloud_layer=on&lev_surface=on" <>
"&var_CAPE=on&var_CIN=on&var_DPT=on&var_GUST=on&var_HGT=on&var_HPBL=on&var_PRES=on" <>
"&var_PRMSL=on&var_RH=on&var_TCDC=on&var_TMP=on&var_UGRD=on&var_VGRD=on&lev_2_m_above_ground=on"
end
defp bounding_box_query_str(bounding_box) do
"leftlon=#{bounding_box.left_longitude}" <>
"&rightlon=#{bounding_box.right_longitude}" <>
"&toplat=#{bounding_box.top_latitude}" <>
"&bottomlat=#{bounding_box.bottom_latitude}"
end
defp dir_name(date, cycle) do
"%2Fgfs.#{format_date(date)}#{format_cycle(cycle)}"
end
defp format_date(date) do
Timex.format!(date, "{YYYY}{0M}{D}")
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment