pyhcal 1.1.0__py3-none-any.whl → 1.1.1__py3-none-any.whl

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.
pyhcal/ERROR.FIL ADDED
@@ -0,0 +1,78 @@
1
+ 16:15:00.416 : LOG_MSG:ERROR.FIL OPENED
2
+ 16:15:00.417 : HASS_ENT:F90_WDBOPNR:entr:WDMSFL,RWFLG: 100 1 C:\Users\mfratki\Documents\github\pyHSPF\src\hspf\bin\WinHSPFLt\hspfmsg.wdm
3
+ 16:15:00.417 : HASS_ENT:F90_WDBOPNR:exit:WDMSFL,RETCOD 100 0
4
+ FILBLK RETCOD 0
5
+ wdmfl 0 0 0 0
6
+ FILBLK RETCOD 0
7
+ 18:06:13.144 : LOG_MSG:ERROR.FIL OPENED
8
+ 18:06:13.145 : HASS_ENT:F90_WDBOPNR:entr:WDMSFL,RWFLG: 100 1 C:\Users\mfratki\Documents\github\pyHSPF\src\hspf\bin\WinHSPFLt\hspfmsg.wdm
9
+ 18:06:13.145 : HASS_ENT:F90_WDBOPNR:exit:WDMSFL,RETCOD 100 0
10
+ FILBLK RETCOD 0
11
+ wdmfl 0 0 0 0
12
+ FILBLK RETCOD 0
13
+ 18:09:53.704 : LOG_MSG:ERROR.FIL OPENED
14
+ 18:09:53.705 : HASS_ENT:F90_WDBOPNR:entr:WDMSFL,RWFLG: 100 1 C:\Users\mfratki\Documents\github\pyHSPF\src\hspf\bin\WinHSPFLt\hspfmsg.wdm
15
+ 18:09:53.705 : HASS_ENT:F90_WDBOPNR:exit:WDMSFL,RETCOD 100 0
16
+ FILBLK RETCOD 0
17
+ wdmfl 0 0 0 0
18
+ FILBLK RETCOD 0
19
+ 18:19:02.896 : LOG_MSG:ERROR.FIL OPENED
20
+ 18:19:02.896 : HASS_ENT:F90_WDBOPNR:entr:WDMSFL,RWFLG: 100 1 C:\Users\mfratki\Documents\github\pyHSPF\src\hspf\bin\WinHSPFLt\hspfmsg.wdm
21
+ 18:19:02.896 : HASS_ENT:F90_WDBOPNR:exit:WDMSFL,RETCOD 100 0
22
+ FILBLK RETCOD 0
23
+ wdmfl 0 0 0 0
24
+ FILBLK RETCOD 0
25
+ 18:19:05.790 : LOG_MSG:ERROR.FIL OPENED
26
+ 18:19:05.790 : HASS_ENT:F90_WDBOPNR:entr:WDMSFL,RWFLG: 100 1 C:\Users\mfratki\Documents\github\pyHSPF\src\hspf\bin\WinHSPFLt\hspfmsg.wdm
27
+ 18:19:05.790 : HASS_ENT:F90_WDBOPNR:exit:WDMSFL,RETCOD 100 0
28
+ FILBLK RETCOD 0
29
+ wdmfl 0 0 0 0
30
+ FILBLK RETCOD 0
31
+ 18:32:46.775 : LOG_MSG:ERROR.FIL OPENED
32
+ 18:32:46.776 : HASS_ENT:F90_WDBOPNR:entr:WDMSFL,RWFLG: 100 1 C:\Users\mfratki\Documents\github\pyHSPF\src\hspf\bin\WinHSPFLt\hspfmsg.wdm
33
+ 18:32:46.776 : HASS_ENT:F90_WDBOPNR:exit:WDMSFL,RETCOD 100 0
34
+ FILBLK RETCOD 0
35
+ wdmfl 0 0 0 0
36
+ FILBLK RETCOD 0
37
+ 18:38:43.431 : LOG_MSG:ERROR.FIL OPENED
38
+ 18:38:43.432 : HASS_ENT:F90_WDBOPNR:entr:WDMSFL,RWFLG: 100 1 C:\Users\mfratki\Documents\github\pyHSPF\src\hspf\bin\WinHSPFLt\hspfmsg.wdm
39
+ 18:38:43.432 : HASS_ENT:F90_WDBOPNR:exit:WDMSFL,RETCOD 100 0
40
+ FILBLK RETCOD 0
41
+ wdmfl 0 0 0 0
42
+ FILBLK RETCOD 0
43
+ 18:44:23.798 : LOG_MSG:ERROR.FIL OPENED
44
+ 18:44:23.799 : HASS_ENT:F90_WDBOPNR:entr:WDMSFL,RWFLG: 100 1 C:\Users\mfratki\Documents\github\pyHSPF\src\hspf\bin\WinHSPFLt\hspfmsg.wdm
45
+ 18:44:23.800 : HASS_ENT:F90_WDBOPNR:exit:WDMSFL,RETCOD 100 0
46
+ FILBLK RETCOD 0
47
+ wdmfl 0 0 0 0
48
+ FILBLK RETCOD 0
49
+ 18:52:12.607 : LOG_MSG:ERROR.FIL OPENED
50
+ 18:52:12.608 : HASS_ENT:F90_WDBOPNR:entr:WDMSFL,RWFLG: 100 1 C:\Users\mfratki\Documents\github\pyHSPF\src\hspf\bin\WinHSPFLt\hspfmsg.wdm
51
+ 18:52:12.608 : HASS_ENT:F90_WDBOPNR:exit:WDMSFL,RETCOD 100 0
52
+ FILBLK RETCOD 0
53
+ wdmfl 0 0 0 0
54
+ FILBLK RETCOD 0
55
+ 18:59:18.608 : LOG_MSG:ERROR.FIL OPENED
56
+ 18:59:18.609 : HASS_ENT:F90_WDBOPNR:entr:WDMSFL,RWFLG: 100 1 C:\Users\mfratki\Documents\github\pyHSPF\src\hspf\bin\WinHSPFLt\hspfmsg.wdm
57
+ 18:59:18.609 : HASS_ENT:F90_WDBOPNR:exit:WDMSFL,RETCOD 100 0
58
+ FILBLK RETCOD 0
59
+ wdmfl 0 0 0 0
60
+ FILBLK RETCOD 0
61
+ 19:05:51.046 : LOG_MSG:ERROR.FIL OPENED
62
+ 19:05:51.047 : HASS_ENT:F90_WDBOPNR:entr:WDMSFL,RWFLG: 100 1 C:\Users\mfratki\Documents\github\pyHSPF\src\hspf\bin\WinHSPFLt\hspfmsg.wdm
63
+ 19:05:51.047 : HASS_ENT:F90_WDBOPNR:exit:WDMSFL,RETCOD 100 0
64
+ FILBLK RETCOD 0
65
+ wdmfl 0 0 0 0
66
+ FILBLK RETCOD 0
67
+ 19:14:05.088 : LOG_MSG:ERROR.FIL OPENED
68
+ 19:14:05.088 : HASS_ENT:F90_WDBOPNR:entr:WDMSFL,RWFLG: 100 1 C:\Users\mfratki\Documents\github\pyHSPF\src\hspf\bin\WinHSPFLt\hspfmsg.wdm
69
+ 19:14:05.089 : HASS_ENT:F90_WDBOPNR:exit:WDMSFL,RETCOD 100 0
70
+ FILBLK RETCOD 0
71
+ wdmfl 0 0 0 0
72
+ FILBLK RETCOD 0
73
+ 19:18:33.712 : LOG_MSG:ERROR.FIL OPENED
74
+ 19:18:33.713 : HASS_ENT:F90_WDBOPNR:entr:WDMSFL,RWFLG: 100 1 C:\Users\mfratki\Documents\github\pyHSPF\src\hspf\bin\WinHSPFLt\hspfmsg.wdm
75
+ 19:18:33.713 : HASS_ENT:F90_WDBOPNR:exit:WDMSFL,RETCOD 100 0
76
+ FILBLK RETCOD 0
77
+ wdmfl 0 0 0 0
78
+ FILBLK RETCOD 0
pyhcal/calibrators.py CHANGED
@@ -10,6 +10,7 @@ import subprocess
10
10
  #non-standard imports
