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.
Files changed (90) hide show
  1. {flopy-3.2.1 → flopy-3.2.2}/PKG-INFO +47 -11
  2. {flopy-3.2.1 → flopy-3.2.2}/flopy/mbase.py +307 -17
  3. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mf.py +8 -6
  4. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfbcf.py +2 -2
  5. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfchd.py +1 -1
  6. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfde4.py +2 -2
  7. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfdis.py +11 -94
  8. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfdrn.py +1 -1
  9. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfevt.py +3 -3
  10. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfghb.py +2 -2
  11. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfgmg.py +60 -19
  12. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfhfb.py +7 -7
  13. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mflpf.py +13 -10
  14. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfmlt.py +3 -3
  15. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfnwt.py +1 -1
  16. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfoc.py +26 -20
  17. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfoc88.py +9 -9
  18. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfpar.py +15 -9
  19. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfparbc.py +7 -7
  20. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfpcg.py +2 -2
  21. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfpcgn.py +3 -3
  22. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfpks.py +1 -1
  23. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfrch.py +4 -4
  24. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfriv.py +6 -4
  25. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfsip.py +2 -2
  26. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfsor.py +3 -3
  27. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfswi2.py +34 -34
  28. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfswr1.py +4 -4
  29. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfupw.py +4 -4
  30. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfuzf1.py +5 -5
  31. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfwel.py +1 -2
  32. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfzon.py +2 -2
  33. {flopy-3.2.1 → flopy-3.2.2}/flopy/modpath/mp.py +7 -5
  34. {flopy-3.2.1 → flopy-3.2.2}/flopy/modpath/mpbas.py +1 -1
  35. {flopy-3.2.1 → flopy-3.2.2}/flopy/modpath/mpsim.py +18 -16
  36. {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mt.py +1 -1
  37. {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mtbtn.py +3 -3
  38. {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mtssm.py +7 -6
  39. {flopy-3.2.1 → flopy-3.2.2}/flopy/plot/__init__.py +1 -1
  40. {flopy-3.2.1 → flopy-3.2.2}/flopy/plot/crosssection.py +73 -103
  41. flopy-3.2.2/flopy/plot/map.py +647 -0
  42. flopy-3.2.2/flopy/plot/plotutil.py +1205 -0
  43. {flopy-3.2.1 → flopy-3.2.2}/flopy/utils/__init__.py +3 -1
  44. {flopy-3.2.1 → flopy-3.2.2}/flopy/utils/binaryfile.py +91 -364
  45. {flopy-3.2.1 → flopy-3.2.2}/flopy/utils/binaryhydmodfile.py +3 -3
  46. {flopy-3.2.1 → flopy-3.2.2}/flopy/utils/binaryswrfile.py +21 -21
  47. flopy-3.2.2/flopy/utils/datafile.py +476 -0
  48. flopy-3.2.2/flopy/utils/flopy_io.py +128 -0
  49. flopy-3.2.2/flopy/utils/formattedfile.py +366 -0
  50. flopy-3.2.2/flopy/utils/modpathfile.py +421 -0
  51. flopy-3.2.2/flopy/utils/reference.py +386 -0
  52. {flopy-3.2.1 → flopy-3.2.2}/flopy/utils/util_array.py +512 -83
  53. {flopy-3.2.1 → flopy-3.2.2}/flopy/utils/util_list.py +234 -13
  54. flopy-3.2.2/flopy/version.py +4 -0
  55. {flopy-3.2.1 → flopy-3.2.2}/flopy.egg-info/PKG-INFO +47 -11
  56. {flopy-3.2.1 → flopy-3.2.2}/flopy.egg-info/SOURCES.txt +5 -0
  57. {flopy-3.2.1 → flopy-3.2.2}/setup.py +2 -6
  58. flopy-3.2.1/flopy/plot/map.py +0 -592
  59. flopy-3.2.1/flopy/plot/plotutil.py +0 -512
  60. flopy-3.2.1/flopy/version.py +0 -4
  61. flopy-3.2.1/requirements.txt +0 -2
  62. {flopy-3.2.1 → flopy-3.2.2}/flopy/__init__.py +0 -0
  63. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/__init__.py +0 -0
  64. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfaddoutsidefile.py +0 -0
  65. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfbas.py +0 -0
  66. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfbct.py +0 -0
  67. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mflmt.py +0 -0
  68. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfmnw1.py +0 -0
  69. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfmnw2.py +0 -0
  70. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfmnwi.py +0 -0
  71. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfpbc.py +0 -0
  72. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfpval.py +0 -0
  73. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfsms.py +0 -0
  74. {flopy-3.2.1 → flopy-3.2.2}/flopy/modflow/mfswi.py +0 -0
  75. {flopy-3.2.1 → flopy-3.2.2}/flopy/modpath/__init__.py +0 -0
  76. {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/__init__.py +0 -0
  77. {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mtadv.py +0 -0
  78. {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mtdsp.py +0 -0
  79. {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mtgcg.py +0 -0
  80. {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mtphc.py +0 -0
  81. {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mtrct.py +0 -0
  82. {flopy-3.2.1 → flopy-3.2.2}/flopy/mt3d/mttob.py +0 -0
  83. {flopy-3.2.1 → flopy-3.2.2}/flopy/seawat/__init__.py +0 -0
  84. {flopy-3.2.1 → flopy-3.2.2}/flopy/seawat/swt.py +0 -0
  85. {flopy-3.2.1 → flopy-3.2.2}/flopy/seawat/swtvdf.py +0 -0
  86. {flopy-3.2.1 → flopy-3.2.2}/flopy/utils/mfreadnam.py +0 -0
  87. {flopy-3.2.1 → flopy-3.2.2}/flopy.egg-info/dependency_links.txt +0 -0
  88. {flopy-3.2.1 → flopy-3.2.2}/flopy.egg-info/requires.txt +0 -0
  89. {flopy-3.2.1 → flopy-3.2.2}/flopy.egg-info/top_level.txt +0 -0
  90. {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
- from flopy.utils.binaryfile import BinaryHeader
15
+ import flopy.utils
16
16
  VERBOSE = False
17
17
 
18
18
 
19
19
 
20
20
  def decode_fortran_descriptor(fd):
21
- #--strip off any quotes around format string
21
+ # strip off any quotes around format string
22
22
  fd = fd.replace("'", "")
23
23
  fd = fd.replace('"', '')
24
- #--strip off '(' and ')'
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
- #--'(F9.0)' will return raw = ['', '9']
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
- '''Converts a 1D or 2D array into a string
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
- #--fix for numpy 1.6 bug
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
- # '''meta class to catch existing instances of util_2d,
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
- '''3-D wrapper from util_2d - shape must be 3-D
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
- #--if value is not enumerable, then make a list of something
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
- #--if this is a list or 1-D array with constant values per layer
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
- #--if an array of shape nrow,ncol was passed, tile it out for each layer
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) + "(filled zero)"
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
- """get the file entry info for a given kper
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
- """parse self.__value into a dict{kper:util_2d}
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
- """parse an argument into a util_2d instance
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
- '''1d or 2-d array support with minimum of mem footprint.
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
- #--just for testing
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
- #--set fmtin
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
- #--get (npl,python_format_descriptor) from fmtin
951
+ # get (npl,python_format_descriptor) from fmtin
649
952
  self.py_desc = self.fort_2_py(self.fmtin)
650
953
 
651
- #--some defense
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
- #--overloads, tries to avoid creating arrays if possible
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
- #--this explicit cast is to handle a bug in numpy versions < 1.6.2
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
- '''this one is dangerous because it resets __value
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
- '''this is the entry point for getting an
1153
+ """
1154
+ this is the entry point for getting an
741
1155
  input file entry for this object
742
- '''
743
- #--call get_file_array first in case we need to
744
- #-- get a new external unit number and reset self.locat
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
- '''increments locat and update model instance if needed.
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
- #--if the value is not a filename
1169
+ """
1170
+ # if the value is not a filename
756
1171
  if self.vtype != str:
757
1172
 
758
- #--if the ext_filename was passed, then we need
759
- #-- to write an external array
1173
+ # if the ext_filename was passed, then we need
1174
+ # to write an external array
760
1175
  if self.ext_filename != None:
761
- #--if we need fixed format, reset self.locat and get a
762
- #-- new unit number
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
- #--write external formatted or unformatted array
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
- #--this internal array or constant
1196
+ # this internal array or constant
782
1197
  else:
783
1198
  if self.vtype is np.ndarray:
784
1199
  return self.string
785
- #--if this is a constant, return a null string
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
- #--if this is a free format model, then we can use the same
791
- #-- ext file over and over - no need to copy
792
- #--also, loosen things up with FREE format
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
- #--if fixed format, we need to get a new unit number
802
- #-- and reset locat
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
- #--otherwise, we need to load the the value filename
808
- #-- and return as a string
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
- '''get the string represenation of value attribute
815
- '''
1229
+ """
1230
+ get the string represenation of value attribute
1231
+ """
816
1232
  a = self.array
817
- #--convert array to sting with specified format
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
- '''get the array representation of value attribute
824
- if value is a string or a constant, the array is loaded/built only once
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
- '''load a (possibly wrapped format) array from a file
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
- #--write the array
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
- '''get the modflow control record
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
- #--this explicit cast to float is to handle a
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
- #--need to check if ext_filename exists, if not, need to
997
- #-- write constant as array to file or array to file
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
- #--if value is a scalar and we don't want external array
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
- #--explicit cast for numpy bug in versions < 1.6.2
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
- '''converts the fortran format descriptor
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
- '''parses and casts the raw value into an acceptable format for __value
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
- #--JDH Note: value should be the filename with
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
- '''functionality to load util_2d instance from an existing
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
- #--clean up the filename a little
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
- '''parses a control record when reading an existing file
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
- #--if free format keywords
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':