User:Wakebrdkid/National Climatic Data Center

Article

Tests

BeginPackage["Wikicode`NationalClimaticDataCenter`"]

StationsNearest::usage = "StationsNearest[{lat,lon}] finds the weather \
station closest to the given geocoordinates."

ISDFetch::usage = "ISDFetch[{usaf,wban,___},year] imports the ISD file \
corresponding to the given station (as returned by functions like \
StationsNearest) and year."

Begin["`Private`"]

(*Format specification:ftp://ftp.ncdc.noaa.gov/pub/data/ish/ish-\
format-document.pdf*)(*Examples:Import[isdfile,"ISD"] \
Import[isdfile,"ISD","Properties""{"Date","Time","Latitude",\
"Longitude","WindType"}]*)
ISDImport[f_, options___] := Module[{s, res}, s = OpenRead[f];
   res = ReadList[s, String];
   Close[s];
   ISDParse[res, options]];

(*Additional data is not parsed,just returned in string form*)

$ISDBaseProperties = 
  Thread[{"USAF", "WBAN", "Date", "Time", "Source", "Latitude", 
     "Longitude", "ReportType", "Elevation", "CallLetter", 
     "QualityControl", "WindAngle", "WindDirection", "WindType", 
     "WindSpeed", "WindSpeedQuality", "CeilingHeight", 
     "CeilingQuality", "CeilingDetermination", "CAVOK", 
     "VisibilityDistance", "VisibilityQuality", 
     "VisibilityVariability", "VisibilityVariabilityQuality", 
     "Temperature", "TemperatureQuality", "DewPoint", 
     "DewPointQuality", "Pressure", "PressureQuality", 
     "Additional"} -> {(*{1,
     4},*){5, 10}, {11, 15}, {16, 23}, {24, 27}, {28, 28}, {29, 
      34}, {35, 41}, {42, 46}, {47, 51}, {52, 56}, {57, 60}, {61, 
      63}, {64, 64}, {65, 65}, {66, 69}, {70, 70}, {71, 75}, {76, 
      76}, {77, 77}, {78, 78}, {79, 84}, {85, 85}, {86, 86}, {87, 
      87}, {88, 92}, {93, 93}, {94, 98}, {99, 99}, {100, 104}, {105, 
      105}, {106, -1}}];

$ISDStationProperties = {"USAF" -> {1, 6}, "WBAN" -> {8, 12}, 
   "Name" -> {14, 42}, "Country" -> {44, 48}, "State" -> {50, 51}, 
   "CallSign" -> {53, 57}, "Latitude" -> {59, 64}, 
   "Longitude" -> {66, 72}, "Elevation" -> {74, 82}, 
   "StartDate" -> {84, 91}, "EndDate" -> {93, 100}};

Options[ISDParse] = {"Properties" :> $ISDBaseProperties[[All, 1]]};
ISDParse[records_List, opts : OptionsPattern[]] := 
 Module[{header = 
    SortBy[Intersection[$ISDBaseProperties[[All, 1]], 
      OptionValue["Properties"]], First[# /. $ISDBaseProperties] &], 
   data, nameToPos, p, m = Missing["NotAvailable"]}, 
  nameToPos = 
   Append[Thread[
     header -> Range[Length[header]]], _String :> (## &[])];
  data = StringTake[records, header /. $ISDBaseProperties];
  p = {"Date"} /. nameToPos;
  p != {} && (p = p[[1]];
    data[[All, p]] = 
     ToExpression@
      StringTake[data[[All, p]], {{1, 4}, {5, 6}, {7, 8}}]);
  p = {"Time"} /. nameToPos;
  p != {} && (p = p[[1]];
    data[[All, p]] = 
     ToExpression@StringTake[data[[All, p]], {{1, 2}, {3, 4}}]);
  p = {"Latitude", "Longitude"} /. nameToPos;
  p != {} && (data[[All, p]] = ToExpression@data[[All, p]]/1000.);
  p = {"Elevation"} /. nameToPos;
  p != {} && (data[[All, p]] = 
     ToExpression@data[[All, p]] /. {9999 -> m});
  p = {"WindAngle"} /. nameToPos;
  p != {} && (data[[All, p]] = 
     ToExpression@data[[All, p]] /. {999 -> m});
  p = {"Temperature", "DewPoint", "WindSpeed"} /. nameToPos;
  p != {} && (data[[All, p]] = 
     ToExpression@data[[All, p]]/10. /. {999.9 -> m});
  p = {"CeilingHeight"} /. nameToPos;
  p != {} && (data[[All, p]] = 
     ToExpression@data[[All, p]] /. {99999 -> m});
  p = {"CAVOK"} /. nameToPos;
  p != {} && (data[[All, p]] = 
     data[[All, p]] /. {"N" -> False, "Y" -> True, "9" -> m});
  p = {"VisibilityDistance"} /. nameToPos;
  p != {} && (data[[All, p]] = 
     ToExpression@data[[All, p]] /. {999999 -> m});
  p = {"VisibilityVariability"} /. nameToPos;
  p != {} && (data[[All, p]] = 
     data[[All, p]] /. {"N" -> False, "V" -> True, "9" -> m});
  p = {"Pressure"} /. nameToPos;
  p != {} && (data[[All, p]] = 
     ToExpression@data[[All, p]]/10. /. {9999.9 -> m});
  Thread[header -> Transpose[data]]]

ImportExport`RegisterImport["ISD", ISDImport]

stations = 
  Module[{m = 
     Missing["NotAvailable"]}, {# /. "999999" -> m, #2 /. 
         "99999" -> m, StringTrim@#3 /. "" -> m, 
        StringSplit@#4 /. {} -> m, StringTrim@#5 /. "" -> m, 
        StringTrim@#6 /. "" -> m, 
        If[#7 == "-99999", m, ToExpression@#7/1000.], 
        If[#8 == "-999999", m, ToExpression@#8/1000.], 
        If[StringTrim@#9 == "-99999", m, ToExpression@#9/10.], 
        If[#10 == "NO DATA ", m, DateList[#10][[;; 3]]], 
        If[#11 == "NO DATA ", m, DateList[#11][[;; 3]]]} & @@ 
      StringTake[#, $ISDStationProperties[[All, 2]]] & /@ 
    Select[ReadList[
      StringToStream[
       Import["http://www1.ncdc.noaa.gov/pub/data/inventories/ISH-\
HISTORY.TXT"]], String], StringLength@# == 100 &]];

StationsNearest = 
  Nearest[#[[7 ;; 8]] -> # & /@ 
    Cases[stations, {__, _Real, _Real, _, _, _}], 
   DistanceFunction -> GeoDistance];

ISDFetch[{usaf_, wban_, ___}, year_] := 
 Module[{m = Missing@"NotAvailable"}, 
  Import["ftp://ftp.ncdc.noaa.gov/pub/data/noaa/" <> ToString@year <> 
    "/" <> If[usaf === m, "999999", usaf] <> "-" <> 
    If[wban === m, "99999", wban] <> "-" <> ToString@year <> ".gz", 
   "ISD"]]

End[]
EndPackage[]