11
11
  import pandas as pd
12
12
  import numpy as np
13
+ import geopandas as gpd
13
14
  from pathlib import Path
14
15
 
15
16
  #My packages
@@ -20,7 +21,7 @@ from mpcaHydro import data_manager as dm
20
21
  from pyhcal import metrics
21
22
  from pyhcal import figures
22
23
  from pyhcal import setup_utils
23
-
24
+ from pyhcal.mappers import Mapper
24
25
 
25
26
  def new_calibration(project_folder,model_name,download_station_data = True,run_model = True,convert_wdms = True):
26
27
  return setup_utils.create_calibration_project(model_name,project_folder,download_station_data,run_model,convert_wdms)
@@ -45,6 +46,7 @@ class calibrator:
45
46
  self.project_name = self.project_path.name
46
47
  self.model_path = self.project_path.joinpath('model')
47
48
  self.output_path = self.project_path.joinpath('output')
49
+ self.gis_path = self.project_path.joinpath('gis')
48
50
  self.run = None
49
51
  self.start_date = '1996-01-01'
50
52
  self.end_date = '2100-01-01'
@@ -58,25 +60,48 @@ class calibrator:
58
60
 
59
61
  self.MODL_DB = pd.read_csv(self.project_path.joinpath('_'.join([self.project_name ,'MODL_DB.csv'])))
