def test_iteritems(): d = {'a': 0, 'b': 1, 'c': 2} for k, v in iteritems(d): assert type(k) == str assert type(v) == int
def rasm_soil(data, soil_file): """Write VIC formatted soil parameter file""" message = """ *** ---------------------------------------------------------------------- *** Notes about RASM soil parameter file generations: - To fill in missing grid cells 'mask' variable must be the same as the domain file mask. - Inactive grid cells will have a dummy line printed for all variables except the lons/lats. - Any grid cells with nans will be copied from the previous line without nans or FILL_VALUEs. *** --------------------------------------------------------------------- ***\n """ print(message) # ---------------------------------------------------------------- # c = grid_params.cols(nlayers=3) f = grid_params.format(nlayers=3) c.soil_param['Nveg'] = np.array([0]) f.soil_param['Nveg'] = '%1i' numcells = data['mask'].size arrayshape = (numcells, 1 + np.max([np.max(cols) for v, cols in iteritems(c.soil_param)])) soil_params = np.empty(arrayshape) dtypes = ['%1i'] * arrayshape[1] # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # find nearest real grid cell for all grid cells where frozen soil mask is # active # This is needed because the RASM mask is often different than existing # datasets print('Finding/filling nearest neighbors for all variables based on ' 'fs_active mask') # real mask (from input dataset) ry, rx = np.nonzero(data['fs_active']) # fill mask (we will fill all of these grid cells with their nearest real # value) my_mask = np.zeros(data['fs_active'].shape, dtype=int) my_mask[ry, rx] = 1 fy, fx = np.nonzero(my_mask == 0) # Find nearest real grid cell combined = np.dstack(([data['yc'][ry, rx], data['xc'][ry, rx]]))[0] points = list( np.vstack((data['yc'][fy, fx], data['xc'][fy, fx])).transpose()) mytree = cKDTree(combined) dist, inds = mytree.query(points, k=1) # loop over all variables and fill in values for var in c.soil_param: if var not in [ 'run_cell', 'grid_cell', 'lats', 'lons', 'fs_active', 'Nveg' ]: # unmask the variable data[var] = np.array(data[var]) # fill with nearest data if data[var].ndim == 2: data[var][fy, fx] = data[var][ry[inds], rx[inds]] elif data[var].ndim == 3: data[var][:, fy, fx] = data[var][:, ry[inds], rx[inds]] # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # This is the domain mask yinds, xinds = np.nonzero(data['mask'] == 1) ymask, xmask = np.nonzero(data['mask'] == 0) # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # Fix problematic avg_T values print('Finding/filling nearest neighbors for avg_T\n') # real mask (from input dataset) ry, rx = np.nonzero((data['avg_T'] > -50) & (data['avg_T'] < 99)) # fill mask (we will fill all of these grid cells with their nearest # real value) my_mask = np.zeros(data['avg_T'].shape) my_mask[ry, rx] = 1 fy, fx = np.nonzero(my_mask == 0) # Find nearest real grid cell if len(fy) > 0: combined = np.dstack(([data['yc'][ry, rx], data['xc'][ry, rx]]))[0] points = list( np.vstack((data['yc'][fy, fx], data['xc'][fy, fx])).transpose()) mytree = cKDTree(combined) dist, inds = mytree.query(points, k=1) data['avg_T'] = np.array(data['avg_T']) data['avg_T'][fy, fx] = data['avg_T'][ry[inds], rx[inds]] # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # For rasm, all cols are shifted one to right to make room for nveg in # col 0 i = -1 for var, cols in iteritems(c.soil_param): for col in cols: dtypes[col] = f.soil_param[var] for (y, x), maskval in np.ndenumerate(data['mask']): # advance the row count i += 1 # put real data for var in c.soil_param: cols = c.soil_param[var] if data[var].ndim == 2: soil_params[i, cols] = data[var][y, x] elif data[var].ndim == 3: for j, col in enumerate(cols): soil_params[i, col] = data[var][j, y, x] # write the grid cell number soil_params[i, 2] = i + 1 # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # Write phi_s soil_params[:, c.soil_param['phi_s']] = -999 # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # Write nveg soil_params[:, 0] = data['Nveg'][:, :].flatten() # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # Set all grid cells to run soil_params[:, 1] = 1 # run soil_params[:, -1] = 1 # run with frozen soils on # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # rewrite the lons/lats columns soil_params[:, 3] = data['lats'].flatten() soil_params[:, 4] = data['lons'].flatten() assert soil_params[-1, 3] == data['lats'][y, x] assert soil_params[-1, 4] == data['lons'][y, x] # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # check for nans # sometimes RASM has land grid cells that the input file does not. # In this case, we will use the previous lnd grid cell if np.isnan(soil_params.sum()): bad_cells = [] replacements = [] for i, cell in enumerate(soil_params): if np.isnan(np.sum(cell)): bad_cells.append(i) j = i while True: j -= 1 if (FILL_VALUE not in soil_params[j, :]) and \ not np.isnan(np.sum(soil_params[j, :])): soil_params[i, 5:] = soil_params[j, 5:] replacements.append(j) break print('Fixed {0} bad cells'.format(len(bad_cells))) print('Example: {0}-->{1}'.format(bad_cells[0], replacements[0])) # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # Print summary of variables for var, cols in iteritems(c.soil_param): print('{0: <12}--> min: {1:<09.3f}, max: {2:<09.3f}, mean:' ' {3:<09.3f}'.format(var, soil_params[:, cols].min(), soil_params[:, cols].max(), soil_params[:, cols].mean())) # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # Finish up assert soil_params[-1, 3] == data['lats'][y, x] assert soil_params[-1, 4] == data['lons'][y, x] # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # Write the file print('writing soil parameter file: {0}'.format(soil_file)) np.savetxt(soil_file, soil_params, fmt=dtypes) print('done RASM with soil') # ---------------------------------------------------------------- # return
def rasm_soil(data, soil_file): """Write VIC formatted soil parameter file""" message = """ *** ---------------------------------------------------------------------- *** Notes about RASM soil parameter file generations: - To fill in missing grid cells 'mask' variable must be the same as the domain file mask. - Inactive grid cells will have a dummy line printed for all variables except the lons/lats. - Any grid cells with nans will be copied from the previous line without nans or FILL_VALUEs. *** --------------------------------------------------------------------- ***\n """ print(message) # ---------------------------------------------------------------- # c = grid_params.cols(nlayers=3) f = grid_params.format(nlayers=3) c.soil_param['Nveg'] = np.array([0]) f.soil_param['Nveg'] = '%1i' numcells = data['mask'].size arrayshape = (numcells, 1 + np.max([np.max(cols) for v, cols in iteritems(c.soil_param)])) soil_params = np.empty(arrayshape) dtypes = ['%1i'] * arrayshape[1] # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # find nearest real grid cell for all grid cells where frozen soil mask is # active # This is needed because the RASM mask is often different than existing # datasets print('Finding/filling nearest neighbors for all variables based on ' 'fs_active mask') # real mask (from input dataset) ry, rx = np.nonzero(data['fs_active']) # fill mask (we will fill all of these grid cells with their nearest real # value) my_mask = np.zeros(data['fs_active'].shape, dtype=int) my_mask[ry, rx] = 1 fy, fx = np.nonzero(my_mask == 0) # Find nearest real grid cell combined = np.dstack(([data['yc'][ry, rx], data['xc'][ry, rx]]))[0] points = list(np.vstack((data['yc'][fy, fx], data['xc'][fy, fx])).transpose()) mytree = cKDTree(combined) dist, inds = mytree.query(points, k=1) # loop over all variables and fill in values for var in c.soil_param: if var not in ['run_cell', 'grid_cell', 'lats', 'lons', 'fs_active', 'Nveg']: # unmask the variable data[var] = np.array(data[var]) # fill with nearest data if data[var].ndim == 2: data[var][fy, fx] = data[var][ry[inds], rx[inds]] elif data[var].ndim == 3: data[var][:, fy, fx] = data[var][:, ry[inds], rx[inds]] # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # This is the domain mask yinds, xinds = np.nonzero(data['mask'] == 1) ymask, xmask = np.nonzero(data['mask'] == 0) # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # Fix problematic avg_T values print('Finding/filling nearest neighbors for avg_T\n') # real mask (from input dataset) ry, rx = np.nonzero((data['avg_T'] > -50) & (data['avg_T'] < 99)) # fill mask (we will fill all of these grid cells with their nearest # real value) my_mask = np.zeros(data['avg_T'].shape) my_mask[ry, rx] = 1 fy, fx = np.nonzero(my_mask == 0) # Find nearest real grid cell if len(fy) > 0: combined = np.dstack(([data['yc'][ry, rx], data['xc'][ry, rx]]))[0] points = list(np.vstack((data['yc'][fy, fx], data['xc'][fy, fx])).transpose()) mytree = cKDTree(combined) dist, inds = mytree.query(points, k=1) data['avg_T'] = np.array(data['avg_T']) data['avg_T'][fy, fx] = data['avg_T'][ry[inds], rx[inds]] # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # For rasm, all cols are shifted one to right to make room for nveg in # col 0 i = -1 for var, cols in iteritems(c.soil_param): for col in cols: dtypes[col] = f.soil_param[var] for (y, x), maskval in np.ndenumerate(data['mask']): # advance the row count i += 1 # put real data for var in c.soil_param: cols = c.soil_param[var] if data[var].ndim == 2: soil_params[i, cols] = data[var][y, x] elif data[var].ndim == 3: for j, col in enumerate(cols): soil_params[i, col] = data[var][j, y, x] # write the grid cell number soil_params[i, 2] = i + 1 # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # Write phi_s soil_params[:, c.soil_param['phi_s']] = -999 # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # Write nveg soil_params[:, 0] = data['Nveg'][:, :].flatten() # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # Set all grid cells to run soil_params[:, 1] = 1 # run soil_params[:, -1] = 1 # run with frozen soils on # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # rewrite the lons/lats columns soil_params[:, 3] = data['lats'].flatten() soil_params[:, 4] = data['lons'].flatten() assert soil_params[-1, 3] == data['lats'][y, x] assert soil_params[-1, 4] == data['lons'][y, x] # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # check for nans # sometimes RASM has land grid cells that the input file does not. # In this case, we will use the previous lnd grid cell if np.isnan(soil_params.sum()): bad_cells = [] replacements = [] for i, cell in enumerate(soil_params): if np.isnan(np.sum(cell)): bad_cells.append(i) j = i while True: j -= 1 if (FILL_VALUE not in soil_params[j, :]) and \ not np.isnan(np.sum(soil_params[j, :])): soil_params[i, 5:] = soil_params[j, 5:] replacements.append(j) break print('Fixed {0} bad cells'.format(len(bad_cells))) print('Example: {0}-->{1}'.format(bad_cells[0], replacements[0])) # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # Print summary of variables for var, cols in iteritems(c.soil_param): print('{0: <12}--> min: {1:<09.3f}, max: {2:<09.3f}, mean:' ' {3:<09.3f}'.format(var, soil_params[:, cols].min(), soil_params[:, cols].max(), soil_params[:, cols].mean())) # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # Finish up assert soil_params[-1, 3] == data['lats'][y, x] assert soil_params[-1, 4] == data['lons'][y, x] # ---------------------------------------------------------------- # # ---------------------------------------------------------------- # # Write the file print('writing soil parameter file: {0}'.format(soil_file)) np.savetxt(soil_file, soil_params, fmt=dtypes) print('done RASM with soil') # ---------------------------------------------------------------- # return