flopy 3.2.1__zip → 3.2.2__zip
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.
- {flopy-3.2.1 → flopy-3.2.2}/PKG-INFO +47 -11
- {flopy-3.2.1 → flopy-3.2.2}/flopy/mbase.py +307 -17
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mf.py +8 -6
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfbcf.py +2 -2
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfchd.py +1 -1
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfde4.py +2 -2
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfdis.py +11 -94
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfdrn.py +1 -1
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfevt.py +3 -3
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfghb.py +2 -2
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfgmg.py +60 -19
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfhfb.py +7 -7
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mflpf.py +13 -10
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfmlt.py +3 -3
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfnwt.py +1 -1
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfoc.py +26 -20
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfoc88.py +9 -9
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfpar.py +15 -9
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfparbc.py +7 -7
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfpcg.py +2 -2
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfpcgn.py +3 -3
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfpks.py +1 -1
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfrch.py +4 -4
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfriv.py +6 -4
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfsip.py +2 -2
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfsor.py +3 -3
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfswi2.py +34 -34
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfswr1.py +4 -4
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfupw.py +4 -4
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfuzf1.py +5 -5
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfwel.py +1 -2
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfzon.py +2 -2
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modpath/mp.py +7 -5
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modpath/mpbas.py +1 -1
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modpath/mpsim.py +18 -16
- {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mt.py +1 -1
- {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mtbtn.py +3 -3
- {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mtssm.py +7 -6
- {flopy-3.2.1 → flopy-3.2.2}/flopy/plot/__init__.py +1 -1
- {flopy-3.2.1 → flopy-3.2.2}/flopy/plot/crosssection.py +73 -103
- flopy-3.2.2/flopy/plot/map.py +647 -0
- flopy-3.2.2/flopy/plot/plotutil.py +1205 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/utils/__init__.py +3 -1
- {flopy-3.2.1 → flopy-3.2.2}/flopy/utils/binaryfile.py +91 -364
- {flopy-3.2.1 → flopy-3.2.2}/flopy/utils/binaryhydmodfile.py +3 -3
- {flopy-3.2.1 → flopy-3.2.2}/flopy/utils/binaryswrfile.py +21 -21
- flopy-3.2.2/flopy/utils/datafile.py +476 -0
- flopy-3.2.2/flopy/utils/flopy_io.py +128 -0
- flopy-3.2.2/flopy/utils/formattedfile.py +366 -0
- flopy-3.2.2/flopy/utils/modpathfile.py +421 -0
- flopy-3.2.2/flopy/utils/reference.py +386 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/utils/util_array.py +512 -83
- {flopy-3.2.1 → flopy-3.2.2}/flopy/utils/util_list.py +234 -13
- flopy-3.2.2/flopy/version.py +4 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy.egg-info/PKG-INFO +47 -11
- {flopy-3.2.1 → flopy-3.2.2}/flopy.egg-info/SOURCES.txt +5 -0
- {flopy-3.2.1 → flopy-3.2.2}/setup.py +2 -6
- flopy-3.2.1/flopy/plot/map.py +0 -592
- flopy-3.2.1/flopy/plot/plotutil.py +0 -512
- flopy-3.2.1/flopy/version.py +0 -4
- flopy-3.2.1/requirements.txt +0 -2
- {flopy-3.2.1 → flopy-3.2.2}/flopy/__init__.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/__init__.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfaddoutsidefile.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfbas.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfbct.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mflmt.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfmnw1.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfmnw2.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfmnwi.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfpbc.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfpval.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfsms.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfswi.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/modpath/__init__.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/__init__.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mtadv.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mtdsp.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mtgcg.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mtphc.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mtrct.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mttob.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/seawat/__init__.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/seawat/swt.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/seawat/swtvdf.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy/utils/mfreadnam.py +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy.egg-info/dependency_links.txt +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy.egg-info/requires.txt +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/flopy.egg-info/top_level.txt +0 -0
- {flopy-3.2.1 → flopy-3.2.2}/setup.cfg +0 -0
|
@@ -12,16 +12,16 @@ import os
|
|
|
12
12
|
import shutil
|
|
13
13
|
import copy
|
|
14
14
|
import numpy as np
|
|
15
|
-
|
|
15
|
+
import flopy.utils
|
|
16
16
|
VERBOSE = False
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def decode_fortran_descriptor(fd):
|
|
21
|
-
|
|
21
|
+
# strip off any quotes around format string
|
|
22
22
|
fd = fd.replace("'", "")
|
|
23
23
|
fd = fd.replace('"', '')
|
|
24
|
-
|
|
24
|
+
# strip off '(' and ')'
|
|
25
25
|
fd = fd.strip()[1:-1]
|
|
26
26
|
if str('FREE') in str(fd.upper()):
|
|
27
27
|
return 'free', None, None, None
|
|
@@ -38,7 +38,7 @@ def decode_fortran_descriptor(fd):
|
|
|
38
38
|
for fmt in fmts:
|
|
39
39
|
if fmt in raw:
|
|
40
40
|
raw = raw.split(fmt)
|
|
41
|
-
|
|
41
|
+
# '(F9.0)' will return raw = ['', '9']
|
|
42
42
|
# try and except will catch this
|
|
43
43
|
try:
|
|
44
44
|
npl = int(raw[0])
|
|
@@ -87,14 +87,16 @@ def read1d(f, a):
|
|
|
87
87
|
return a
|
|
88
88
|
|
|
89
89
|
def array2string(a, fmt_tup):
|
|
90
|
-
|
|
90
|
+
"""
|
|
91
|
+
Converts a 1D or 2D array into a string
|
|
91
92
|
Input:
|
|
92
93
|
a: array
|
|
93
94
|
fmt_tup = (npl,fmt_str)
|
|
94
95
|
fmt_str: format string
|
|
95
96
|
npl: number of numbers per line
|
|
96
97
|
Output:
|
|
97
|
-
s: string representation of the array
|
|
98
|
+
s: string representation of the array
|
|
99
|
+
"""
|
|
98
100
|
|
|
99
101
|
aa = np.atleast_2d(a)
|
|
100
102
|
nr, nc = np.shape(aa)[0:2]
|
|
@@ -104,7 +106,7 @@ def array2string(a, fmt_tup):
|
|
|
104
106
|
s = ''
|
|
105
107
|
for r in range(nr):
|
|
106
108
|
for c in range(nc):
|
|
107
|
-
|
|
109
|
+
# fix for numpy 1.6 bug
|
|
108
110
|
if aa.dtype == 'float32':
|
|
109
111
|
s = s + (fmt_str.format(float(aa[r, c])))
|
|
110
112
|
else:
|
|
@@ -152,10 +154,11 @@ def u2d_like(model, other):
|
|
|
152
154
|
|
|
153
155
|
|
|
154
156
|
# class meta_interceptor(type):
|
|
155
|
-
#
|
|
157
|
+
# """
|
|
158
|
+
# meta class to catch existing instances of util_2d,
|
|
156
159
|
# transient_2d and util_3d to prevent re-instantiating them.
|
|
157
160
|
# a lot of python trickery here...
|
|
158
|
-
#
|
|
161
|
+
# """
|
|
159
162
|
# def __call__(cls, *args, **kwds):
|
|
160
163
|
# for a in args:
|
|
161
164
|
# if isinstance(a, util_2d) or isinstance(a, util_3d):
|
|
@@ -229,8 +232,9 @@ class util_3d(object):
|
|
|
229
232
|
|
|
230
233
|
def __init__(self, model, shape, dtype, value, name,
|
|
231
234
|
fmtin=None, cnstnt=1.0, iprn=-1, locat=None, ext_unit_dict=None):
|
|
232
|
-
|
|
233
|
-
|
|
235
|
+
"""
|
|
236
|
+
3-D wrapper from util_2d - shape must be 3-D
|
|
237
|
+
"""
|
|
234
238
|
if isinstance(value,util_3d):
|
|
235
239
|
for attr in value.__dict__.items():
|
|
236
240
|
setattr(self,attr[0],attr[1])
|
|
@@ -251,6 +255,135 @@ class util_3d(object):
|
|
|
251
255
|
model.external_path, self.name_base.replace(' ', '_'))
|
|
252
256
|
self.util_2ds = self.build_2d_instances()
|
|
253
257
|
|
|
258
|
+
|
|
259
|
+
def to_shapefile(self, filename):
|
|
260
|
+
"""
|
|
261
|
+
Export 3-D model data to shapefile (polygons). Adds an
|
|
262
|
+
attribute for each util_2d in self.u2ds
|
|
263
|
+
|
|
264
|
+
Parameters
|
|
265
|
+
----------
|
|
266
|
+
filename : str
|
|
267
|
+
Shapefile name to write
|
|
268
|
+
|
|
269
|
+
Returns
|
|
270
|
+
----------
|
|
271
|
+
None
|
|
272
|
+
|
|
273
|
+
See Also
|
|
274
|
+
--------
|
|
275
|
+
|
|
276
|
+
Notes
|
|
277
|
+
-----
|
|
278
|
+
|
|
279
|
+
Examples
|
|
280
|
+
--------
|
|
281
|
+
>>> import flopy
|
|
282
|
+
>>> ml = flopy.modflow.Modflow.load('test.nam')
|
|
283
|
+
>>> ml.lpf.hk.to_shapefile('test_hk.shp')
|
|
284
|
+
"""
|
|
285
|
+
|
|
286
|
+
from flopy.utils.flopy_io import write_grid_shapefile
|
|
287
|
+
array_dict = {}
|
|
288
|
+
for ilay in range(self.model.nlay):
|
|
289
|
+
u2d = self[ilay]
|
|
290
|
+
array_dict[u2d.name] = u2d.array
|
|
291
|
+
write_grid_shapefile(filename, self.model.dis.sr,
|
|
292
|
+
array_dict)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def plot(self, filename_base=None, file_extension=None, mflay=None,
|
|
296
|
+
fignum=None, **kwargs):
|
|
297
|
+
"""
|
|
298
|
+
Plot 3-D model input data
|
|
299
|
+
|
|
300
|
+
Parameters
|
|
301
|
+
----------
|
|
302
|
+
filename_base : str
|
|
303
|
+
Base file name that will be used to automatically generate file
|
|
304
|
+
names for output image files. Plots will be exported as image
|
|
305
|
+
files if file_name_base is not None. (default is None)
|
|
306
|
+
file_extension : str
|
|
307
|
+
Valid matplotlib.pyplot file extension for savefig(). Only used
|
|
308
|
+
if filename_base is not None. (default is 'png')
|
|
309
|
+
mflay : int
|
|
310
|
+
MODFLOW zero-based layer number to return. If None, then all
|
|
311
|
+
all layers will be included. (default is None)
|
|
312
|
+
**kwargs : dict
|
|
313
|
+
axes : list of matplotlib.pyplot.axis
|
|
314
|
+
List of matplotlib.pyplot.axis that will be used to plot
|
|
315
|
+
data for each layer. If axes=None axes will be generated.
|
|
316
|
+
(default is None)
|
|
317
|
+
pcolor : bool
|
|
318
|
+
Boolean used to determine if matplotlib.pyplot.pcolormesh
|
|
319
|
+
plot will be plotted. (default is True)
|
|
320
|
+
colorbar : bool
|
|
321
|
+
Boolean used to determine if a color bar will be added to
|
|
322
|
+
the matplotlib.pyplot.pcolormesh. Only used if pcolor=True.
|
|
323
|
+
(default is False)
|
|
324
|
+
inactive : bool
|
|
325
|
+
Boolean used to determine if a black overlay in inactive
|
|
326
|
+
cells in a layer will be displayed. (default is True)
|
|
327
|
+
contour : bool
|
|
328
|
+
Boolean used to determine if matplotlib.pyplot.contour
|
|
329
|
+
plot will be plotted. (default is False)
|
|
330
|
+
clabel : bool
|
|
331
|
+
Boolean used to determine if matplotlib.pyplot.clabel
|
|
332
|
+
will be plotted. Only used if contour=True. (default is False)
|
|
333
|
+
grid : bool
|
|
334
|
+
Boolean used to determine if the model grid will be plotted
|
|
335
|
+
on the figure. (default is False)
|
|
336
|
+
masked_values : list
|
|
337
|
+
List of unique values to be excluded from the plot.
|
|
338
|
+
|
|
339
|
+
Returns
|
|
340
|
+
----------
|
|
341
|
+
out : list
|
|
342
|
+
Empty list is returned if filename_base is not None. Otherwise
|
|
343
|
+
a list of matplotlib.pyplot.axis is returned.
|
|
344
|
+
|
|
345
|
+
See Also
|
|
346
|
+
--------
|
|
347
|
+
|
|
348
|
+
Notes
|
|
349
|
+
-----
|
|
350
|
+
|
|
351
|
+
Examples
|
|
352
|
+
--------
|
|
353
|
+
>>> import flopy
|
|
354
|
+
>>> ml = flopy.modflow.Modflow.load('test.nam')
|
|
355
|
+
>>> ml.lpf.hk.plot()
|
|
356
|
+
|
|
357
|
+
"""
|
|
358
|
+
import flopy.plot.plotutil as pu
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
if file_extension is not None:
|
|
362
|
+
fext = file_extension
|
|
363
|
+
else:
|
|
364
|
+
fext = 'png'
|
|
365
|
+
|
|
366
|
+
names = ['{} layer {}'.format(self.name, k+1) for k in range(self.shape[0])]
|
|
367
|
+
|
|
368
|
+
filenames = None
|
|
369
|
+
if filename_base is not None:
|
|
370
|
+
if mflay is not None:
|
|
371
|
+
i0 = int(mflay)
|
|
372
|
+
if i0+1 >= self.shape[0]:
|
|
373
|
+
i0 = self.shape[0] - 1
|
|
374
|
+
i1 = i0 + 1
|
|
375
|
+
else:
|
|
376
|
+
i0 = 0
|
|
377
|
+
i1 = self.shape[0]
|
|
378
|
+
# build filenames
|
|
379
|
+
filenames = ['{}_{}_Layer{}.{}'.format(filename_base, self.name,
|
|
380
|
+
k+1, fext) for k in range(i0, i1)]
|
|
381
|
+
|
|
382
|
+
return pu._plot_array_helper(self.array, self.model,
|
|
383
|
+
names=names, filenames=filenames,
|
|
384
|
+
mflay=mflay, fignum=fignum, **kwargs)
|
|
385
|
+
|
|
386
|
+
|
|
254
387
|
def __getitem__(self, k):
|
|
255
388
|
if isinstance(k, int):
|
|
256
389
|
return self.util_2ds[k]
|
|
@@ -279,12 +412,12 @@ class util_3d(object):
|
|
|
279
412
|
|
|
280
413
|
def build_2d_instances(self):
|
|
281
414
|
u2ds = []
|
|
282
|
-
|
|
415
|
+
# if value is not enumerable, then make a list of something
|
|
283
416
|
if not isinstance(self.__value, list) \
|
|
284
417
|
and not isinstance(self.__value, np.ndarray):
|
|
285
418
|
self.__value = [self.__value] * self.shape[0]
|
|
286
419
|
|
|
287
|
-
|
|
420
|
+
# if this is a list or 1-D array with constant values per layer
|
|
288
421
|
if isinstance(self.__value, list) \
|
|
289
422
|
or (isinstance(self.__value, np.ndarray)
|
|
290
423
|
and (self.__value.ndim == 1)):
|
|
@@ -308,7 +441,7 @@ class util_3d(object):
|
|
|
308
441
|
u2ds.append(u2d)
|
|
309
442
|
|
|
310
443
|
elif isinstance(self.__value, np.ndarray):
|
|
311
|
-
|
|
444
|
+
# if an array of shape nrow,ncol was passed, tile it out for each layer
|
|
312
445
|
if self.__value.shape[0] != self.shape[0]:
|
|
313
446
|
if self.__value.shape == (self.shape[1], self.shape[2]):
|
|
314
447
|
self.__value = [self.__value] * self.shape[0]
|
|
@@ -361,6 +494,7 @@ class util_3d(object):
|
|
|
361
494
|
return util_3d(self.model,self.shape,self.dtype,new_u2ds,
|
|
362
495
|
self.name,self.fmtin,self.cnstnt,self.iprn,
|
|
363
496
|
self.locat)
|
|
497
|
+
|
|
364
498
|
#class transient_2d((with_metaclass(meta_interceptor, object))):
|
|
365
499
|
class transient_2d(object):
|
|
366
500
|
"""
|
|
@@ -429,7 +563,7 @@ class transient_2d(object):
|
|
|
429
563
|
|
|
430
564
|
"""
|
|
431
565
|
|
|
432
|
-
def __init__(self,model, shape, dtype, value, name=None, fmtin=None,
|
|
566
|
+
def __init__(self, model, shape, dtype, value, name=None, fmtin=None,
|
|
433
567
|
cnstnt=1.0, iprn=-1, ext_filename=None, locat=None, bin=False):
|
|
434
568
|
|
|
435
569
|
if isinstance(value,transient_2d):
|
|
@@ -456,12 +590,178 @@ class transient_2d(object):
|
|
|
456
590
|
self.transient_2ds = self.build_transient_sequence()
|
|
457
591
|
|
|
458
592
|
def get_zero_2d(self, kper):
|
|
459
|
-
name = self.name_base + str(kper + 1) +
|
|
593
|
+
name = self.name_base + str(kper + 1) + '(filled zero)'
|
|
460
594
|
return util_2d(self.model, self.shape,
|
|
461
595
|
self.dtype, 0.0, name=name).get_file_entry()
|
|
462
596
|
|
|
597
|
+
|
|
598
|
+
def to_shapefile(self, filename):
|
|
599
|
+
"""
|
|
600
|
+
Export transient 2D data to a shapefile (as polygons). Adds an
|
|
601
|
+
attribute for each unique util_2d instance in self.data
|
|
602
|
+
|
|
603
|
+
Parameters
|
|
604
|
+
----------
|
|
605
|
+
filename : str
|
|
606
|
+
Shapefile name to write
|
|
607
|
+
|
|
608
|
+
Returns
|
|
609
|
+
----------
|
|
610
|
+
None
|
|
611
|
+
|
|
612
|
+
See Also
|
|
613
|
+
--------
|
|
614
|
+
|
|
615
|
+
Notes
|
|
616
|
+
-----
|
|
617
|
+
|
|
618
|
+
Examples
|
|
619
|
+
--------
|
|
620
|
+
>>> import flopy
|
|
621
|
+
>>> ml = flopy.modflow.Modflow.load('test.nam')
|
|
622
|
+
>>> ml.rch.rech.as_shapefile('test_rech.shp')
|
|
623
|
+
"""
|
|
624
|
+
from flopy.utils.flopy_io import write_grid_shapefile
|
|
625
|
+
array_dict = {}
|
|
626
|
+
for kper in range(self.model.nper):
|
|
627
|
+
u2d = self[kper]
|
|
628
|
+
array_dict[u2d.name] = u2d.array
|
|
629
|
+
write_grid_shapefile(filename, self.model.dis.sr, array_dict)
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
def plot(self, filename_base=None, file_extension=None, **kwargs):
|
|
633
|
+
"""
|
|
634
|
+
Plot transient 2-D model input data
|
|
635
|
+
|
|
636
|
+
Parameters
|
|
637
|
+
----------
|
|
638
|
+
filename_base : str
|
|
639
|
+
Base file name that will be used to automatically generate file
|
|
640
|
+
names for output image files. Plots will be exported as image
|
|
641
|
+
files if file_name_base is not None. (default is None)
|
|
642
|
+
file_extension : str
|
|
643
|
+
Valid matplotlib.pyplot file extension for savefig(). Only used
|
|
644
|
+
if filename_base is not None. (default is 'png')
|
|
645
|
+
**kwargs : dict
|
|
646
|
+
axes : list of matplotlib.pyplot.axis
|
|
647
|
+
List of matplotlib.pyplot.axis that will be used to plot
|
|
648
|
+
data for each layer. If axes=None axes will be generated.
|
|
649
|
+
(default is None)
|
|
650
|
+
pcolor : bool
|
|
651
|
+
Boolean used to determine if matplotlib.pyplot.pcolormesh
|
|
652
|
+
plot will be plotted. (default is True)
|
|
653
|
+
colorbar : bool
|
|
654
|
+
Boolean used to determine if a color bar will be added to
|
|
655
|
+
the matplotlib.pyplot.pcolormesh. Only used if pcolor=True.
|
|
656
|
+
(default is False)
|
|
657
|
+
inactive : bool
|
|
658
|
+
Boolean used to determine if a black overlay in inactive
|
|
659
|
+
cells in a layer will be displayed. (default is True)
|
|
660
|
+
contour : bool
|
|
661
|
+
Boolean used to determine if matplotlib.pyplot.contour
|
|
662
|
+
plot will be plotted. (default is False)
|
|
663
|
+
clabel : bool
|
|
664
|
+
Boolean used to determine if matplotlib.pyplot.clabel
|
|
665
|
+
will be plotted. Only used if contour=True. (default is False)
|
|
666
|
+
grid : bool
|
|
667
|
+
Boolean used to determine if the model grid will be plotted
|
|
668
|
+
on the figure. (default is False)
|
|
669
|
+
masked_values : list
|
|
670
|
+
List of unique values to be excluded from the plot.
|
|
671
|
+
kper : str
|
|
672
|
+
MODFLOW zero-based stress period number to return. If
|
|
673
|
+
kper='all' then data for all stress period will be
|
|
674
|
+
extracted. (default is zero).
|
|
675
|
+
|
|
676
|
+
Returns
|
|
677
|
+
----------
|
|
678
|
+
out : list
|
|
679
|
+
Empty list is returned if filename_base is not None. Otherwise
|
|
680
|
+
a list of matplotlib.pyplot.axis is returned.
|
|
681
|
+
|
|
682
|
+
See Also
|
|
683
|
+
--------
|
|
684
|
+
|
|
685
|
+
Notes
|
|
686
|
+
-----
|
|
687
|
+
|
|
688
|
+
Examples
|
|
689
|
+
--------
|
|
690
|
+
>>> import flopy
|
|
691
|
+
>>> ml = flopy.modflow.Modflow.load('test.nam')
|
|
692
|
+
>>> ml.rch.rech.plot()
|
|
693
|
+
|
|
694
|
+
"""
|
|
695
|
+
import flopy.plot.plotutil as pu
|
|
696
|
+
|
|
697
|
+
if file_extension is not None:
|
|
698
|
+
fext = file_extension
|
|
699
|
+
else:
|
|
700
|
+
fext = 'png'
|
|
701
|
+
|
|
702
|
+
if 'kper' in kwargs:
|
|
703
|
+
kk = kwargs['kper']
|
|
704
|
+
kwargs.pop('kper')
|
|
705
|
+
try:
|
|
706
|
+
kk = kk.lower()
|
|
707
|
+
if kk == 'all':
|
|
708
|
+
k0 = 0
|
|
709
|
+
k1 = self.model.nper
|
|
710
|
+
else:
|
|
711
|
+
k0 = 0
|
|
712
|
+
k1 = 1
|
|
713
|
+
except:
|
|
714
|
+
k0 = int(kk)
|
|
715
|
+
k1 = k0 + 1
|
|
716
|
+
# if kwargs['kper'] == 'all':
|
|
717
|
+
# kwargs.pop('kper')
|
|
718
|
+
# k0 = 0
|
|
719
|
+
# k1 = self.model.nper
|
|
720
|
+
# else:
|
|
721
|
+
# k0 = int(kwargs.pop('kper'))
|
|
722
|
+
# k1 = k0 + 1
|
|
723
|
+
else:
|
|
724
|
+
k0 = 0
|
|
725
|
+
k1 = 1
|
|
726
|
+
|
|
727
|
+
if 'fignum' in kwargs:
|
|
728
|
+
fignum = kwargs.pop('fignum')
|
|
729
|
+
else:
|
|
730
|
+
fignum = list(range(k0, k1))
|
|
731
|
+
|
|
732
|
+
if 'mflay' in kwargs:
|
|
733
|
+
kwargs.pop('mflay')
|
|
734
|
+
|
|
735
|
+
axes = []
|
|
736
|
+
for idx, kper in enumerate(range(k0, k1)):
|
|
737
|
+
title = '{} stress period {:d}'.\
|
|
738
|
+
format(self.name_base.replace('_', '').upper(),
|
|
739
|
+
kper+1)
|
|
740
|
+
if filename_base is not None:
|
|
741
|
+
filename = filename_base + '_{:05d}.{}'.format(kper+1, fext)
|
|
742
|
+
else:
|
|
743
|
+
filename = None
|
|
744
|
+
axes.append(pu._plot_array_helper(self[kper].array, self.model,
|
|
745
|
+
names=title, filenames=filename,
|
|
746
|
+
fignum=fignum[idx], **kwargs))
|
|
747
|
+
return axes
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
def __getitem__(self, kper):
|
|
751
|
+
if kper in list(self.transient_2ds.keys()):
|
|
752
|
+
return self.transient_2ds[kper]
|
|
753
|
+
elif kper < min(self.transient_2ds.keys()):
|
|
754
|
+
return self.get_zero_2d(kper)
|
|
755
|
+
else:
|
|
756
|
+
for i in range(kper,0,-1):
|
|
757
|
+
if i in list(self.transient_2ds.keys()):
|
|
758
|
+
return self.transient_2ds[i]
|
|
759
|
+
raise Exception("transient_2d.__getitem__(): error:" +\
|
|
760
|
+
" could find an entry before kper {0:d}".format(kper))
|
|
761
|
+
|
|
463
762
|
def get_kper_entry(self, kper):
|
|
464
|
-
"""
|
|
763
|
+
"""
|
|
764
|
+
get the file entry info for a given kper
|
|
465
765
|
returns (itmp,file entry string from util_2d)
|
|
466
766
|
"""
|
|
467
767
|
if kper in list(self.transient_2ds.keys()):
|
|
@@ -472,7 +772,8 @@ class transient_2d(object):
|
|
|
472
772
|
return (-1, '')
|
|
473
773
|
|
|
474
774
|
def build_transient_sequence(self):
|
|
475
|
-
"""
|
|
775
|
+
"""
|
|
776
|
+
parse self.__value into a dict{kper:util_2d}
|
|
476
777
|
"""
|
|
477
778
|
|
|
478
779
|
# a dict keyed on kper (zero-based)
|
|
@@ -519,7 +820,8 @@ class transient_2d(object):
|
|
|
519
820
|
|
|
520
821
|
|
|
521
822
|
def __get_2d_instance(self,kper,arg):
|
|
522
|
-
"""
|
|
823
|
+
"""
|
|
824
|
+
parse an argument into a util_2d instance
|
|
523
825
|
"""
|
|
524
826
|
ext_filename = None
|
|
525
827
|
name = self.name_base+str(kper + 1)
|
|
@@ -596,7 +898,8 @@ class util_2d(object):
|
|
|
596
898
|
def __init__(self, model, shape, dtype, value, name=None, fmtin=None,
|
|
597
899
|
cnstnt=1.0, iprn=-1, ext_filename=None, locat=None, bin=False,
|
|
598
900
|
ext_unit_dict=None):
|
|
599
|
-
|
|
901
|
+
"""
|
|
902
|
+
1d or 2-d array support with minimum of mem footprint.
|
|
600
903
|
only creates arrays as needed,
|
|
601
904
|
otherwise functions with strings or constants
|
|
602
905
|
shape = 1-d or 2-d tuple
|
|
@@ -608,10 +911,10 @@ class util_2d(object):
|
|
|
608
911
|
model instance string attribute "external_path"
|
|
609
912
|
used to determine external array writing
|
|
610
913
|
bin controls writing of binary external arrays
|
|
611
|
-
|
|
612
|
-
if isinstance(value,util_2d):
|
|
914
|
+
"""
|
|
915
|
+
if isinstance(value, util_2d):
|
|
613
916
|
for attr in value.__dict__.items():
|
|
614
|
-
setattr(self,attr[0],attr[1])
|
|
917
|
+
setattr(self, attr[0], attr[1])
|
|
615
918
|
return
|
|
616
919
|
self.model = model
|
|
617
920
|
self.shape = shape
|
|
@@ -624,12 +927,12 @@ class util_2d(object):
|
|
|
624
927
|
self.cnstnt = float(cnstnt)
|
|
625
928
|
self.iprn = iprn
|
|
626
929
|
self.ext_filename = None
|
|
627
|
-
|
|
930
|
+
# just for testing
|
|
628
931
|
if hasattr(model, 'use_existing'):
|
|
629
932
|
self.use_existing = bool(model.use_existing)
|
|
630
933
|
else:
|
|
631
934
|
self.use_existing = False
|
|
632
|
-
|
|
935
|
+
# set fmtin
|
|
633
936
|
if fmtin is not None:
|
|
634
937
|
self.fmtin = fmtin
|
|
635
938
|
else:
|
|
@@ -645,10 +948,10 @@ class util_2d(object):
|
|
|
645
948
|
else:
|
|
646
949
|
self.fmtin = '(' + str(npl) + 'G15.6) '
|
|
647
950
|
|
|
648
|
-
|
|
951
|
+
# get (npl,python_format_descriptor) from fmtin
|
|
649
952
|
self.py_desc = self.fort_2_py(self.fmtin)
|
|
650
953
|
|
|
651
|
-
|
|
954
|
+
# some defense
|
|
652
955
|
if dtype not in [np.int, np.float32, np.bool]:
|
|
653
956
|
raise Exception('util_2d:unsupported dtype: ' + str(dtype))
|
|
654
957
|
if self.model.external_path != None and name == None \
|
|
@@ -666,6 +969,115 @@ class util_2d(object):
|
|
|
666
969
|
if self.bin and self.ext_filename is None:
|
|
667
970
|
raise Exception('util_2d: binary flag requires ext_filename')
|
|
668
971
|
|
|
972
|
+
def plot(self, title=None, filename_base=None, file_extension=None,
|
|
973
|
+
fignum=None, **kwargs):
|
|
974
|
+
"""
|
|
975
|
+
Plot 2-D model input data
|
|
976
|
+
|
|
977
|
+
Parameters
|
|
978
|
+
----------
|
|
979
|
+
title : str
|
|
980
|
+
Plot title. If a plot title is not provide one will be
|
|
981
|
+
created based on data name (self.name). (default is None)
|
|
982
|
+
filename_base : str
|
|
983
|
+
Base file name that will be used to automatically generate file
|
|
984
|
+
names for output image files. Plots will be exported as image
|
|
985
|
+
files if file_name_base is not None. (default is None)
|
|
986
|
+
file_extension : str
|
|
987
|
+
Valid matplotlib.pyplot file extension for savefig(). Only used
|
|
988
|
+
if filename_base is not None. (default is 'png')
|
|
989
|
+
**kwargs : dict
|
|
990
|
+
axes : list of matplotlib.pyplot.axis
|
|
991
|
+
List of matplotlib.pyplot.axis that will be used to plot
|
|
992
|
+
data for each layer. If axes=None axes will be generated.
|
|
993
|
+
(default is None)
|
|
994
|
+
pcolor : bool
|
|
995
|
+
Boolean used to determine if matplotlib.pyplot.pcolormesh
|
|
996
|
+
plot will be plotted. (default is True)
|
|
997
|
+
colorbar : bool
|
|
998
|
+
Boolean used to determine if a color bar will be added to
|
|
999
|
+
the matplotlib.pyplot.pcolormesh. Only used if pcolor=True.
|
|
1000
|
+
(default is False)
|
|
1001
|
+
inactive : bool
|
|
1002
|
+
Boolean used to determine if a black overlay in inactive
|
|
1003
|
+
cells in a layer will be displayed. (default is True)
|
|
1004
|
+
contour : bool
|
|
1005
|
+
Boolean used to determine if matplotlib.pyplot.contour
|
|
1006
|
+
plot will be plotted. (default is False)
|
|
1007
|
+
clabel : bool
|
|
1008
|
+
Boolean used to determine if matplotlib.pyplot.clabel
|
|
1009
|
+
will be plotted. Only used if contour=True. (default is False)
|
|
1010
|
+
grid : bool
|
|
1011
|
+
Boolean used to determine if the model grid will be plotted
|
|
1012
|
+
on the figure. (default is False)
|
|
1013
|
+
masked_values : list
|
|
1014
|
+
List of unique values to be excluded from the plot.
|
|
1015
|
+
|
|
1016
|
+
Returns
|
|
1017
|
+
----------
|
|
1018
|
+
out : list
|
|
1019
|
+
Empty list is returned if filename_base is not None. Otherwise
|
|
1020
|
+
a list of matplotlib.pyplot.axis is returned.
|
|
1021
|
+
|
|
1022
|
+
See Also
|
|
1023
|
+
--------
|
|
1024
|
+
|
|
1025
|
+
Notes
|
|
1026
|
+
-----
|
|
1027
|
+
|
|
1028
|
+
Examples
|
|
1029
|
+
--------
|
|
1030
|
+
>>> import flopy
|
|
1031
|
+
>>> ml = flopy.modflow.Modflow.load('test.nam')
|
|
1032
|
+
>>> ml.dis.top.plot()
|
|
1033
|
+
|
|
1034
|
+
"""
|
|
1035
|
+
import flopy.plot.plotutil as pu
|
|
1036
|
+
if title is None:
|
|
1037
|
+
title = self.name
|
|
1038
|
+
|
|
1039
|
+
if file_extension is not None:
|
|
1040
|
+
fext = file_extension
|
|
1041
|
+
else:
|
|
1042
|
+
fext = 'png'
|
|
1043
|
+
|
|
1044
|
+
filename = None
|
|
1045
|
+
if filename_base is not None:
|
|
1046
|
+
filename = '{}_{}.{}'.format(filename_base, self.name, fext)
|
|
1047
|
+
|
|
1048
|
+
return pu._plot_array_helper(self.array, self.model,
|
|
1049
|
+
names=title, filenames=filename,
|
|
1050
|
+
fignum=fignum, **kwargs)
|
|
1051
|
+
|
|
1052
|
+
|
|
1053
|
+
def to_shapefile(self, filename):
|
|
1054
|
+
"""
|
|
1055
|
+
Export 2-D model data to a shapefile (as polygons) of self.array
|
|
1056
|
+
|
|
1057
|
+
Parameters
|
|
1058
|
+
----------
|
|
1059
|
+
filename : str
|
|
1060
|
+
Shapefile name to write
|
|
1061
|
+
|
|
1062
|
+
Returns
|
|
1063
|
+
----------
|
|
1064
|
+
None
|
|
1065
|
+
|
|
1066
|
+
See Also
|
|
1067
|
+
--------
|
|
1068
|
+
|
|
1069
|
+
Notes
|
|
1070
|
+
-----
|
|
1071
|
+
|
|
1072
|
+
Examples
|
|
1073
|
+
--------
|
|
1074
|
+
>>> import flopy
|
|
1075
|
+
>>> ml = flopy.modflow.Modflow.load('test.nam')
|
|
1076
|
+
>>> ml.dis.top.as_shapefile('test_top.shp')
|
|
1077
|
+
"""
|
|
1078
|
+
from flopy.utils.flopy_io import write_grid_shapefile
|
|
1079
|
+
write_grid_shapefile(filename, self.model.dis.sr, {self.name: self.array})
|
|
1080
|
+
|
|
669
1081
|
@staticmethod
|
|
670
1082
|
def get_default_numpy_fmt(dtype):
|
|
671
1083
|
if dtype == np.int:
|
|
@@ -684,7 +1096,7 @@ class util_2d(object):
|
|
|
684
1096
|
def get_value(self):
|
|
685
1097
|
return self.__value
|
|
686
1098
|
|
|
687
|
-
|
|
1099
|
+
# overloads, tries to avoid creating arrays if possible
|
|
688
1100
|
def __add__(self, other):
|
|
689
1101
|
if self.vtype in [np.int, np.float32] and self.vtype == other.vtype:
|
|
690
1102
|
return self.__value + other.get_value()
|
|
@@ -699,7 +1111,7 @@ class util_2d(object):
|
|
|
699
1111
|
|
|
700
1112
|
def __getitem__(self, k):
|
|
701
1113
|
if isinstance(k, int):
|
|
702
|
-
|
|
1114
|
+
# this explicit cast is to handle a bug in numpy versions < 1.6.2
|
|
703
1115
|
if self.dtype == np.float32:
|
|
704
1116
|
return float(self.array[k])
|
|
705
1117
|
else:
|
|
@@ -714,8 +1126,9 @@ class util_2d(object):
|
|
|
714
1126
|
return self.array[(k,)]
|
|
715
1127
|
|
|
716
1128
|
def __setitem__(self, k, value):
|
|
717
|
-
|
|
718
|
-
|
|
1129
|
+
"""
|
|
1130
|
+
his one is dangerous because it resets __value
|
|
1131
|
+
"""
|
|
719
1132
|
a = self.array
|
|
720
1133
|
a[k] = value
|
|
721
1134
|
a = a.astype(self.dtype)
|
|
@@ -737,29 +1150,31 @@ class util_2d(object):
|
|
|
737
1150
|
return type(self.__value)
|
|
738
1151
|
|
|
739
1152
|
def get_file_entry(self):
|
|
740
|
-
|
|
1153
|
+
"""
|
|
1154
|
+
this is the entry point for getting an
|
|
741
1155
|
input file entry for this object
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
1156
|
+
"""
|
|
1157
|
+
# call get_file_array first in case we need to
|
|
1158
|
+
# get a new external unit number and reset self.locat
|
|
745
1159
|
vstring = self.get_file_array()
|
|
746
1160
|
cr = self.get_control_record()
|
|
747
1161
|
return cr+vstring
|
|
748
1162
|
|
|
749
1163
|
|
|
750
1164
|
def get_file_array(self):
|
|
751
|
-
|
|
1165
|
+
"""
|
|
1166
|
+
increments locat and update model instance if needed.
|
|
752
1167
|
if the value is a constant, or a string, or external,
|
|
753
1168
|
return an empty string
|
|
754
|
-
|
|
755
|
-
|
|
1169
|
+
"""
|
|
1170
|
+
# if the value is not a filename
|
|
756
1171
|
if self.vtype != str:
|
|
757
1172
|
|
|
758
|
-
|
|
759
|
-
|
|
1173
|
+
# if the ext_filename was passed, then we need
|
|
1174
|
+
# to write an external array
|
|
760
1175
|
if self.ext_filename != None:
|
|
761
|
-
|
|
762
|
-
|
|
1176
|
+
# if we need fixed format, reset self.locat and get a
|
|
1177
|
+
# new unit number
|
|
763
1178
|
if not self.model.free_format:
|
|
764
1179
|
self.locat = self.model.next_ext_unit()
|
|
765
1180
|
if self.bin:
|
|
@@ -768,7 +1183,7 @@ class util_2d(object):
|
|
|
768
1183
|
self.locat, binFlag=True)
|
|
769
1184
|
else:
|
|
770
1185
|
self.model.add_external(self.ext_filename, self.locat)
|
|
771
|
-
|
|
1186
|
+
# write external formatted or unformatted array
|
|
772
1187
|
if not self.use_existing:
|
|
773
1188
|
if not self.bin:
|
|
774
1189
|
f = open(self.ext_filename, 'w')
|
|
@@ -778,18 +1193,18 @@ class util_2d(object):
|
|
|
778
1193
|
a = self.array.tofile(self.ext_filename)
|
|
779
1194
|
return ''
|
|
780
1195
|
|
|
781
|
-
|
|
1196
|
+
# this internal array or constant
|
|
782
1197
|
else:
|
|
783
1198
|
if self.vtype is np.ndarray:
|
|
784
1199
|
return self.string
|
|
785
|
-
|
|
1200
|
+
# if this is a constant, return a null string
|
|
786
1201
|
else:
|
|
787
1202
|
return ''
|
|
788
1203
|
else:
|
|
789
1204
|
if os.path.exists(self.__value) and self.ext_filename is not None:
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
1205
|
+
# if this is a free format model, then we can use the same
|
|
1206
|
+
# ext file over and over - no need to copy
|
|
1207
|
+
# also, loosen things up with FREE format
|
|
793
1208
|
if self.model.free_format:
|
|
794
1209
|
self.ext_filename = self.__value
|
|
795
1210
|
self.fmtin = '(FREE)'
|
|
@@ -798,31 +1213,33 @@ class util_2d(object):
|
|
|
798
1213
|
else:
|
|
799
1214
|
if self.__value != self.ext_filename:
|
|
800
1215
|
shutil.copy2(self.__value, self.ext_filename)
|
|
801
|
-
|
|
802
|
-
|
|
1216
|
+
# if fixed format, we need to get a new unit number
|
|
1217
|
+
# and reset locat
|
|
803
1218
|
self.locat = self.model.next_ext_unit()
|
|
804
1219
|
self.model.add_external(self.ext_filename, self.locat)
|
|
805
1220
|
|
|
806
1221
|
return ''
|
|
807
|
-
|
|
808
|
-
|
|
1222
|
+
# otherwise, we need to load the the value filename
|
|
1223
|
+
# and return as a string
|
|
809
1224
|
else:
|
|
810
1225
|
return self.string
|
|
811
1226
|
|
|
812
1227
|
@property
|
|
813
1228
|
def string(self):
|
|
814
|
-
|
|
815
|
-
|
|
1229
|
+
"""
|
|
1230
|
+
get the string represenation of value attribute
|
|
1231
|
+
"""
|
|
816
1232
|
a = self.array
|
|
817
|
-
|
|
1233
|
+
# convert array to sting with specified format
|
|
818
1234
|
a_string = array2string(a,self.py_desc)
|
|
819
1235
|
return a_string
|
|
820
1236
|
|
|
821
1237
|
@property
|
|
822
1238
|
def array(self):
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
1239
|
+
"""
|
|
1240
|
+
get the array representation of value attribute
|
|
1241
|
+
if value is a string or a constant, the array is loaded/built only once
|
|
1242
|
+
"""
|
|
826
1243
|
if self.vtype == str:
|
|
827
1244
|
if self.__value_built is None:
|
|
828
1245
|
file_in = open(self.__value,'r')
|
|
@@ -841,12 +1258,13 @@ class util_2d(object):
|
|
|
841
1258
|
|
|
842
1259
|
@staticmethod
|
|
843
1260
|
def load_txt(shape, file_in, dtype, fmtin):
|
|
844
|
-
|
|
1261
|
+
"""
|
|
1262
|
+
load a (possibly wrapped format) array from a file
|
|
845
1263
|
(self.__value) and casts to the proper type (self.dtype)
|
|
846
1264
|
made static to support the load functionality
|
|
847
1265
|
this routine now supports fixed format arrays where the numbers
|
|
848
1266
|
may touch.
|
|
849
|
-
|
|
1267
|
+
"""
|
|
850
1268
|
#file_in = open(self.__value,'r')
|
|
851
1269
|
#file_in = open(filename,'r')
|
|
852
1270
|
#nrow,ncol = self.shape
|
|
@@ -892,25 +1310,25 @@ class util_2d(object):
|
|
|
892
1310
|
if np.isnan(np.sum(data)):
|
|
893
1311
|
raise Exception("util_2d.load_txt() error: np.NaN in data array")
|
|
894
1312
|
data.resize(nrow, ncol)
|
|
895
|
-
return data
|
|
1313
|
+
return data * mult
|
|
896
1314
|
|
|
897
1315
|
@staticmethod
|
|
898
1316
|
def write_txt(shape, file_out, data, fortran_format="(FREE)",
|
|
899
1317
|
python_format=None):
|
|
900
|
-
|
|
1318
|
+
"""
|
|
901
1319
|
write a (possibly wrapped format) array from a file
|
|
902
1320
|
(self.__value) and casts to the proper type (self.dtype)
|
|
903
1321
|
made static to support the load functionality
|
|
904
1322
|
this routine now supports fixed format arrays where the numbers
|
|
905
1323
|
may touch.
|
|
906
|
-
|
|
1324
|
+
"""
|
|
907
1325
|
|
|
908
1326
|
if fortran_format.upper() == '(FREE)' and python_format is None:
|
|
909
1327
|
np.savetxt(file_out,data,util_2d.get_default_numpy_fmt(data.dtype),
|
|
910
1328
|
delimiter='')
|
|
911
1329
|
return
|
|
912
1330
|
|
|
913
|
-
nrow,ncol = shape
|
|
1331
|
+
nrow, ncol = shape
|
|
914
1332
|
if python_format is None:
|
|
915
1333
|
column_length, fmt, width, decimal = \
|
|
916
1334
|
decode_fortran_descriptor(fortran_format)
|
|
@@ -931,7 +1349,7 @@ class util_2d(object):
|
|
|
931
1349
|
lineReturnFlag = False
|
|
932
1350
|
else:
|
|
933
1351
|
lineReturnFlag = True
|
|
934
|
-
|
|
1352
|
+
# write the array
|
|
935
1353
|
for i in range(nrow):
|
|
936
1354
|
icol = 0
|
|
937
1355
|
for j in range(ncol):
|
|
@@ -972,15 +1390,16 @@ class util_2d(object):
|
|
|
972
1390
|
return
|
|
973
1391
|
|
|
974
1392
|
def get_control_record(self):
|
|
975
|
-
|
|
976
|
-
|
|
1393
|
+
"""
|
|
1394
|
+
get the modflow control record
|
|
1395
|
+
"""
|
|
977
1396
|
lay_space = '{0:>27s}'.format('')
|
|
978
1397
|
if self.model.free_format:
|
|
979
1398
|
if self.ext_filename is None:
|
|
980
1399
|
if self.vtype in [np.int]:
|
|
981
1400
|
lay_space = '{0:>32s}'.format('')
|
|
982
1401
|
if self.vtype in [np.int, np.float32]:
|
|
983
|
-
|
|
1402
|
+
# this explicit cast to float is to handle a
|
|
984
1403
|
#- bug in versions of numpy < l.6.2
|
|
985
1404
|
if self.dtype == np.float32:
|
|
986
1405
|
cr = 'CONSTANT ' + \
|
|
@@ -993,8 +1412,8 @@ class util_2d(object):
|
|
|
993
1412
|
cr = 'INTERNAL {0:15.6G} {1:>10s} {2:2.0f} #{3:<30s}\n'\
|
|
994
1413
|
.format(self.cnstnt, self.fmtin, self.iprn, self.name)
|
|
995
1414
|
else:
|
|
996
|
-
|
|
997
|
-
|
|
1415
|
+
# need to check if ext_filename exists, if not, need to
|
|
1416
|
+
# write constant as array to file or array to file
|
|
998
1417
|
f = self.ext_filename
|
|
999
1418
|
fr = os.path.relpath(f, self.model.model_ws)
|
|
1000
1419
|
#if self.locat is None:
|
|
@@ -1005,10 +1424,10 @@ class util_2d(object):
|
|
|
1005
1424
|
# self.fmtin.strip(), self.iprn, self.name)
|
|
1006
1425
|
|
|
1007
1426
|
else:
|
|
1008
|
-
|
|
1427
|
+
# if value is a scalar and we don't want external array
|
|
1009
1428
|
if self.vtype in [np.int, np.float32] and self.ext_filename is None:
|
|
1010
1429
|
locat = 0
|
|
1011
|
-
|
|
1430
|
+
# explicit cast for numpy bug in versions < 1.6.2
|
|
1012
1431
|
if self.dtype == np.float32:
|
|
1013
1432
|
cr = '{0:>10.0f}{1:>10.5G}{2:>20s}{3:10.0f} #{4}\n'\
|
|
1014
1433
|
.format(locat, float(self.__value),
|
|
@@ -1036,10 +1455,11 @@ class util_2d(object):
|
|
|
1036
1455
|
|
|
1037
1456
|
|
|
1038
1457
|
def fort_2_py(self,fd):
|
|
1039
|
-
|
|
1458
|
+
"""
|
|
1459
|
+
converts the fortran format descriptor
|
|
1040
1460
|
into a tuple of npl and a python format specifier
|
|
1041
1461
|
|
|
1042
|
-
|
|
1462
|
+
"""
|
|
1043
1463
|
npl,fmt,width,decimal = decode_fortran_descriptor(fd)
|
|
1044
1464
|
if npl == 'free':
|
|
1045
1465
|
if self.vtype == np.int:
|
|
@@ -1054,9 +1474,10 @@ class util_2d(object):
|
|
|
1054
1474
|
|
|
1055
1475
|
|
|
1056
1476
|
def parse_value(self, value):
|
|
1057
|
-
|
|
1477
|
+
"""
|
|
1478
|
+
parses and casts the raw value into an acceptable format for __value
|
|
1058
1479
|
lot of defense here, so we can make assumptions later
|
|
1059
|
-
|
|
1480
|
+
"""
|
|
1060
1481
|
if isinstance(value, list):
|
|
1061
1482
|
if VERBOSE:
|
|
1062
1483
|
print('util_2d: casting list to array')
|
|
@@ -1080,7 +1501,7 @@ class util_2d(object):
|
|
|
1080
1501
|
except:
|
|
1081
1502
|
# print value
|
|
1082
1503
|
# print os.path.join(self.model.model_ws,value)
|
|
1083
|
-
|
|
1504
|
+
# JDH Note: value should be the filename with
|
|
1084
1505
|
# the relative path. Trace through code to
|
|
1085
1506
|
# determine why it isn't
|
|
1086
1507
|
if os.path.basename(value) == value:
|
|
@@ -1132,12 +1553,13 @@ class util_2d(object):
|
|
|
1132
1553
|
|
|
1133
1554
|
@staticmethod
|
|
1134
1555
|
def load(f_handle, model, shape, dtype, name, ext_unit_dict=None):
|
|
1135
|
-
|
|
1556
|
+
"""
|
|
1557
|
+
functionality to load util_2d instance from an existing
|
|
1136
1558
|
model input file.
|
|
1137
1559
|
external and internal record types must be fully loaded
|
|
1138
1560
|
if you are using fixed format record types,make sure
|
|
1139
1561
|
ext_unit_dict has been initialized from the NAM file
|
|
1140
|
-
|
|
1562
|
+
"""
|
|
1141
1563
|
|
|
1142
1564
|
curr_unit = None
|
|
1143
1565
|
if ext_unit_dict is not None:
|
|
@@ -1158,7 +1580,7 @@ class util_2d(object):
|
|
|
1158
1580
|
iprn=cr_dict['iprn'], fmtin=cr_dict['fmtin'])
|
|
1159
1581
|
|
|
1160
1582
|
elif cr_dict['type'] == 'open/close':
|
|
1161
|
-
|
|
1583
|
+
# clean up the filename a little
|
|
1162
1584
|
fname = cr_dict['fname']
|
|
1163
1585
|
fname = fname.replace("'", "")
|
|
1164
1586
|
fname = fname.replace('"', '')
|
|
@@ -1183,6 +1605,7 @@ class util_2d(object):
|
|
|
1183
1605
|
|
|
1184
1606
|
elif cr_dict['type'] == 'internal':
|
|
1185
1607
|
data = util_2d.load_txt(shape, f_handle, dtype, cr_dict['fmtin'])
|
|
1608
|
+
data *= cr_dict['cnstnt']
|
|
1186
1609
|
u2d = util_2d(model, shape, dtype, data, name=name,
|
|
1187
1610
|
iprn=cr_dict['iprn'], fmtin=cr_dict['fmtin'])
|
|
1188
1611
|
|
|
@@ -1195,6 +1618,7 @@ class util_2d(object):
|
|
|
1195
1618
|
else:
|
|
1196
1619
|
header_data, data = util_2d.load_bin(
|
|
1197
1620
|
shape, ext_unit_dict[cr_dict['nunit']].filehandle, dtype)
|
|
1621
|
+
data *= cr_dict['cnstnt']
|
|
1198
1622
|
u2d = util_2d(model, shape, dtype, data, name=name,
|
|
1199
1623
|
iprn=cr_dict['iprn'], fmtin=cr_dict['fmtin'])
|
|
1200
1624
|
# track this unit number so we can remove it from the external
|
|
@@ -1206,10 +1630,11 @@ class util_2d(object):
|
|
|
1206
1630
|
@staticmethod
|
|
1207
1631
|
def parse_control_record(line, current_unit=None, dtype=np.float32,
|
|
1208
1632
|
ext_unit_dict=None):
|
|
1209
|
-
|
|
1633
|
+
"""
|
|
1634
|
+
parses a control record when reading an existing file
|
|
1210
1635
|
rectifies fixed to free format
|
|
1211
1636
|
current_unit (optional) indicates the unit number of the file being parsed
|
|
1212
|
-
|
|
1637
|
+
"""
|
|
1213
1638
|
free_fmt = ['open/close', 'internal', 'external', 'constant']
|
|
1214
1639
|
raw = line.lower().strip().split()
|
|
1215
1640
|
freefmt, cnstnt, fmtin, iprn, nunit = None, None, None, -1, None
|
|
@@ -1217,7 +1642,7 @@ class util_2d(object):
|
|
|
1217
1642
|
isFloat = False
|
|
1218
1643
|
if dtype == np.float or dtype == np.float32:
|
|
1219
1644
|
isFloat = True
|
|
1220
|
-
|
|
1645
|
+
# if free format keywords
|
|
1221
1646
|
if str(raw[0]) in str(free_fmt):
|
|
1222
1647
|
freefmt = raw[0]
|
|
1223
1648
|
if raw[0] == 'constant':
|
|
@@ -1226,6 +1651,10 @@ class util_2d(object):
|
|
|
1226
1651
|
else:
|
|
1227
1652
|
cnstnt = np.int(raw[1].lower())
|
|
1228
1653
|
if raw[0] == 'internal':
|
|
1654
|
+
if isFloat:
|
|
1655
|
+
cnstnt = np.float(raw[1].lower().replace('d', 'e'))
|
|
1656
|
+
else:
|
|
1657
|
+
cnstnt = np.int(raw[1].lower())
|
|
1229
1658
|
fmtin = raw[2].strip()
|
|
1230
1659
|
iprn = int(raw[3])
|
|
1231
1660
|
elif raw[0] == 'external':
|