def hob_resid_to_shapefile_all(mf, stress_period=[0, -1], shpname='hob_shapefile.shp'): get_vertices = mf.modelgrid.get_cell_vertices # get all files mfname = os.path.join(mf.model_ws, mf.namefile) mf_files = general_util.get_mf_files(mfname) # read mf and get spatial reference hobdf = hob_util.in_hob_to_df(mfname=mfname, return_model=False) # read_hob_out hobout_df = None for file in mf_files.keys(): fn = mf_files[file][1] basename = os.path.basename(fn) if ".hob.out" in basename: hobout_df = pd.read_csv(fn, delim_whitespace=True) # loop over obs and compute residual error obs_names = hobdf['Basename'].unique() geoms = [] all_rec = [] for obs_ in obs_names: curr_hob = hobdf[hobdf['Basename'] == obs_] # trim data based on sptress period start = stress_period[0] endd = stress_period[1] if endd < 0: endd = hobdf['stress_period'].max() curr_hob = curr_hob[(curr_hob['stress_period'] >= start) & (curr_hob['stress_period'] <= endd)] curr_hob_out = hobout_df[hobout_df['OBSERVATION NAME'].isin( curr_hob['name'].values)] err = curr_hob_out['OBSERVED VALUE'] - curr_hob_out[ 'SIMULATED EQUIVALENT'] curr_hob['OBSERVED VALUE'] = curr_hob_out['OBSERVED VALUE'].values curr_hob['SIMULATED EQUIVALENT'] = curr_hob_out[ 'SIMULATED EQUIVALENT'].values curr_hob['err'] = err # n, mean, mse, mae #rec = [obs_, len(err), err.mean(), (err**2.0).mean()**0.5, (err.abs()).mean()] rrow = curr_hob['row'].values[0] - 1 coll = curr_hob['col'].values[0] - 1 xy = get_vertices(rrow, coll) for ierr in err: geoms.append(Point(xy[0][0], xy[0][1], 0)) all_rec.append(curr_hob.copy()) all_rec = pd.concat(all_rec) # here we generate csv file all_rec = all_rec.to_records() epsg = mf.modelgrid.epsg recarray2shp(all_rec, geoms, shpname, epsg=epsg) xxx = 1
def test_polygon_from_ij(): """test creation of a polygon from an i, j location using get_vertices().""" m = flopy.modflow.Modflow('toy_model', model_ws=mpth) botm = np.zeros((2, 10, 10)) botm[0, :, :] = 1.5 botm[1, 5, 5] = 4 # negative layer thickness! botm[1, 6, 6] = 4 dis = flopy.modflow.ModflowDis(nrow=10, ncol=10, nlay=2, delr=100, delc=100, top=3, botm=botm, model=m) m.sr = SpatialReference(delr=m.dis.delr * .3048, delc=m.dis.delc * .3048, xul=600000, yul=5170000, proj4_str='EPSG:26715', rotation=-45) recarray = np.array([(0, 5, 5, .1, True, 's0'), (1, 4, 5, .2, False, 's1'), (0, 7, 8, .3, True, 's2')], dtype=[('k', '<i8'), ('i', '<i8'), ('j', '<i8'), ('stuff', '<f4'), ('stuf', '|b1'), ('stf', np.object)]).view(np.recarray) get_vertices = m.sr.get_vertices # function to get the referenced vertices for a model cell geoms = [ Polygon(get_vertices(i, j)) for i, j in zip(recarray.i, recarray.j) ] assert geoms[0].type == 'Polygon' assert np.abs(geoms[0].bounds[-1] - 5169784.473861726) < 1e-4 fpth = os.path.join(mpth, 'test.shp') recarray2shp(recarray, geoms, fpth, epsg=26715) import epsgref reload(epsgref) from epsgref import prj assert 26715 in prj fpth = os.path.join(mpth, 'test.prj') fpth2 = os.path.join(mpth, '26715.prj') shutil.copy(fpth, fpth2) fpth = os.path.join(mpth, 'test.shp') recarray2shp(recarray, geoms, fpth, prj=fpth2) # test_dtypes fpth = os.path.join(mpth, 'test.shp') ra = shp2recarray(fpth) assert "int" in ra.dtype['k'].name assert "float" in ra.dtype['stuff'].name assert "bool" in ra.dtype['stuf'].name assert "object" in ra.dtype['stf'].name assert True
def test_polygon_from_ij(): """test creation of a polygon from an i, j location using get_vertices().""" m = flopy.modflow.Modflow('toy_model', model_ws=mpth) botm = np.zeros((2, 10, 10)) botm[0, :, :] = 1.5 botm[1, 5, 5] = 4 # negative layer thickness! botm[1, 6, 6] = 4 dis = flopy.modflow.ModflowDis(nrow=10, ncol=10, nlay=2, delr=100, delc=100, top=3, botm=botm, model=m) ncdf = NetCdf('toy.model.nc', m) ncdf.write() m.export('toy_model_two.nc') dis.export('toy_model_dis.nc') mg = m.modelgrid mg.set_coord_info(xoff=mg._xul_to_xll(600000.0, -45.0), yoff=mg._yul_to_yll(5170000, -45.0), angrot=-45.0, proj4='EPSG:26715') recarray = np.array([(0, 5, 5, .1, True, 's0'), (1, 4, 5, .2, False, 's1'), (0, 7, 8, .3, True, 's2')], dtype=[('k', '<i8'), ('i', '<i8'), ('j', '<i8'), ('stuff', '<f4'), ('stuf', '|b1'), ('stf', np.object)]).view(np.recarray) # vertices for a model cell geoms = [Polygon(m.modelgrid.get_cell_vertices(i, j)) for i, j in zip(recarray.i, recarray.j)] assert geoms[0].type == 'Polygon' assert np.abs(geoms[0].bounds[-1] - 5169292.893203464) < 1e-4 fpth = os.path.join(mpth, 'test.shp') recarray2shp(recarray, geoms, fpth, epsg=26715) ep = epsgRef() prj = ep.to_dict() assert 26715 in prj fpth = os.path.join(mpth, 'test.prj') fpth2 = os.path.join(mpth, '26715.prj') shutil.copy(fpth, fpth2) fpth = os.path.join(mpth, 'test.shp') recarray2shp(recarray, geoms, fpth, prj=fpth2) # test_dtypes fpth = os.path.join(mpth, 'test.shp') ra = shp2recarray(fpth) assert "int" in ra.dtype['k'].name assert "float" in ra.dtype['stuff'].name assert "bool" in ra.dtype['stuf'].name assert "object" in ra.dtype['stf'].name assert True
def point_to_shapefile(df, shpfile='temp_shp.shp', xy_field=[], epsg=None): """ Convert a dataframe to shapefile. Returns ------- """ geoms = [] for irec, rec in df.iterrows(): x_ = rec[xy_field[0]] y_ = rec[xy_field[1]] geoms.append(Point(x_, y_, 0)) att_table = df.to_records() recarray2shp(att_table, geoms, shpfile, epsg=epsg) pass
def export_contours(modelgrid, filename, contours, fieldname='level', epsg=None, prj=None, **kwargs): """Convert matplotlib contour plot object to shapefile. Parameters ---------- filename : str path of output shapefile contours : matplotlib.contour.QuadContourSet or list of them (object returned by matplotlib.pyplot.contour) epsg : int EPSG code. See https://www.epsg-registry.org/ or spatialreference.org prj : str Existing projection file to be used with new shapefile. **kwargs : key-word arguments to flopy.export.shapefile_utils.recarray2shp Returns ------- df : dataframe of shapefile contents """ from flopy.utils.geometry import LineString from flopy.export.shapefile_utils import recarray2shp if not isinstance(contours, list): contours = [contours] if epsg is None: epsg = modelgrid.epsg if prj is None: prj = modelgrid.proj4 geoms = [] level = [] for ctr in contours: levels = ctr.levels for i, c in enumerate(ctr.collections): paths = c.get_paths() geoms += [LineString(p.vertices) for p in paths] level += list(np.ones(len(paths)) * levels[i]) # convert the dictionary to a recarray ra = np.array(level, dtype=[(fieldname, float)]).view(np.recarray) recarray2shp(ra, geoms, filename, epsg, prj, **kwargs)
def test_polygon_from_ij(): """test creation of a polygon from an i, j location using get_vertices().""" m = flopy.modflow.Modflow('toy_model', model_ws=mpth) botm = np.zeros((2, 10, 10)) botm[0, :, :] = 1.5 botm[1, 5, 5] = 4 # negative layer thickness! botm[1, 6, 6] = 4 dis = flopy.modflow.ModflowDis(nrow=10, ncol=10, nlay=2, delr=100, delc=100, top=3, botm=botm, model=m) m.sr = SpatialReference(delr=m.dis.delr * .3048, delc=m.dis.delc * .3048, xul=600000, yul=5170000, proj4_str='EPSG:26715', rotation=-45) recarray = np.array([(0, 5, 5, .1, True, 's0'), (1, 4, 5, .2, False, 's1'), (0, 7, 8, .3, True, 's2')], dtype=[('k', '<i8'), ('i', '<i8'), ('j', '<i8'), ('stuff', '<f4'), ('stuf', '|b1'), ('stf', np.object)]).view(np.recarray) get_vertices = m.sr.get_vertices # function to get the referenced vertices for a model cell geoms = [Polygon(get_vertices(i, j)) for i, j in zip(recarray.i, recarray.j)] assert geoms[0].type == 'Polygon' assert np.abs(geoms[0].bounds[-1] - 5169784.473861726) < 1e-4 fpth = os.path.join(mpth, 'test.shp') recarray2shp(recarray, geoms, fpth, epsg=26715) import epsgref reload(epsgref) from epsgref import prj assert 26715 in prj fpth = os.path.join(mpth, 'test.prj') fpth2 = os.path.join(mpth, '26715.prj') shutil.copy(fpth, fpth2) fpth = os.path.join(mpth, 'test.shp') recarray2shp(recarray, geoms, fpth, prj=fpth2) # test_dtypes fpth = os.path.join(mpth, 'test.shp') ra = shp2recarray(fpth) assert "int" in ra.dtype['k'].name assert "float" in ra.dtype['stuff'].name assert "bool" in ra.dtype['stuf'].name assert "object" in ra.dtype['stf'].name assert True
def write_shapefile(self, endpoint_data=None, shpname='endpoings.shp', direction='ending', sr=None, epsg=None, **kwargs): """Write particle starting / ending locations to shapefile. endpoint_data : np.recarry Record array of same form as that returned by EndpointFile.get_alldata. (if none, EndpointFile.get_alldata() is exported). shpname : str File path for shapefile direction : str String defining if starting or ending particle locations should be considered. (default is 'ending') sr : flopy.utils.reference.SpatialReference instance Used to scale and rotate Global x,y,z values in MODPATH Endpoint file epsg : int EPSG code for writing projection (.prj) file. If this is not supplied, the proj4 string or epgs code associated with sr will be used. kwargs : keyword arguments to flopy.export.shapefile_utils.recarray2shp """ from flopy.utils.reference import SpatialReference from flopy.utils.geometry import Point from flopy.export.shapefile_utils import recarray2shp epd = endpoint_data.copy() if epd is None: epd = self.get_alldata() if direction.lower() == 'ending': xcol, ycol, zcol = 'x', 'y', 'z' elif direction.lower() == 'starting': xcol, ycol, zcol = 'x0', 'y0', 'z0' else: errmsg = 'flopy.map.plot_endpoint direction must be "ending" ' + \ 'or "starting".' raise Exception(errmsg) if sr is None: sr = SpatialReference() x, y = sr.transform(epd[xcol], epd[ycol]) z = epd[zcol] geoms = [Point(x[i], y[i], z[i]) for i in range(len(epd))] # convert back to one-based for n in self.kijnames: epd[n] += 1 recarray2shp(epd, geoms, shpname=shpname, epsg=epsg, **kwargs)
def test_polygon_from_ij(): """test creation of a polygon from an i, j location using get_vertices().""" m = flopy.modflow.Modflow("toy_model", model_ws="temp") botm = np.zeros((2, 10, 10)) botm[0, :, :] = 1.5 botm[1, 5, 5] = 4 # negative layer thickness! botm[1, 6, 6] = 4 dis = flopy.modflow.ModflowDis(nrow=10, ncol=10, nlay=2, delr=100, delc=100, top=3, botm=botm, model=m) m.sr = SpatialReference( delr=m.dis.delr * 0.3048, delc=m.dis.delc * 0.3048, xul=600000, yul=5170000, proj4_str="EPSG:26715", rotation=-45, ) recarray = np.array( [(0, 5, 5, 0.1, True, "s0"), (1, 4, 5, 0.2, False, "s1"), (0, 7, 8, 0.3, True, "s2")], dtype=[("k", "<i8"), ("i", "<i8"), ("j", "<i8"), ("stuff", "<f4"), ("stuf", "|b1"), ("stf", np.object)], ).view(np.recarray) get_vertices = m.sr.get_vertices # function to get the referenced vertices for a model cell geoms = [Polygon(get_vertices(i, j)) for i, j in zip(recarray.i, recarray.j)] assert geoms[0].type == "Polygon" assert geoms[0].bounds[-1] - 5169784.473861726 < 1e-6 recarray2shp(recarray, geoms, "temp/test.shp", epsg=26715) import epsgref reload(epsgref) from epsgref import prj assert 26715 in prj shutil.copy("temp/test.prj", "temp/26715.prj") recarray2shp(recarray, geoms, "temp/test.shp", prj="temp/26715.prj")
def mflist_export(f, mfl, **kwargs): """ export helper for MfList instances Parameters ----------- f : string (filename) or existing export instance type (NetCdf only for now) mfl : MfList instance """ assert isinstance(mfl, DataListInterface) and \ isinstance(mfl, DataInterface) \ , "mflist_helper only helps instances that support DataListInterface" if isinstance(f, str) and f.lower().endswith(".nc"): f = NetCdf(f, mfl.model) if isinstance(f, str) and f.lower().endswith(".shp"): sparse = kwargs.get("sparse", False) kper = kwargs.get("kper", 0) squeeze = kwargs.get("squeeze", True) model_grid = mfl.model.modelgrid if model_grid is None: raise Exception("MfList.to_shapefile: ModelGrid is not set") elif model_grid.grid_type == 'USG-Unstructured': raise Exception('Flopy does not support exporting to shapefile ' 'from a MODFLOW-USG unstructured grid.') if kper is None: keys = mfl.data.keys() keys.sort() else: keys = [kper] if not sparse: array_dict = {} for kk in keys: arrays = mfl.to_array(kk) for name, array in arrays.items(): for k in range(array.shape[0]): # aname = name+"{0:03d}_{1:02d}".format(kk, k) n = shapefile_utils.shape_attr_name(name, length=4) aname = "{}{}{}".format(n, k + 1, int(kk) + 1) array_dict[aname] = array[k] shapefile_utils.write_grid_shapefile2(f, model_grid, array_dict) else: from ..export.shapefile_utils import recarray2shp from ..utils.geometry import Polygon #if np.isscalar(kper): # kper = [kper] model_grid = mfl.mg df = mfl.get_dataframe(squeeze=squeeze) if 'kper' in kwargs or df is None: ra = mfl[kper] verts = np.array(model_grid.get_cell_vertices(ra.i, ra.j)) elif df is not None: verts = np.array([model_grid.get_cell_vertices(i, df.j.values[ix]) for ix, i in enumerate(df.i.values)]) ra = df.to_records(index=False) epsg = kwargs.get('epsg', None) prj = kwargs.get('prj', None) polys = np.array([Polygon(v) for v in verts]) recarray2shp(ra, geoms=polys, shpname=f, mg=model_grid, epsg=epsg, prj=prj) elif isinstance(f, NetCdf) or isinstance(f, dict): base_name = mfl.package.name[0].lower() # f.log("getting 4D masked arrays for {0}".format(base_name)) # m4d = mfl.masked_4D_arrays # f.log("getting 4D masked arrays for {0}".format(base_name)) # for name, array in m4d.items(): for name, array in mfl.masked_4D_arrays_itr(): var_name = base_name + '_' + name if isinstance(f, dict): f[var_name] = array continue f.log("processing {0} attribute".format(name)) units = None if var_name in NC_UNITS_FORMAT: units = NC_UNITS_FORMAT[var_name].format(f.grid_units, f.time_units) precision_str = NC_PRECISION_TYPE[mfl.dtype[name].type] if var_name in NC_LONG_NAMES: attribs = {"long_name": NC_LONG_NAMES[var_name]} else: attribs = {"long_name": var_name} attribs["coordinates"] = "time layer latitude longitude" attribs["min"] = np.nanmin(array) attribs["max"] = np.nanmax(array) if np.isnan(attribs["min"]) or np.isnan(attribs["max"]): raise Exception( "error processing {0}: all NaNs".format(var_name)) if units is not None: attribs["units"] = units try: dim_tuple = ("time",) + f.dimension_names var = f.create_variable(var_name, attribs, precision_str=precision_str, dimensions=dim_tuple) except Exception as e: estr = "error creating variable {0}:\n{1}".format(var_name, str(e)) f.logger.warn(estr) raise Exception(estr) array[np.isnan(array)] = f.fillvalue try: var[:] = array except Exception as e: estr = "error setting array to variable {0}:\n{1}".format( var_name, str(e)) f.logger.warn(estr) raise Exception(estr) f.log("processing {0} attribute".format(name)) return f else: raise NotImplementedError("unrecognized export argument:{0}".format(f))
def write_shapefile(self, pathline_data=None, one_per_particle=True, direction='ending', shpname='endpoings.shp', sr=None, epsg=None, **kwargs): """Write pathlines to shapefile. pathline_data : np.recarry Record array of same form as that returned by EndpointFile.get_alldata. (if none, EndpointFile.get_alldata() is exported). one_per_particle : boolean (default True) True writes a single LineString with a single set of attribute data for each particle. False writes a record/geometry for each pathline segment (each row in the PathLine file). This option can be used to visualize attribute information (time, model layer, etc.) across a pathline in a GIS. direction : str String defining if starting or ending particle locations should be included in shapefile attribute information. Only used if one_per_particle=False. (default is 'ending') shpname : str File path for shapefile sr : flopy.utils.reference.SpatialReference instance Used to scale and rotate Global x,y,z values in MODPATH Endpoint file epsg : int EPSG code for writing projection (.prj) file. If this is not supplied, the proj4 string or epgs code associated with sr will be used. kwargs : keyword arguments to flopy.export.shapefile_utils.recarray2shp """ from flopy.utils.reference import SpatialReference from flopy.utils.geometry import LineString from flopy.export.shapefile_utils import recarray2shp pth = pathline_data if pth is None: pth = self._data.view(np.recarray) pth = pth.copy() pth.sort(order=['particleid', 'time']) if sr is None: sr = SpatialReference() particles = np.unique(pth.particleid) geoms = [] # 1 geometry for each path if one_per_particle: loc_inds = 0 if direction == 'ending': loc_inds = -1 pthdata = [] for pid in particles: ra = pth[pth.particleid == pid] x, y = sr.transform(ra.x, ra.y) z = ra.z geoms.append(LineString(list(zip(x, y, z)))) pthdata.append((pid, ra.particlegroup[0], ra.time.max(), ra.k[loc_inds], ra.i[loc_inds], ra.j[loc_inds])) pthdata = np.array(pthdata, dtype=[('particleid', np.int), ('particlegroup', np.int), ('time', np.float), ('k', np.int), ('i', np.int), ('j', np.int) ]).view(np.recarray) # geometry for each row in PathLine file else: dtype = pth.dtype #pthdata = np.empty((0, len(dtype)), dtype=dtype).view(np.recarray) pthdata = [] for pid in particles: ra = pth[pth.particleid == pid] x, y = sr.transform(ra.x, ra.y) z = ra.z geoms += [LineString([(x[i-1], y[i-1], z[i-1]), (x[i], y[i], z[i])]) for i in np.arange(1, (len(ra)))] #pthdata = np.append(pthdata, ra[1:]).view(np.recarray) pthdata += ra[1:].tolist() pthdata = np.array(pthdata, dtype=dtype).view(np.recarray) # convert back to one-based for n in set(self.kijnames).intersection(set(pthdata.dtype.names)): pthdata[n] += 1 recarray2shp(pthdata, geoms, shpname=shpname, epsg=sr.epsg, **kwargs)
def test_polygon_from_ij(): """test creation of a polygon from an i, j location using get_vertices().""" m = flopy.modflow.Modflow("toy_model", model_ws=mpth) botm = np.zeros((2, 10, 10)) botm[0, :, :] = 1.5 botm[1, 5, 5] = 4 # negative layer thickness! botm[1, 6, 6] = 4 dis = flopy.modflow.ModflowDis( nrow=10, ncol=10, nlay=2, delr=100, delc=100, top=3, botm=botm, model=m ) fname = os.path.join(mpth, "toy.model.nc") ncdf = NetCdf(fname, m) ncdf.write() fname = os.path.join(mpth, "toy_model_two.nc") m.export(fname) fname = os.path.join(mpth, "toy_model_dis.nc") dis.export(fname) mg = m.modelgrid mg.set_coord_info( xoff=mg._xul_to_xll(600000.0, -45.0), yoff=mg._yul_to_yll(5170000, -45.0), angrot=-45.0, proj4="EPSG:26715", ) recarray = np.array( [ (0, 5, 5, 0.1, True, "s0"), (1, 4, 5, 0.2, False, "s1"), (0, 7, 8, 0.3, True, "s2"), ], dtype=[ ("k", "<i8"), ("i", "<i8"), ("j", "<i8"), ("stuff", "<f4"), ("stuf", "|b1"), ("stf", object), ], ).view(np.recarray) # vertices for a model cell geoms = [ Polygon(m.modelgrid.get_cell_vertices(i, j)) for i, j in zip(recarray.i, recarray.j) ] assert geoms[0].type == "Polygon" assert np.abs(geoms[0].bounds[-1] - 5169292.893203464) < 1e-4 fpth = os.path.join(mpth, "test.shp") recarray2shp(recarray, geoms, fpth, epsg=26715) ep = EpsgReference() prj = ep.to_dict() assert 26715 in prj fpth = os.path.join(mpth, "test.prj") fpth2 = os.path.join(mpth, "26715.prj") shutil.copy(fpth, fpth2) fpth = os.path.join(mpth, "test.shp") recarray2shp(recarray, geoms, fpth, prj=fpth2) # test_dtypes fpth = os.path.join(mpth, "test.shp") ra = shp2recarray(fpth) assert "int" in ra.dtype["k"].name assert "float" in ra.dtype["stuff"].name assert "bool" in ra.dtype["stuf"].name assert "object" in ra.dtype["stf"].name assert True
def mflist_export(f, mfl, **kwargs): """ export helper for MfList instances Parameters ----------- f : string (filename) or existing export instance type (NetCdf only for now) mfl : MfList instance """ assert isinstance(mfl, DataListInterface) and \ isinstance(mfl, DataInterface) \ , "mflist_helper only helps instances that support DataListInterface" if isinstance(f, str) and f.lower().endswith(".nc"): f = NetCdf(f, mfl.model) if isinstance(f, str) and f.lower().endswith(".shp"): sparse = kwargs.get("sparse", False) kper = kwargs.get("kper", 0) squeeze = kwargs.get("squeeze", True) model_grid = mfl.model.modelgrid if model_grid is None: raise Exception("MfList.to_shapefile: ModelGrid is not set") import flopy.utils.flopy_io as fio if kper is None: keys = mfl.data.keys() keys.sort() else: keys = [kper] if not sparse: array_dict = {} for kk in keys: arrays = mfl.to_array(kk) for name, array in arrays.items(): for k in range(array.shape[0]): # aname = name+"{0:03d}_{1:02d}".format(kk, k) n = shapefile_utils.shape_attr_name(name, length=4) aname = "{}{}{}".format(n, k + 1, int(kk) + 1) array_dict[aname] = array[k] shapefile_utils.write_grid_shapefile2(f, model_grid, array_dict) else: from ..export.shapefile_utils import recarray2shp from ..utils.geometry import Polygon #if np.isscalar(kper): # kper = [kper] model_grid = mfl.mg df = mfl.get_dataframe(squeeze=squeeze) if 'kper' in kwargs or df is None: ra = mfl[kper] verts = np.array(model_grid.get_cell_vertices(ra.i, ra.j)) elif df is not None: verts = np.array([model_grid.get_cell_vertices(i, df.j.values[ix]) for ix, i in enumerate(df.i.values)]) ra = df.to_records(index=False) epsg = kwargs.get('epsg', None) prj = kwargs.get('prj', None) polys = np.array([Polygon(v) for v in verts]) recarray2shp(ra, geoms=polys, shpname=f, mg=model_grid, epsg=epsg, prj=prj) elif isinstance(f, NetCdf) or isinstance(f, dict): base_name = mfl.package.name[0].lower() # f.log("getting 4D masked arrays for {0}".format(base_name)) # m4d = mfl.masked_4D_arrays # f.log("getting 4D masked arrays for {0}".format(base_name)) # for name, array in m4d.items(): for name, array in mfl.masked_4D_arrays_itr(): var_name = base_name + '_' + name if isinstance(f, dict): f[var_name] = array continue f.log("processing {0} attribute".format(name)) units = None if var_name in NC_UNITS_FORMAT: units = NC_UNITS_FORMAT[var_name].format(f.grid_units, f.time_units) precision_str = NC_PRECISION_TYPE[mfl.dtype[name].type] if var_name in NC_LONG_NAMES: attribs = {"long_name": NC_LONG_NAMES[var_name]} else: attribs = {"long_name": var_name} attribs["coordinates"] = "time layer latitude longitude" attribs["min"] = np.nanmin(array) attribs["max"] = np.nanmax(array) if np.isnan(attribs["min"]) or np.isnan(attribs["max"]): raise Exception( "error processing {0}: all NaNs".format(var_name)) if units is not None: attribs["units"] = units try: dim_tuple = ("time",) + f.dimension_names var = f.create_variable(var_name, attribs, precision_str=precision_str, dimensions=dim_tuple) except Exception as e: estr = "error creating variable {0}:\n{1}".format(var_name, str(e)) f.logger.warn(estr) raise Exception(estr) array[np.isnan(array)] = f.fillvalue try: var[:] = array except Exception as e: estr = "error setting array to variable {0}:\n{1}".format( var_name, str(e)) f.logger.warn(estr) raise Exception(estr) f.log("processing {0} attribute".format(name)) return f else: raise NotImplementedError("unrecognized export argument:{0}".format(f))