1+ import json
2+ from enum import Enum
3+ from typing import Optional , Tuple
4+
5+ import pandas as pd
6+
7+ from wetterdienst import Kind , Period , Provider , Resolution
8+ from wetterdienst .core .timeseries .request import TimeseriesRequest
9+ from wetterdienst .core .timeseries .values import TimeseriesValues
10+ from wetterdienst .metadata .columns import Columns
11+ from wetterdienst .metadata .datarange import DataRange
12+ from wetterdienst .metadata .period import PeriodType
13+ from wetterdienst .metadata .resolution import ResolutionType
14+ from wetterdienst .metadata .timezone import Timezone
15+ from wetterdienst .metadata .unit import UnitEnum , OriginUnit , SIUnit
16+ from wetterdienst .util .cache import CacheExpiry
17+ from wetterdienst .util .network import download_file
18+ from wetterdienst .util .parameter import DatasetTreeCore
19+
20+
21+ class NoaaTCParameter (DatasetTreeCore ):
22+ class DYNAMIC (Enum ):
23+ WATER_LEVEL = "water_level"
24+
25+
26+ class NoaaTCUnit (DatasetTreeCore ):
27+ class DYNAMIC (UnitEnum ):
28+ WATER_LEVEL = OriginUnit .METER .value , SIUnit .METER .value
29+
30+
31+ class NoaaTCResolution (Enum ):
32+ DYNAMIC = Resolution .DYNAMIC .value
33+
34+
35+
36+
37+ class NoaaTCValues (TimeseriesValues ):
38+ _data_tz = Timezone .DYNAMIC
39+
40+ _endpoint = (
41+ "https://api.tidesandcurrents.noaa.gov/api/prod/datagetter?station={station_id}&product={parameter}&"
42+ "begin_date={start_date}&end_date={end_date}&datum=navd&units=metric&time_zone=gmt&"
43+ "application=wetterdienst/https://github.com/earthobservations/wetterdienst&format=json"
44+ )
45+
46+ def _collect_station_parameter (self , station_id : str , parameter : Enum , dataset : Enum ) -> pd .DataFrame :
47+ url = self ._endpoint .format (
48+ station_id = station_id , parameter = parameter .value , start_date = self .sr .start_date .isoformat (), end_date = self .sr .end_date .isoformat ()
49+ )
50+
51+ payload = download_file (url , CacheExpiry .FIVE_MINUTES )
52+
53+ df = pd .DataFrame .from_records (json .load (payload )["data" ])
54+
55+ print (df )
56+
57+
58+ class NoaaTCRequest (TimeseriesRequest ):
59+ _values = NoaaTCValues
60+ _tz = Timezone .USA
61+ _parameter_base = NoaaTCParameter
62+ _unit_base = NoaaTCUnit
63+ _has_tidy_data = True
64+ _has_datasets = False
65+ _data_range = DataRange .FIXED
66+ _period_base = Period .HISTORICAL
67+ _period_type = PeriodType .FIXED
68+ _resolution_type = ResolutionType .DYNAMIC
69+ _resolution_base = NoaaTCResolution
70+ _kind = Kind .OBSERVATION
71+ _provider = Provider .NOAA
72+ _endpoint = "https://api.tidesandcurrents.noaa.gov/mdapi/prod/webapi/stations.json?units=metric"
73+
74+ def __init__ (self , parameter , start_date , end_date ):
75+ super (NoaaTCRequest , self ).__init__ (
76+ parameter = parameter ,
77+ resolution = Resolution .DYNAMIC ,
78+ period = Period .HISTORICAL ,
79+ start_date = start_date ,
80+ end_date = end_date ,
81+ )
82+
83+ def _all (self ) -> pd .DataFrame :
84+ def _extract_ortho_msl (url ):
85+ payload = download_file (url , self .settings , CacheExpiry .METAINDEX )
86+
87+ datum_dict = json .load (payload )
88+
89+ datum_msl = None
90+ if datum_dict ["datums" ]:
91+ datum_msl = [datum for datum in datum_dict ["datums" ] if datum ["name" ] == "MSL" ]
92+
93+ datum_msl = datum_msl and datum_msl [0 ]["value" ] or None
94+
95+ return datum_dict ["OrthometricDatum" ], datum_msl
96+
97+ payload = download_file (self ._endpoint , self .settings , CacheExpiry .METAINDEX )
98+
99+ df = pd .DataFrame .from_records (json .load (payload )["stations" ])
100+
101+ df = df .loc [:, ["id" , "name" , "state" , "lat" , "lng" , "datums" ]]
102+
103+ df .loc [:, ["orthodatum" , "msl" ]] = df .pop ("datums" ).map (lambda x : x ["self" ]).map (_extract_ortho_msl ).tolist ()
104+
105+ df = df .loc [df .loc [:, "orthodatum" ] == "NAVD88" , :]
106+
107+ return df .rename (
108+ columns = {
109+ "id" : Columns .STATION_ID .value ,
110+ "name" : Columns .NAME .value ,
111+ "state" : Columns .STATE .value ,
112+ "lat" : Columns .LATITUDE .value ,
113+ "lng" : Columns .LONGITUDE .value ,
114+ }
115+ )
116+
117+
118+ if __name__ == "__main__" :
119+ request = NoaaTCRequest (parameter = "water_level" , start_date = "1970-01-01" , end_date = "1970-01-02" ).all ()
120+ print (request .df )
121+ values = next (request .values .query ())
122+ print (values .df )
0 commit comments