def station_to_modelgrid(self,station_csv,screen_length=1,bbox_is_latlon=False,convert2metric=True,is_discharge=False): '''Returns a dataframe of station information that includes projected model grid coordinates. If the model domain shape is already projected, need_to_project = False (default).''' print 'Reading groundwater station data and translating to the model grid.\n' station_df = pd.DataFrame.from_csv(station_csv) if (convert2metric == True): convert_cols = ['alt_va'] if (is_discharge == False): # For GW measurements . . . convert_cols = convert_cols + ['well_depth_va','hole_depth_va','well_elev'] for icol in convert_cols: station_df[icol] *= 0.3048 # Convert feet to meters model_epsg = self.model_epsg epsg_projected = pyproj.Proj('+init=EPSG:' + str(model_epsg)) if (bbox_is_latlon == True): w_lon,s_lat,e_lon,n_lat = self.bbox model_epsg = self.model_epsg # Configure the re-projection object and project the lat/lon coords x_nw,y_nw = epsg_projected(w_lon,n_lat) x_sw,y_sw = epsg_projected(w_lon,s_lat) else: x_w,y_s,x_e,y_n = self.bbox x_nw,y_nw = x_w,y_n x_sw,y_sw = x_w,y_s # First return the projected distances from the NW corner of the active model (i.e., MODFLOW grid orientation.) station_df['Projected_X'],station_df['Projected_Y'],station_df['MODFLOW_X'],station_df['MODFLOW_Y'] = \ zip(*station_df.apply(lambda row: gu.latlon_to_modelxy((row['dec_lat_va'],row['dec_long_va']),(x_nw,y_nw),epsg_projected),axis=1)) # Now return the projected distances from the SW corner of the active model (i.e., easting and northing) _,_,station_df['Easting'],station_df['Northing'] = \ zip(*station_df.apply(lambda row: gu.latlon_to_modelxy((row['dec_lat_va'],row['dec_long_va']),(x_sw,y_sw),epsg_projected),axis=1)) # The NWIS download occasionally captures stations that are outside the active model area. grid_util.latlon_to_modelxy # returns these as model_xy = np.nan. Filter any such stations station_df = station_df.dropna(subset=['MODFLOW_X','MODFLOW_Y']) if (is_discharge == False): # For GW measurements . . . # Translate the observation locations to the model grid station_df['Row'],station_df['Column'],station_df['ROFF'],station_df['COFF'] = \ zip(*station_df.apply(lambda row: gu.modelxy_to_rowcol(row['MODFLOW_X'],row['MODFLOW_Y'],self.delr,self.delc),axis=1)) station_df['ModelTop'],station_df['Layer'],station_df['LocalZ'] = \ zip(*station_df.apply(gu.globalz_to_layer,args=(self.top,self.bottoms,self.midpoints,self.ibound,self.lay_thick),axis=1)) # Remove the observations in inactive cells station_df = station_df.dropna(subset=['Layer']) # A few arithmetic transformations for later convenience . . . station_df['GlobZTop'],station_df['GlobZBot'] = station_df['well_elev'],station_df['well_elev'] - screen_length return station_df
def get_ppt(self,ppt_nx,ppt_ny,ppt_dz,zone_array,ppt_name_root='pt',param_name_root='k_',ipar_init=1): '''Generates a dataframe of pilot point locations. Note that grid_util.globalxy_to_localxy uses the northwest corner of the model grid as the origin. However, the PEST pilot points file assumes the SW corner of the model grid as the origin (i.e., it prints coordinates as northings and eastings.)''' # Generate the pilot point grid in the row/col plane x_vector = np.linspace(0,self.delr * self.ncol,ppt_nx+1)[:-1] x_vector = np.add(x_vector,0.5*(x_vector[1]-x_vector[0])) y_vector = np.linspace(0,self.delc * self.nrow,ppt_ny+1)[:-1] y_vector = np.add(y_vector,0.5*(y_vector[1]-y_vector[0])) ppt_df = pd.DataFrame(columns=['PPT_Name','Param_Name','Easting','Northing','Elevation','Zone','Value']) icount = 0 for ix,jy in product(x_vector,y_vector): # row and column returned from this function in PYTHON indexing irow,icol,_,_ = gu.modelxy_to_rowcol(ix,(self.nrow*self.delc - jy),self.delr,self.delc) # Generate the vertical dimension of the pilot point grid # This algorithm assumes that for any (row,col), no active cells are found # beneath any inactive cells. z_0 = self.midpoints[irow,icol][0] z_vector = np.arange(z_0,z_0 - np.sum(self.layer_depths),-(abs(ppt_dz))) # The PEST 10-character limit precludes # writing row,col, and layer identifiers into the pilot point name. # As an alternative, I've simply labeled them A,B,C, etc., starting # with the top pilot point in a given (row,col) for iz,iletter in zip(z_vector,string.uppercase[:(len(z_vector))]): ilay,_ = gu.globalz_to_localz(irow,icol,iz,self.midpoints,self.bottoms,self.layer_depths) if (gu.check_if_active(irow,icol,ilay,self.ibound) == True): izone = zone_array[irow-1,icol-1,ilay-1] ppt_name = ppt_name_root + str(irow) + '_' + str(icol) + iletter param_name = param_name_root + str(irow) + '_' + str(icol) + iletter ppt_df.loc[icount,:] = [ppt_name,param_name,ix,jy,iz,izone,ipar_init] icount += 1 return ppt_df
def get_ppt(self, ppt_nx, ppt_ny, ppt_dz, zone_array, ppt_name_root='pt', param_name_root='k_', ipar_init=1): '''Generates a dataframe of pilot point locations. Note that grid_util.globalxy_to_localxy uses the northwest corner of the model grid as the origin. However, the PEST pilot points file assumes the SW corner of the model grid as the origin (i.e., it prints coordinates as northings and eastings.)''' # Generate the pilot point grid in the row/col plane x_vector = np.linspace(0, self.delr * self.ncol, ppt_nx + 1)[:-1] x_vector = np.add(x_vector, 0.5 * (x_vector[1] - x_vector[0])) y_vector = np.linspace(0, self.delc * self.nrow, ppt_ny + 1)[:-1] y_vector = np.add(y_vector, 0.5 * (y_vector[1] - y_vector[0])) ppt_df = pd.DataFrame(columns=[ 'PPT_Name', 'Param_Name', 'Easting', 'Northing', 'Elevation', 'Zone', 'Value' ]) icount = 0 for ix, jy in product(x_vector, y_vector): # row and column returned from this function in PYTHON indexing irow, icol, _, _ = gu.modelxy_to_rowcol( ix, (self.nrow * self.delc - jy), self.delr, self.delc) # Generate the vertical dimension of the pilot point grid # This algorithm assumes that for any (row,col), no active cells are found # beneath any inactive cells. z_0 = self.midpoints[irow, icol][0] z_vector = np.arange(z_0, z_0 - np.sum(self.layer_depths), -(abs(ppt_dz))) # The PEST 10-character limit precludes # writing row,col, and layer identifiers into the pilot point name. # As an alternative, I've simply labeled them A,B,C, etc., starting # with the top pilot point in a given (row,col) for iz, iletter in zip(z_vector, string.uppercase[:(len(z_vector))]): ilay, _ = gu.globalz_to_localz(irow, icol, iz, self.midpoints, self.bottoms, self.layer_depths) if (gu.check_if_active(irow, icol, ilay, self.ibound) == True): izone = zone_array[irow - 1, icol - 1, ilay - 1] ppt_name = ppt_name_root + str(irow) + '_' + str( icol) + iletter param_name = param_name_root + str(irow) + '_' + str( icol) + iletter ppt_df.loc[icount, :] = [ ppt_name, param_name, ix, jy, iz, izone, ipar_init ] icount += 1 return ppt_df
def station_to_modelgrid(self, station_csv, screen_length=1, bbox_is_latlon=False, convert2metric=True, is_discharge=False): '''Returns a dataframe of station information that includes projected model grid coordinates. If the model domain shape is already projected, need_to_project = False (default).''' print 'Reading groundwater station data and translating to the model grid.\n' station_df = pd.DataFrame.from_csv(station_csv) if (convert2metric == True): convert_cols = ['alt_va'] if (is_discharge == False): # For GW measurements . . . convert_cols = convert_cols + [ 'well_depth_va', 'hole_depth_va', 'well_elev' ] for icol in convert_cols: station_df[icol] *= 0.3048 # Convert feet to meters model_epsg = self.model_epsg epsg_projected = pyproj.Proj('+init=EPSG:' + str(model_epsg)) if (bbox_is_latlon == True): w_lon, s_lat, e_lon, n_lat = self.bbox model_epsg = self.model_epsg # Configure the re-projection object and project the lat/lon coords x_nw, y_nw = epsg_projected(w_lon, n_lat) x_sw, y_sw = epsg_projected(w_lon, s_lat) else: x_w, y_s, x_e, y_n = self.bbox x_nw, y_nw = x_w, y_n x_sw, y_sw = x_w, y_s # First return the projected distances from the NW corner of the active model (i.e., MODFLOW grid orientation.) station_df['Projected_X'],station_df['Projected_Y'],station_df['MODFLOW_X'],station_df['MODFLOW_Y'] = \ zip(*station_df.apply(lambda row: gu.latlon_to_modelxy((row['dec_lat_va'],row['dec_long_va']),(x_nw,y_nw),epsg_projected),axis=1)) # Now return the projected distances from the SW corner of the active model (i.e., easting and northing) _,_,station_df['Easting'],station_df['Northing'] = \ zip(*station_df.apply(lambda row: gu.latlon_to_modelxy((row['dec_lat_va'],row['dec_long_va']),(x_sw,y_sw),epsg_projected),axis=1)) # The NWIS download occasionally captures stations that are outside the active model area. grid_util.latlon_to_modelxy # returns these as model_xy = np.nan. Filter any such stations station_df = station_df.dropna(subset=['MODFLOW_X', 'MODFLOW_Y']) if (is_discharge == False): # For GW measurements . . . # Translate the observation locations to the model grid station_df['Row'],station_df['Column'],station_df['ROFF'],station_df['COFF'] = \ zip(*station_df.apply(lambda row: gu.modelxy_to_rowcol(row['MODFLOW_X'],row['MODFLOW_Y'],self.delr,self.delc),axis=1)) station_df['ModelTop'],station_df['Layer'],station_df['LocalZ'] = \ zip(*station_df.apply(gu.globalz_to_layer,args=(self.top,self.bottoms,self.midpoints,self.ibound,self.lay_thick),axis=1)) # Remove the observations in inactive cells station_df = station_df.dropna(subset=['Layer']) # A few arithmetic transformations for later convenience . . . station_df['GlobZTop'], station_df['GlobZBot'] = station_df[ 'well_elev'], station_df['well_elev'] - screen_length return station_df