60
62
 
63
+ # Alot of effort to try and include the subwatershed gdf if it exists. TODO: refactor
64
+ self.subwatershed_gdf_filepath = self.gis_path.joinpath('_'.join([self.project_name ,'Subwatersheds.shp']))
65
+ if self.subwatershed_gdf_filepath.exists():
66
+ self.subwatershed_gdf = gpd.read_file(self.subwatershed_gdf_filepath)
67
+ if 'SubID' in self.subwatershed_gdf.columns:
68
+ self.subwatershed_gdf = self.subwatershed_gdf.set_index('SubID')
69
+ else:
70
+ print("Warning: 'SubID' column not found in subwatershed shapefile. GIS operations will not function correctly.")
71
+ else:
72
+ self.subwatershed_gdf = None
73
+
61
74
  self.model = None
62
75
  self._wdms = None
63
76
  self.uci = None
64
-
77
+ self.mapper = None
65
78
  ## Input/Output methods
79
+
80
+
66
81
  def initialize(self,reach_ids,default = 4):
67
82
 
68
83
  self.uci.update_table(default,'RCHRES','BINARY-INFO',0,columns = ['HEATPR','HYDRPR','SEDPR','OXRXPR','NUTRPR','PLNKPR'],operator = 'set')
69
84
  self.uci.update_table(2,'RCHRES','BINARY-INFO',0,columns = ['HEATPR','HYDRPR','SEDPR','OXRXPR','NUTRPR','PLNKPR'],opnids = reach_ids,operator = 'set')
70
85
 
71
86
  self.uci.write(self.model.uci_file)
72
- winHSPF = str(Path(__file__).resolve().parent.parent) + '\\bin\\WinHSPFLt\\WinHspfLt.exe'
73
- subprocess.run([winHSPF,self.model.uci_file]) #, stdout=subprocess.PIPE, creationflags=0x08000000)
87
+ subprocess.run([self.model.winHSPF,self.model.uci_file]) #, stdout=subprocess.PIPE, creationflags=0x08000000)
74
88
 
75
89
  def set_dates(self, start_date = '1996-01-01',end_date ='2100-01-01'):
76
90
  self.start_date = start_date
77
91
  self.end_date = end_date
78
92
 
