mpcaHydro 2.0.3__tar.gz → 2.0.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mpcaHydro
3
- Version: 2.0.3
3
+ Version: 2.0.4
4
4
  Summary: Python package for downloading MPCA hydrology data
5
5
  Project-URL: Homepage, https://github.com/mfratkin1/mpcaHydro
6
6
  Author-email: Mulu Fratkin <michael.fratkin@state.mn.us>
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
5
5
  [project]
6
6
  name = "mpcaHydro"
7
7
  urls = { "Homepage" = "https://github.com/mfratkin1/mpcaHydro" } # ? Add this!
8
- version = "2.0.3"
8
+ version = "2.0.4"
9
9
  dependencies = [
10
10
  "pandas",
11
11
  "requests",
@@ -27,3 +27,12 @@ classifiers = [
27
27
  "Development Status :: 3 - Alpha",
28
28
  "Programming Language :: Python"
29
29
  ]
30
+
31
+ [tool.pixi.workspace]
32
+ channels = ["conda-forge"]
33
+ platforms = ["win-64"]
34
+
35
+ [tool.pixi.pypi-dependencies]
36
+ mpcaHydro = { path = ".", editable = true }
37
+
38
+ [tool.pixi.tasks]
@@ -71,22 +71,19 @@ class Service():
71
71
  self._url = url
72
72
  return url
73
73
 
74
-
75
- def df(self,args_dict):
76
-
74
+ def get_json(self,args_dict):
77
75
  # Download request
78
- # print('Downloading')
79
76
  response = requests.get(self.url(args_dict))
80
-
81
77
  response.raise_for_status() # raises exception when not a 2xx response
82
-
83
-
84
-
85
78
  if response.status_code != 200:
86
79
  print('Error: ' + response.json()['message'])
87
80
  return 1
81
+ return response.json()
82
+
83
+ def df(self,args_dict):
88
84
 
89
- get_requests = response.json()
85
+
86
+ get_requests = self.get_json(args_dict)
90
87
  # Convert to dataframe
91
88
  if args_dict['request'] in ['getTimeseriesValues']:
92
89
  dfs = []
@@ -164,7 +161,8 @@ class pyWISK():
164
161
  start_date = '1996-01-01',
165
162
  end_date = '2050-12-31',
166
163
  stationgroup_id = None,
167
- timezone = 'GMT-6'):
164
+ timezone = 'GMT-6',
165
+ as_json = False):
168
166
 
169
167
  if ts_ids is None:
170
168
  print('Determing Timeseries IDs')
@@ -192,9 +190,12 @@ class pyWISK():
192
190
  'timezone':timezone,
193
191
  'ca_sta_returnfields': ['stn_HUC12','stn_EQuIS_ID']}
194
192
 
195
- df = self.service.get(args)
193
+ if as_json:
194
+ output = self.service.get_json(args)
195
+ else:
196
+ output = self.service.get(args)
196
197
  #print('Done!')
197
- return df
198
+ return output
198
199
 