79
-
93
+ def _load_gdf(self,catchment_id_column = 'SubID'):
94
+ self.subwatershed_gdf_filepath = self.gis_path.joinpath('_'.join([self.project_name ,'Subwatersheds.shp']))
95
+ if self.subwatershed_gdf_filepath.exists():
96
+ self.subwatershed_gdf = gpd.read_file(self.subwatershed_gdf_filepath)
97
+ self.subwatershed_gdf = self.subwatershed_gdf.set_index(catchment_id_column)
98
+ else:
99
+ self.subwatershed_gdf = None
100
+
101
+ def _update_mapper(self):
102
+ if self.subwatershed_gdf is not None:
103
+ self.mapper = Mapper(self.project_name,self.uci,self.subwatershed_gdf,hbn = self.model.hbns)
104
+
80
105
  def load_model(self,name):
81
106
 
82
107
  if isinstance(name,int): # Default approach
@@ -98,8 +123,10 @@ class calibrator:
98
123
 
99
124
  self.model.wdms = self._wdms
100
125
  self.model.reports.wdms = self._wdms
101
- self.uci = deepcopy(self.model.uci) #uci to be manipulated
126
+ self.uci = deepcopy(self.model.uci) #uci to be manipulated
102
127
 
128
+ if self.subwatershed_gdf is not None:
129
+ self.mapper = Mapper(self.project_name,self.uci,self.subwatershed_gdf,hbn = self.model.hbns)
103
130
 
104
131
  def run_model(self,name = None,overwrite_hbn = False): # NO STATE CHANGE
105
132
 
@@ -125,7 +152,7 @@ class calibrator:
125
152
  return sim
126
153
 
127
154
  def get_observed_data(self,station_ids,constituent,time_step = 'YE',baseflow_percentage = None):
128
- obs = self.dm._get_data(station_ids,constituent,agg_period = time_step).sort_index(level = 'index')
155
+ obs = self.dm.get_station_data(station_ids,constituent,agg_period = time_step)['observed'].sort_index(level = 'index')
129
156
  obs.name = 'observed'
130
157
  return obs
131
158
 