199
200
  def get_stations(self,
200
201
  huc_id = None,
@@ -0,0 +1,88 @@
1
+ CAS_RN,CHEMICAL_NAME,PARAMETER,constituent
2
+ BOD,"Biochemical oxygen demand, standard conditions",Biochemical Oxygen Demand,BOD
3
+ BOD,"Biochemical oxygen demand, standard conditions",Biochemical Oxygen Demand (BOD),BOD
4
+ BOD,"Biochemical oxygen demand, standard conditions","Biochemical oxygen demand, standard conditions",BOD
5
+ 479-61-8,Chlorophyll a,Chlorophyll a,CHLA
6
+ 479-61-8,Chlorophyll a,Chlorophyll A,CHLA
7
+ CHLA-CORR,"Chlorophyll a, corrected for pheophytin",Chlorophyll A,CHLA
8
+ CHLA-CORR,"Chlorophyll a, corrected for pheophytin",Chlorophyll-A,CHLA
9
+ CHLA-CORR,"Chlorophyll a, corrected for pheophytin",Chlorophyll,CHLA
10
+ CHLA-CORR,"Chlorophyll a, corrected for pheophytin","Chlorophyll a, pheophytin-adjusted",CHLA
11
+ CHLA-CORR,"Chlorophyll a, corrected for pheophytin","Chlorophyll a, corrected for pheophytin",CHLA
12
+ CHLA-CORR,"Chlorophyll a, corrected for pheophytin","Chlorophyll-a, Pheophytin Corrected",CHLA
13
+ CHLA-CORR,"Chlorophyll a, corrected for pheophytin","Chlorophyll a, corrected for pheophytin - Periphyton (attached)",CHLA
14
+ CHLA-CORR,"Chlorophyll a, corrected for pheophytin",Chlorophyll a,CHLA
15
+ CHLA-C-PERI,"Chlorophyll a, corrected for pheophytin - Periphyton (attached)","Chlorophyll a, corrected for pheophytin - Periphyton (attached)",CHLA
16
+ FECAL-COLIF,Fecal Coliform,Fecal Coliform,ECOLI
17
+ NO2NO3,Inorganic nitrogen (nitrate and nitrite),Nitrate/Nitrite as N (N+N) as N,N
18
+ NO2NO3,Inorganic nitrogen (nitrate and nitrite),"Nitrate + Nitrite Nitrogen, Dissolved as N",N
19
+ NO2NO3,Inorganic nitrogen (nitrate and nitrite),Nitrate/Nitrite as N as N,N
20
+ NO2NO3,Inorganic nitrogen (nitrate and nitrite),"Nitrogen, NO2 plus NO3 as N",N
21
+ NO2NO3,Inorganic nitrogen (nitrate and nitrite),N+N as N,N
22
+ NO2NO3,Inorganic nitrogen (nitrate and nitrite),Nitrate/Nitrite as N,N
23
+ NO2NO3,Inorganic nitrogen (nitrate and nitrite),Inorganic nitrogen (nitrate and nitrite) as N,N
24
+ NO2NO3,Inorganic nitrogen (nitrate and nitrite),"Nitrate + Nitrite Nitrogen, Total",N
25
+ NO2NO3,Inorganic nitrogen (nitrate and nitrite),"Nitrate + Nitrite Nitrogen, Total as N",N
26
+ NO2NO3,Inorganic nitrogen (nitrate and nitrite),Nitrate+Nitrite Nitrogen as N,N
27
+ NO2NO3,Inorganic nitrogen (nitrate and nitrite),Inorganic nitrogen (nitrate and nitrate) as N,N
28
+ NO2NO3,Inorganic nitrogen (nitrate and nitrite),Nitrate+Nitrite as N,N
29
+ 14797-55-8,Nitrate,"Nitrogen, nitrate, as NO3 as N",NO3
30
+ 14797-55-8,Nitrate,Nitrate as N as N,NO3
31
+ 14797-55-8,Nitrate,Nitrate-N as N,NO3
32
+ 14797-55-8,Nitrate,"Nitrogen, nitrate, as N as N",NO3
33
+ 14797-55-8,Nitrate,Nitrate as N,NO3
34
+ 14797-65-0,Nitrite,"Nitrogen, nitrite, as N as N",NO2
35
+ 14797-65-0,Nitrite,Nitrite as N,NO2
36
+ 14797-65-0,Nitrite,Nitrite as N as N,NO2
37
+ 14797-65-0,Nitrite,Nitrite-N as N,NO2
38
+ 14797-65-0,Nitrite,"Nitrogen, nitrite, as NO2 as N",NO2
39
+ 14265-44-2,Orthophosphate,"Orthophosphate, as P as P",OP
40
+ 14265-44-2,Orthophosphate,Orthophosphate as P as P,OP
41
+ 14265-44-2,Orthophosphate,"Orthophosphate as P, Dissolved as P",OP
42
+ 14265-44-2,Orthophosphate,Orthophosphate as P (LF) as P,OP
43
+ 14265-44-2,Orthophosphate,phosphate-P as P,OP
44
+ 14265-44-2,Orthophosphate,"Orthophosphate Phosphorus, Total as P",OP
45
+ 14265-44-2,Orthophosphate,"Orthophosphate Phosphorus, Dissolved as P",OP
46
+ 14265-44-2,Orthophosphate,"Ortho Phosphorus, Dissolved as P",OP
47
+ 14265-44-2,Orthophosphate,Orthophosphate as P,OP
48
+ 14265-44-2,Orthophosphate,Ortho Phosphorus as P,OP
49
+ 14265-44-2,Orthophosphate,"Phosphorus, Soluble Ortho as P",OP
50
+ 14265-44-2,Orthophosphate,Orthophosphate as P (FF) as P,OP
51
+ 14265-44-2,Orthophosphate,Phosphorus as P,OP
52
+ SSC,Suspended Sediment Concentration (SSC),Suspended Sediment Concentration (SSC),SSC
53
+ SOLIDS-TDS,Total dissolved solids,Residue - filterable (TDS),TDS
54
+ SOLIDS-TDS,Total dissolved solids,Total dissolved solids (TDS),TDS
55
+ SOLIDS-TDS,Total dissolved solids,"Solids, Total Dissolved",TDS
56
+ SOLIDS-TDS,Total dissolved solids,Total dissolved solids,TDS
57
+ SOLIDS-TDS,Total dissolved solids,Total Dissolved Solids,TDS
58
+ N-KJEL,Kjeldahl nitrogen,"Kjeldahl Nitrogen, Total as N",TKN
59
+ N-KJEL,Kjeldahl nitrogen,Total Kjeldahl Nitrogen as N,TKN
60
+ N-KJEL,Kjeldahl nitrogen,TKN as N,TKN
61
+ N-KJEL,Kjeldahl nitrogen,"Nitrogen, Total Kjeldahl (TKN) as N",TKN
62
+ N-KJEL,Kjeldahl nitrogen,"Nitrogen, Total Kjeldahl as N",TKN
63
+ N-KJEL,Kjeldahl nitrogen,Kjeldahl nitrogen as N,TKN
64
+ PHOSPHATE-P,Phosphate-phosphorus,Phosphate-phosphorus as P,TP
65
+ 7723-14-0,Phosphorus,Orthophosphate as P,TP
66
+ 7723-14-0,Phosphorus,"Phosphorus, Total as P",TP
67
+ 7723-14-0,Phosphorus,"Phosphorus, Total as P as P",TP
68
+ 7723-14-0,Phosphorus,"Phosphorus, Total Dissolved, as P (FF) as P",TP
69
+ 7723-14-0,Phosphorus,Total Diss Phosphorus as P,TP
70
+ 7723-14-0,Phosphorus,"Phosphorus, Dissolved as P",TP
71
+ 7723-14-0,Phosphorus,"Phosphorus, Total Dissolved, as P (LF) as P",TP
72
+ 7723-14-0,Phosphorus,Total Phosphorus as P,TP
73
+ 7723-14-0,Phosphorus,total phosphorus as P,TP
74
+ 7723-14-0,Phosphorus,Phosphorus as P,TP
75
+ 7723-14-0,Phosphorus,"Phosphorus, Total",TP
76
+ SOLIDS-TS,Total solids,Total solids,TS
77
+ SOLIDS-TS,Total solids,Total Solids,TS
78
+ SOLIDS-TSS,Total suspended solids,"Solids, Total Suspended",TSS
79
+ SOLIDS-TSS,Total suspended solids,Total Suspended Solids in Water,TSS
80
+ SOLIDS-TSS,Total suspended solids,Total suspended solids,TSS
81
+ SOLIDS-TSS,Total suspended solids,Residue - nonfilterable (TSS),TSS
82
+ SOLIDS-TSS,Total suspended solids,total suspended solids,TSS
83
+ SOLIDS-TSS,Total suspended solids,"Solids, Suspended",TSS
84
+ SOLIDS-TSS,Total suspended solids,Total Suspended Solids,TSS
85
+ TEMP-W,"Temperature, water","Temperature, water",WT
86
+ TEMP-W,"Temperature, water","Temperature, field",WT
87
+ TEMP-W,"Temperature, water","Temperature, Water",WT
88
+ TEMP-W,"Temperature, water",Field Temperature,WT
@@ -285,12 +285,7 @@ class dataManager():
285
285
  try:
286
286
  df = self.data[station_id]
287
287
  except:
288
- df = pd.read_csv(self.folderpath.joinpath(station_id + '.csv'),
289
- index_col='datetime',
290
- parse_dates=['datetime'],
291
- #usecols=['Ts Date','Station number','variable', 'value','reach_id'],
292
- dtype={'station_id': str, 'value': float, 'variable': str,'constituent':str,'unit':str})
293
- self.data[station_id] = df
288
+ self._load(station_id)
294
289
  return df
295
290
 
296
291
  def info(self,constituent):
@@ -6,41 +6,15 @@ Created on Tue Oct 10 14:13:23 2023
6
6
  """
7
7
 
8
8
  import pandas as pd
9
+ from pathlib import Path
9
10
  #from hspf_tools.orm.models import Station
10
11
  # import geopandas as gpd
11
12
 
13
+ EQUIS_PARAMETER_XREF = pd.read_csv(Path(__file__).parent/'data/EQUIS_PARAMETER_XREF.csv')
12
14
 
13
15
 
14
-
15
-
16
- CONSTITUENT_MAP = {'Total suspended solids':'TSS',
17
- 'Total solids': 'TSS',
18
- 'Solids, Suspended' : 'TSS',
19
- 'Solids, Total Suspended' : 'TSS',
20
- 'Residue - nonfilterable (TSS)': 'TSS',
21
- 'Kjeldahl nitrogen as N': 'TKN',
22
- 'Inorganic nitrogen (nitrate and nitrate) as N': 'N',
23
- 'Nitrogen, Total Kjeldahl (TKN) as N': 'TKN',
24
- 'Nitrate + Nitrite Nitrogen, Total as N': 'N',
25
- 'Nitrate/Nitrite as N (N+N) as N': 'N',
26
- 'Nutrient-nitrogen as N': 'N',
27
- 'Nitrate/Nitrite as N': 'N',
28
- 'Phosphorus, Total as P as P':'TP',
29
- 'Phosphorus, Total as P' : 'TP',
30
- 'Phosphorus as P': 'TP',
31
- 'Total Phosphorus as P': 'TP',
32
- 'Orthophosphate as P': 'OP',
33
- 'Carbonaceous biochemical oxygen demand, standard conditions': 'BOD',
34
- 'Chemical oxygen demand':'BOD',
35
- 'Biochemical oxygen demand, standard conditions': 'BOD',
36
- 'Chlorophyll a, corrected for pheophytin':'CHLA',
37
- 'Chlorophyll-A':'CHLA',
38
- 'Chlorophyll-a, Pheophytin Corrected':'CHLA',
39
- 'Flow':'Q',
40
- 'Temperature, water': 'WT',
41
- 'Dissolved oxygen': 'DO',
42
- 'Dissolved oxygen (DO)': 'DO',
43
- 'Suspended Sediment Concentration': 'SSC'}
16
+ CONSTITUENT_MAP = {i[0]:i[1] for i in EQUIS_PARAMETER_XREF[['PARAMETER','constituent']].values}
17
+
44
18
 
45
19
  # station_no = 'S010-822'
46
20
  # data = download(station_no)
@@ -164,6 +138,14 @@ def transform(df):
164
138
  return df
165
139
 
166
140
  def load(df,file_path):
141
+ '''
142
+ date, time, value, variable, unit, station_id, station_name, constituent, source, data_format, data_type, quality_code,
143
+
144
+
145
+
146
+ '''
147
+
148
+
167
149
  df.to_csv(file_path)
168
150
 
169
151
 
@@ -152,7 +152,60 @@ VALID_CONSTITUENTS = ['Q','WT','OP','DO','TP','TSS','N','TKN']
152
152
  # latitude = station_info.iloc[0]['station_latitude'],
153
153
  # longitude = station_info.iloc[0]['station_longitude'],
154
154
  # station_type = 'River')
155
+
156
+
157
+ def extract(station_nos, constituent, dbpath, start_year = 1996, end_year = 2030, wplmn = False):
158
+ '''
159
+ given a list of station_nos, download all data relevent to HSPF from MPCA WISKI and store in a duckdb database
160
+
161
+ 1. Find relevent timeseries ids for each constituent
162
+ 2. Download data for each timeseries id
163
+ 3. Store data in duckdb database
164
+
165
+ '''
166
+ #1. Find relevent timeseries ids for each constituent
167
+ if station_nos[0] == 'E':
168
+ ts_names = TS_NAME_SELECTOR[constituent]['External']
169
+ else:
170
+ ts_names =TS_NAME_SELECTOR[constituent]['Internal']
171
+
172
+ if wplmn:
173
+ constituent_nos = CONSTITUENT_NAME_NO_WPLMN[constituent]
174
+ else:
175
+ constituent_nos = CONSTITUENT_NAME_NO[constituent]
155
176
 
177
+ ts_ids = wiski.get_ts_ids(station_nos = station_nos,
178
+ stationparameter_no = constituent_nos,
179
+ ts_name = ts_names['unit'])
180
+
181
+ jsons = []
182
+ for ts_id in ts_ids:
183
+ jsons.append(download_chunk(ts_id,start_year,end_year,as_json = True))
184
+ time.sleep(.1)
185
+ return jsons
186
+
187
+
188
+ # with duckdb.connect(db_path) as con:
189
+ # con.execute("DROP TABLE IF EXISTS observations")
190
+ # datafiles = folderpath.joinpath('*.csv').as_posix()
191
+ # query = '''
192
+ # CREATE TABLE observations AS SELECT *
193
+ # FROM
194
+ # read_csv_auto(?,
195
+ # union_by_name = true);
196
+
197
+ # '''
198
+ # con.execute(query,[datafiles])
199
+
200
+
201
+ # con = duckdb.connect(database=db_path))
202
+ # print('Downloading Timeseries Data')
203
+ # df = pd.concat([_download(constituent,station_nos,start_year,end_year,raw = True, wplmn = False) for constituent in VALID_CONSTITUENTS])
204
+ # df.to_csv(filepath,index = False)
205
+ # print('Timeseries Data Downloaded!')
206
+
207
+
208
+
156
209
 
157
210
  def info(station_nos):
158
211
  ts_ids = wiski.get_ts_ids(station_nos = station_nos,
@@ -263,14 +316,14 @@ def _download(constituent,station_nos,start_year = 1996,end_year = 2030, raw = F
263
316
  return df
264
317
 
265
318
 
266
- def download_chunk(ts_id,start_year = 1996,end_year = 2030, interval = 5):
319
+ def download_chunk(ts_id,start_year = 1996,end_year = 2030, interval = 5, as_json = False):
267
320
  frames = [pd.DataFrame()]
268
321
 
269
322
  for start in range(start_year,end_year,interval):
270
323
  end = int(start + interval-1)
271
324
  if end > end_year:
272
325
  end = end_year
273
- df = wiski.get_ts(ts_id,start_date = f'{start}-01-01',end_date = f'{end}-12-31')
326
+ df = wiski.get_ts(ts_id,start_date = f'{start}-01-01',end_date = f'{end}-12-31',as_json = as_json)
274
327
  if not df.empty: frames.append(df)
275
328
  df.index = pd.to_datetime(df['Timestamp'])
276
329
  time.sleep(.1)
File without changes
@@ -1,25 +0,0 @@
1
- [workspace]
2
- channels = ["https://prefix.dev/conda-forge"]
3
- platforms = ["linux-64", "osx-64", "win-64"]
4
-
5
-
6
- [dependencies]
7
- requests = "*"
8
- pandas = "*"
9
- time = "*"
10
- pathlib = "*"
11
- spyder = "*"
12
- jupyter = "*"
13
-
14
- [package]
15
- name = "mpcaHydro"
16
- version = "0.1.0"
17
-
18
- [package.build]
19
- backend = { name = "pixi-build-python", version = "0.1.*" }
20
-
21
- [package.run-dependencies]
22
- requests = "*"
23
- pandas = "*"
24
- time = "*"
25
- pathlib = "*"
File without changes
File without changes
File without changes