pyhcal/mappers.py ADDED
@@ -0,0 +1,105 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Created on Mon Jan 27 11:20:47 2025
4
+
5
+ @author: mfratki
6
+ """
7
+
8
+ from pyhcal.repository import Repository
9
+ from hspf.uci import UCI
10
+ import geopandas as gpd
11
+ import matplotlib.pyplot as plt
12
+ import pandas as pd
13
+ from pathlib import Path
14
+
15
+ # Try to load statewide subwatersheds from data folder,
16
+
17
+ # try:
18
+ # SUBWATERSHEDS = gpd.read_file(str(Path(__file__).resolve().parent/'data\\statewide_subwatersheds.gpkg'))
19
+ # except:
20
+ # print("Could not load statewide subwatersheds. Please ensure the file 'statewide_subwatersheds.gpkg' is located in the 'data' folder of the pyhcal package.")
21
+
22
+
23
+
24
+ class uciMapper():
25
+ def __init__(self,model_names,gis_layer,huc6 = False):
26
+ self.mappers = []
27
+
28
+ if huc6:
29
+ model_names = Repository.HUC_DIRECTORY.loc[Repository.HUC_DIRECTORY['Repository_HUC6 Name'].isin(model_names),'Repository_HUC8 Name']
30
+ model_names = model_names.loc[model_names.isin(Repository.valid_models())].values
31
+
32
+ for model_name in model_names:
33
+ repo = Repository(model_name)
34
+ uci = UCI(repo.uci_file)
35
+ #gis_layer = SUBWATERSHEDS.loc[SUBWATERSHEDS['repo_name'] == model_name,:]
36
+ #gis_layer.set_index('SubID',inplace=True)
37
+ self.mappers.append(Mapper(model_name,uci,gis_layer))
38
+
39
+ def map_parameter(self,operation,table_name,parameter,table_id):
40
+ table = self.join_table(operation,table_name,table_id)
41
+ fig, ax = plt.subplots()
42
+ #[table.plot(column = parameter,ax = ax) for table in tables]
43
+ table.plot(column = parameter,ax = ax,cmap='viridis',legend=True)
44
+ plt.title(parameter)
45
+
46
+ def join_table(self,operation,table_name,table_id):
47
+ tables = [mapper.join_table(operation,table_name,table_id) for mapper in self.mappers]
48
+ table = pd.concat(tables)
49
+ return table
50
+
51
+ class Mapper():
52
+ def __init__(self,model_name,uci,subwatershed_gdf,hbn = None):
53
+ self.model_name = model_name
54
+ self.uci = uci
55
+ self.hbn = hbn
56
+ # if subwatershed_gdf is None:
57
+ # subwatershed_gdf = SUBWATERSHEDS.loc[SUBWATERSHEDS['repo_name'] == model_name,:]
58
+ # subwatershed_gdf.set_index('SubID',inplace=True)
59
+
60
+ self.subwatershed_gdf = subwatershed_gdf
61
+ self.subwatersheds = uci.network.subwatersheds()
62
+ self.subwatershed_ids = list(set(self.subwatersheds.index))
63
+
64
+ def map_parameter(self,operation,table_name,parameter,table_id=0,weight_by_area = True):
65
+ fig, ax = plt.subplots()
66
+ self.join_table(operation,table_name,parameter,table_id).plot(column = parameter,ax = ax,cmap='viridis',legend=True)
67
+ plt.title(parameter)
68
+
69
+ def join_table(self,operation,table_name,parameter,table_id=0,weight_by_area = True):
70
+ table = self.uci.table(operation,table_name,table_id)
71
+ subwatersheds = self.uci.network.subwatersheds()
72
+ subwatersheds = subwatersheds.loc[subwatersheds['SVOL'] == 'PERLND'].reset_index(drop=False).set_index('SVOLNO').join(table,how = 'left')
73
+ subwatersheds.index.name = 'SVOLNO' # Sometimes the index name gets dropped. I'm guessing when there are missing joins.
74
+ subwatersheds = subwatersheds.reset_index('SVOLNO').set_index(['SVOLNO','TVOLNO','SVOL','MLNO'])
75
+
76
+ #weight by area factor:
77
+ if weight_by_area:
78
+ subwatersheds['weighted_param'] = subwatersheds['AFACTR']*subwatersheds[parameter]
79
+ subwatersheds = subwatersheds.groupby(subwatersheds.index.get_level_values('TVOLNO'))['weighted_param'].sum()/subwatersheds.groupby(subwatersheds.index.get_level_values('TVOLNO'))['AFACTR'].sum()
80
+ subwatersheds.name = parameter
81
+ else:
82
+ subwatersheds = subwatersheds.groupby(subwatersheds.index.get_level_values('TVOLNO'))[parameter].mean()
83
+ subwatersheds.name = parameter
84
+ return self.subwatershed_gdf.join(subwatersheds)
85
+
86
+ def map_flag():
87
+ raise NotImplementedError()
88
+
89
+ def map_output(self,operation,output_name,t_code=5,agg_func = 'mean'):
90
+ subwatersheds = self.subwatersheds.loc[(self.subwatersheds['SVOL'] == operation),:].copy()
91
+ opnids = list(subwatersheds['SVOLNO'].unique())
92
+ output = self.hbn.get_multiple_timeseries(operation,t_code,output_name,opnids = opnids).agg(agg_func)
93
+ if operation in ['PERLND','IMPLND']:
94
+ subwatersheds = pd.merge(subwatersheds,output.to_frame(output_name),right_index = True,left_on = 'SVOLNO')
95
+ subwatersheds['area_output'] = subwatersheds['AFACTR']*subwatersheds[output_name]
96
+ subwatersheds = subwatersheds[['AFACTR','area_output']].groupby(subwatersheds.index).sum()
97
+ subwatersheds[output_name] = subwatersheds['area_output']/subwatersheds['AFACTR']
98
+
99
+ fig, ax = plt.subplots()
100
+ #[table.plot(column = parameter,ax = ax) for table in tables]
101
+ self.subwatershed_gdf.join(subwatersheds).plot(column = output_name,ax = ax,cmap='viridis',legend=True)
102
+ plt.title(output_name)
103
+
104
+ #return self.subwatershed_gdf.join(subwatersheds)
105
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyhcal
3
- Version: 1.1.0
3
+ Version: 1.1.1
4
4
  Summary: Python package for calibrating MPCA HSPF models
5
5
  Project-URL: Homepage, https://github.com/mfratkin1/pyhcal
6
6
  Author-email: Mulu Fratkin <michael.fratkin@state.mn.us>
@@ -1,15 +1,14 @@
1
+ pyhcal/ERROR.FIL,sha256=w35iHJYKYpcU9lrmU4FqLGMlKLabOOX-_Z567kHF8CA,5018
1
2
  pyhcal/__init__.py,sha256=4TEpGD-PfEY8yK-od8DpEMA4_iQ-q9y0PBvROXSPdB0,94
2
- pyhcal/calibrators.py,sha256=lDxvXpjLj1Xhp-NPCVUyyWeaMTZdP5FA9Bh-PuwrOHs,30383
3
+ pyhcal/calibrators.py,sha256=jWlM7-eWLLDpgASzLpEQQ6jUBx9T9vDaUMeMaF-GWzk,31939
3
4
  pyhcal/figures.py,sha256=Iu7LaN_i2IuDA_nfxj-a8AkG-FTLZVicJ3-efIs5OiE,45534
5
+ pyhcal/mappers.py,sha256=YhrYbX8H5rvWFFXBS2a8UAaEFIwZQwE4Vzxz1TIN97Q,5225
4
6
  pyhcal/metrics.py,sha256=GUGHd-op-g1Foj8wnS_JVURSms4ifcC0a5h8ketQ29I,17911
5
7
  pyhcal/modl_db.py,sha256=z8trT387Gcbg15xAqAcW62c1dbgSSjymv3qOyH3Dyx8,12569
6
8
  pyhcal/repository.py,sha256=VPHeSbrnFAG1F6tFXdnI2C72xm3dTPb7Z3rkPr--srI,4603
7
9
  pyhcal/setup_utils.py,sha256=sIINj8_h-MgQhcCH_u95nFTJVw0QEgnR0fZgAitX1iQ,30398
8
10
  pyhcal/data/HUC_Names.csv,sha256=UGmd3Q5E8DyFWggXzaXWpsRze7sFyrlpYqaYpMWAiGM,18946
9
11
  pyhcal/data/WISKI_EQUIS_XREF.csv,sha256=bPYq-f4-Qc6jsvUgl81lwXBeFamfDe5TjohqUV1XJlg,1244704
10
- pyhcal/data/outlets.duckdb,sha256=zB1t2NsnrUed-3HOT61DYmtOy89PZ9uWZAwmAEUhleY,2895872
11
- pyhcal/data/stations_EQUIS.gpkg,sha256=SPyxGK5H3bbqMikv45n_ul-KULPNWyad9XcDq_9mXwM,2019328
12
- pyhcal/data/stations_wiski.gpkg,sha256=vlh03SihjlQMIbn25rfPqOKQtJsSYS2FMR65zAznTQQ,905216
13
- pyhcal-1.1.0.dist-info/METADATA,sha256=xRX7vV5LA1UxSsAZze6VMRzTJI6ePZ749Pdf8h-VQgw,560
14
- pyhcal-1.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
15
- pyhcal-1.1.0.dist-info/RECORD,,
12
+ pyhcal-1.1.1.dist-info/METADATA,sha256=ishvd0JOT5YuSTJvsjWvpKnM6Bxll2tc0-iyLk3aUd8,560
13
+ pyhcal-1.1.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
14
+ pyhcal-1.1.1.dist-info/RECORD,,
Binary file
Binary file
Binary file
File without changes