-
Notifications
You must be signed in to change notification settings - Fork 0
/
model_v3.py
2132 lines (1797 loc) · 101 KB
/
model_v3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/env python
##\file
##\brief Top level file for the ecological modeling.
##\detail This file describes the model proper and the major
# model-specific coding elements used to build this model.
##\section Includes Included Libraries
# The file makes use of the following libraries
# - Standard Python Libraries
# - copy
# - exceptions
# - itertools
# - re
# - StringIO
# - sys
# - time
# - Third Party Libraries
# - pandas version 0.13.1
# - xlrd
# - Model defined libraries
# - config
# - event
# - function
# - landscape
# Diagnostic modules
#from memory_profiler import profile
#from pympler.asizeof import asizeof
# STD Python modules
import collections
import copy
from builtins import Exception as exceptions
#import exceptions
import glob
import itertools
import math
import os
import re
import sys
import time
# Third party modules
import numpy
import pandas
import xlrd
# This model's modules
import config
import event
import function
import landscape
import plantingmodel
##\class SpeciesModel
##\brief Base class for all species models.
##\detail This is a generic base class defining the functionality
# of a single species model for a single location in the landscape.
# All species models should inherit
# from this class to make sure they get the basic elements.
##\role{Ecology/Machinery}
class SpeciesModel(object):
##\brief A reference to the model Params object
params = None
##\brief A reference to the model DispersalModel object
dspModel = None
## Class constructor.
#\param [in] self The object's reference to itself.
#\param [in] index The species index.
#\param [in] abr The species USDA alpha-numeric vegetation code.
#\param [in] name The full species name.
#\param [in] modelType The type of a model.
#\param [in] habitat The habitat provided by the species (salinity regime)
#\param [in] dspClass The dispersal class of the species (0,1,2,3=high)
#\param [in] ffibsScore The FFIBS (forested, fresh, intermediate, brackish, saline) score for that species
#\param [in] cover The fraction of model cell that is covered by a species.
#\param [in] loc The x,y location of a cell. Given as the row,column index with in the model grid.
def __init__(self, index=0, name='', abr='', modelType='', habitat='', dspClass=0, ffibsScore=0, cover=0, loc=0):
##\brief Species index
##\details An integer that is a unique numerical species index.
## - Type: integer
## - Range: [0, inf)
#self.index = index
##\brief The long name for a species
##\details A string used to make output pretty
## - Type: string
#self.name = name
##\brief Species code
##\details A string abbreviation for the species. The value is the species' USDA alpha-numeric vegetation code.
# This is an important member value in the model. It is used as the key in the dictionary that stores the list
# of species in a patch.
## - Type: string
self.abr = abr
##\brief The model type
##\details A string containing the model type.
##\n
## This member should one of the following values (as a string):\n
# - BarrierIslandModel
# - EmergentWetlandModel
# - BottomlandHardwoodForestModel
# - SAVModel
# - NullModel_Coverage
# - NullModel
##\n
self.modelType = modelType
##\brief The habitat type
##\details A string containing the habitat type.
##\n
## This member should one of the following values (as a string):\n
# - Fresh
# - Intermediate
# - Brackish
# - Saline
# - NA
##\n
self.habitat = habitat
##\brief The dispersal class of a species
##\details Dispersal classes describe far a species can establish, 1 is from one cell away, 2 is from two cells away, 3 is from anywhere, and 0 is for null
## - Type: float
## - Range: [0, 3]
self.dspClass = dspClass
##\brief The FIBS score of a species corresponds to its salinity regime: Fresh = 0.25, Intermediate = 1.5, Brackish = 7.15 or 11.5, Saline = 17.5 or 24, null coverages are nan
##\details FIBS score
## - Type: float
## - Range: [0.25, 24]
self.ffibsScore = ffibsScore
##\brief The area occupied by a species
##\details This is the fraction of a patch covered by a species.
## - Type: float
## - Range: [0, inf)
self.cover = cover
##\brief Species Location
##\details This is the location of a species. The location is stored as a python tuple
# that contains the row and column index of the landscape where the species is present
## - Type: tuple
self.loc = loc
##\brief Object configuration.
#\param self The object's reference to itself.
#\param index The species index.
#\param abr The species USDA alpha-numeric vegetation code.
#\param name The full species name.
#\param modelType The type of a model.
#\param habitat The habitat provided by the species (salinity regime).
#\param dspClass The dispersal class the species belongs (low, med, high).
#\param ffibsScore The FFIBS score of the species.
#\param cover The fraction of model cell that is covered by a species.
#\param loc The x,y location of a cell. Given as the row,column index with in the model grid.
##\detail This function is used to configure an object after it has been created.
# this is used SpeciesModelList when it is creating the list of species from
# the species growth/senescence tables and by PatchModel when creating the
# individual species model for each location.
def config(self, index=0, name='', abr='', modelType='', habitat='', dspClass=0, ffibsScore=0, cover=0, loc=0):
#self.index = index
#self.name = name
self.abr = abr
self.modelType = modelType
self.habitat = habitat
self.dspClass = dspClass
self.ffibsScore = ffibsScore
self.cover = cover
#self.loc = loc
##\brief Computes the probability of senescence.
##\detail This is a generic function that returns the probability of plants senesencing.
# This function should be redefined by each class that inherits form SpeciesModel.
def senescence(self, loc):
return 0.0
##\brief Computes the probability of establishment
##\details This is a generic function that returns the probability of plants growing.
# This function should be redefined by each class that inherits from SpeciesModel.
def growth(self, loc):
return 0.0
##\brief Computes the probability of establishment for high dispersal species
##\details This is a generic function that returns the probability of plants growing.
# This function should be redefined by each class that inherits from SpeciesModel.
def spread(self, loc):
return 0.0
def __float__(self):
return -3.0
#return self.cover
#def __str__(self):
# ret = ''
# #ret = str(self.index) + ', '
# #ret += self.name + ', '
# ret += self.abr + ', '
# ret += self.modelType + ', '
# ret += str(self.cover) + ', '
# ret += str(self.loc)
# return ret
##\class NullModel
##\brief A place holder.
##\role{Machinery}
##\detail A place holder for items in the output that are not coverage values (e.g. FFIBS).
## Having this class makes the rest of the model code simpler.
class NullModel(SpeciesModel):
def __init__(self, index=0, name='', abr='', habitat = '', dspClass=0, ffibsScore=0, cover=0, loc=0):
SpeciesModel.__init__(self, index, name, abr, 'NullModel', habitat, dspClass, ffibsScore, cover, loc)
##\brief
##\detail
def senescence(self, loc):
return 0.0
##\brief
##\detail
def growth(self, loc):
return 0.0
def spread(self,loc):
return 0.0
##\class NullModel_Coverage
##\brief A place holder.
##\role{Machinery}
##\detail A place holder for coverage types that
# do not really do anything but do need to be counted when adding up coverage (e.g. water).
# Having this class makes the rest of the model code simpler.
class NullModel_Coverage(SpeciesModel):
def __init__(self, index=0, name='', abr='', habitat = '', dspClass=0, ffibsScore=0, cover=0, loc=0):
SpeciesModel.__init__(self, index, name, abr, 'NullModel_Coverage', habitat, dspClass, ffibsScore, cover, loc)
##\brief
##\detail
def senescence(self, loc):
return 0.0
##\brief
##\detail
def growth(self, loc):
return 0.0
def spread(self,loc):
return 0.0
##\class BottomlandHardwoodForestModel
##\brief This class handles the ecology for the bottomland hardwood forest species.
##\role{Ecology}
##\detail bottomland hardwood forest types change state based on the
# height of the habitat above mean water surface.
class BottomlandHardwoodForestModel(SpeciesModel):
def __init__(self, index=0, name='', abr='', habitat='', dspClass=0, ffibsScore=0, cover=0, loc=0, Pdata=None, Ddata=None):
SpeciesModel.__init__(self, index, name, abr, 'BottomlandHardwoodForestModel', habitat, dspClass, ffibsScore, cover, loc)
self.P = function.Function(Pdata['elvValue'], Pdata['rate'])
self.D = function.Function(Ddata['elvValue'], Ddata['rate'])
## Senescence function
# This function determines the probability that a bottomland hardwood forest species
# will experience senescence. The probability of senescence is a function
# of the elevation of the local habitat above the mean water surface. The
# exact functional relationship between height above water and the probability
# of senescence is determined by the senescence table for each species.
# The senescence tables are defined in a model input file.
def senescence(self, loc):
try:
elv = SpeciesModel.params.heightAboveWater[loc]
sal = SpeciesModel.params.meanSal[loc]
bi = SpeciesModel.params.biEstCond[loc]
if bi or sal > 1.0:
return 1.0
return self.D[elv]
except RuntimeError as error:
msg = 'BottomlandHardwoodForestModel.senescence(): Error: location out of range. Additional info follows\n'
msg += str(error)
raise RuntimeError(msg)
## Growth function
# This function determines the probability that a bottomland hardwood forest species will become
# established at the current location. The probability of a bottomland hardwood forest species becoming
# established is depended on three major factors. First, the salinity must be below 1.0 ppt.
# Second, there must be a period of 14 days with no flooding followed by a period of 14 with
# water depths below 14 cm. Finally, the height of the habitat above mean water level determines
# the final probability.
# I'm not entirely happy with the current state of this function because the computation
# of the basic establishment conditions (14 day no flood, 14 days water depth < 14 cm) is
# handled external to the model. The problem is that the current approach divides
# the responsibilities for representing the ecology of upland forest species (now bottomland hardwood forest).
# An external program determines the establishment conditions while the model proper handles
# the final computation of the probability of establishment. I would like to fix this.
def growth(self, loc):
try:
elv = SpeciesModel.params.heightAboveWater[loc]
sal = SpeciesModel.params.meanSal[loc]
est = SpeciesModel.params.treeEstCond[loc]
bi = SpeciesModel.params.biEstCond[loc]
dsp = SpeciesModel.dspModel[loc][self.abr]
if bi or sal > 1.0:
return 0
return self.P[elv] * dsp * est
except RuntimeError as error:
msg = 'BottomlandHardwoodForestModel.growth(): Error: location out of range. Additional info follows\n'
msg += str(error)
raise RuntimeError(msg)
def spread(self,loc):
if self.dspClass == 3:
try:
elv = SpeciesModel.params.heightAboveWater[loc]
sal = SpeciesModel.params.meanSal[loc]
est = SpeciesModel.params.treeEstCond[loc]
bi = SpeciesModel.params.biEstCond[loc]
if bi or sal > 1.0:
return 0
return self.P[elv]*est
except RuntimeError as error:
msg = 'BottomlandHardwoodForestModel.growth(): Error: location out of range. Additional info follows\n'
msg += str(error)
raise RuntimeError(msg)
else:
return 0.0
##\class EmergentWetlandModel
##\brief This class handles the ecology for the emergent wetland species.
##\role{Ecology}
##\detail
class EmergentWetlandModel(SpeciesModel):
def __init__(self, index=0, name='', abr='', habitat = '', dspClass=0, ffibsScore=0, cover=0, loc=0, Pdata=None, Ddata=None):
SpeciesModel.__init__(self, index, name, abr, 'EmergentWetlandModel', habitat, dspClass, ffibsScore, cover, loc)
self.P = function.Function2DFast(Pdata['waValue'], Pdata['salValue'], Pdata['rate'])
self.D = function.Function2DFast(Ddata['waValue'], Ddata['salValue'], Ddata['rate'])
## Senescence function
# This function determines the probability that an emergent wetland species
# will experience senescence. The probability of senescence is a function
# of variation in water stage height (computed as the standard deviation of stage)
# and salinity. The exact relationship between the probability of senescence and
# the environmental factors is describe the by scenescence table for each species.
# The senescence tables are defined in a model input file.
def senescence(self, loc):
waveAmp = SpeciesModel.params.waveAmp[loc]
meanSal = SpeciesModel.params.meanSal[loc]
elv = SpeciesModel.params.heightAboveWater[loc]
bi = SpeciesModel.params.biEstCond[loc]
#if bi or elv > SpeciesModel.params.elevationThreshold:
#return 1.0
if bi: return 1.0
return self.D[waveAmp,meanSal]
## Growth function
# This function determines the probability that an emergent wetland species will become
# established at the current location.
def growth(self, loc):
waveAmp = SpeciesModel.params.waveAmp[loc]
meanSal = SpeciesModel.params.meanSal[loc]
elv = SpeciesModel.params.heightAboveWater[loc]
bi = SpeciesModel.params.biEstCond[loc]
dsp = SpeciesModel.dspModel[loc][self.abr]
#No_elev_threshold# if bi or elv > SpeciesModel.params.elevationThreshold:
#if bi > SpeciesModel.params.elevationThreshold:
if bi: return 0.0
return self.P[waveAmp, meanSal] * dsp
def spread(self,loc):
if self.dspClass == 3:
waveAmp = SpeciesModel.params.waveAmp[loc]
meanSal = SpeciesModel.params.meanSal[loc]
elv = SpeciesModel.params.heightAboveWater[loc]
bi = SpeciesModel.params.biEstCond[loc]
if bi: return 0.0
return self.P[waveAmp, meanSal]
else:
return 0.0
class SwampForestModel(SpeciesModel):
def __init__(self, index=0, name='', abr='', habitat = '', dspClass=0, ffibsScore=0, cover=0, loc=0, Pdata=None, Ddata=None):
SpeciesModel.__init__(self, index, name, abr, 'SwampForestModel', habitat, dspClass, ffibsScore, cover, loc)
self.P = function.Function2DFast(Pdata['waValue'], Pdata['salValue'], Pdata['rate'])
self.D = function.Function2DFast(Ddata['waValue'], Ddata['salValue'], Ddata['rate'])
## Senescence function
# This function determines the probability that an emergent wetland species
# will experience senescence. The probability of senescence is a function
# of variation in water stage height (computed as the standard deviation of stage)
# and salinity. The exact relationship between the probability of senescence and
# the environmental factors is describe the by scenescence table for each species.
# The senescence tables are defined in a model input file.
def senescence(self, loc):
waveAmp = SpeciesModel.params.waveAmp[loc]
meanSal = SpeciesModel.params.meanSal[loc]
bi = SpeciesModel.params.biEstCond[loc]
if bi: return 1.0
return self.D[waveAmp,meanSal]
## Growth function
# This function determines the probability that an emergent wetland species will become
# established at the current location. The probability of an wetland species becoming
# established is depended on
# three major factors. First, the salinity must be below 1.0 ppt.
# Second, there must be a period of 14 days with no flooding followed by a period of 14 with
# water depths below 14 cm. Finally, the height of the habitat above mean water level determines
# the final probability.
def growth(self, loc):
waveAmp = SpeciesModel.params.waveAmp[loc]
meanSal = SpeciesModel.params.meanSal[loc]
est = SpeciesModel.params.treeEstCond[loc]
bi = SpeciesModel.params.biEstCond[loc]
dsp = SpeciesModel.dspModel[loc][self.abr]
if bi: return 0.0
return self.P[waveAmp, meanSal] * dsp * est
def spread(self,loc):
if self.dspClass == 3:
waveAmp = SpeciesModel.params.waveAmp[loc]
meanSal = SpeciesModel.params.meanSal[loc]
est = SpeciesModel.params.treeEstCond[loc]
bi = SpeciesModel.params.biEstCond[loc]
if bi: return 0.0
return self.P[waveAmp, meanSal] * est
else:
return 0.0
##\class SAVModel
##\brief This class handles the ecology for the SAV species.
##\role{Ecology}
##\detail It is not used for the 2023 Coastal Master Plan. The SAV model is now separate.
#
class SAVModel(SpeciesModel):
def __init__(self, index=0, name='', abr='', habitat = '', dspClass=0, ffibsScore=0, cover=0, loc=0, SAVData=None):
SpeciesModel.__init__(self, index, name, abr, 'SAVModel', habitat, dspClass,ffibsScore, cover, loc)
if SAVData == None:
errorMessage = 'SAVModel: Error: No SAVData object passed to constructor (i.e. __init__() )\n'
raise RuntimeError(errorMessage)
self.betaIntercept = SAVData['Intercept']
self.betaTemp = SAVData['Temp']
self.betaSal = SAVData['Sal']
self.betaDepth = SAVData['Depth']
def senescence(self, loc):
return 0;
def growth(self, loc):
d = SpeciesModel.params.smDepth[loc]
s = SpeciesModel.params.smSal[loc]
t = SpeciesModel.params.smTemp[loc]
bi = SpeciesModel.params.biEstCond[loc]
if bi:
return 0.0
return min( 1.0, max(0.0, self.betaIntercept + self.betaTemp*t + self.betaSal*s + self.betaDepth*d ) )
##\class BarrierIslandModel
##\brief This class handles the ecology for the barrier island species.
##\role{Ecology}
##\detail
#
class BarrierIslandModel(SpeciesModel):
def __init__(self, index=0, name='', abr='', habitat='', dspClass=0, ffibsScore=0, cover=0, loc=0, Pdata=None, Ddata=None):
SpeciesModel.__init__(self, index, name, abr, 'BarrierIslandModel', habitat, dspClass, ffibsScore, cover, loc)
self.P = function.Function(Pdata['elvValue'], Pdata['rate'])
self.D = function.Function(Ddata['elvValue'], Ddata['rate'])
def senescence(self, loc):
elv = SpeciesModel.params.biHeightAboveWater[loc]
bi = SpeciesModel.params.biEstCond[loc]
if not bi:
return 1.0
return self.D[elv]
def growth(self, loc):
elv = SpeciesModel.params.biHeightAboveWater[loc]
bi = SpeciesModel.params.biEstCond[loc]
#dsp = SpeciesModel.dspModel[self.loc][self.abr]
if not bi:
return 0.0
return self.P[elv]# * dsp
##\class
##\brief
##\role{Ecology}
##\detail
#
class FloatingMarshModel(EmergentWetlandModel):
def __init__(self, index=0, name='', abr='', habitat ='', dspClass=0, ffibsScore=0, cover=0, loc=0, Pdata=None, Ddata=None):
EmergentWetlandModel.__init__(self, index, name, abr, habitat, dspClass, ffibsScore, cover, loc, Pdata, Ddata)
self.modelType = 'FloatingMarshModel'
self.transList = None
##\brief Growth/Senescence table storage
##\detail This class stores the growth and senescence tables
# for each species. The class is structured as a dictionary.
# Each species is identified by a unique abbreviation. For
# example, _Phragmities australis_ (Roseau cane) is represented
# by the abbreviation PAHU7. The abbreviations are based on the
# USDA species abbreviations. The abbreviations for each of the species
# used in this model are defined in the establishment table file.
#
# Each unique abbreviation is associated with the growth and senescence
# tables. These tables are defined in the establishment and senescence file.
#
# This class' job is to make the data from the establishment and senescence
# tables available to the other model components.
#
class SpeciesModelList(dict):
##\brief Class constructor
def __init__(self):
dict.__init__(self)
##\brief Load data from establishment and senescence files.
##@param [in] estFilename The name of the file containing the establishment tables.
##@param [in] mortFilename The name of the file containing the senescence tables.
##\details This member function loads the establishment and senescence tables
# from the filenames passed in as arguments. The files are expected to be
# MSExcel spreadsheets stored in the XLSX format. The data in each file
# should be divided into a set of separate tabbed sheets. One sheet should
# be named "VegTypeNames". This sheet should list all the species to include
# in the model. There should also be one table for each of the species included in the
# model. There are three exceptions to this: SAV, the bottomland hardwood forest species and the
# barrier island species. SAV parameters are read from the model configuration file.
# The barrier island species and the bottomland hardwood forest species are each represented by a single
# sheet.
#
# The function performs the following steps:\n
def config(self, estFilename, mortFilename):
errorMessage = ''
###################################################
##
# - __Step 1__: Read the VegTypeNames sheet from the
# establishment and senescence files.
#
# The VegTypeNames file is where we get the
# names of the species in the model. If this
# sheet does not exist in the Excel files,
# or if the files do not exist, raise and
# exception.
###################################################
try:
estData = pandas.read_excel(estFilename, 'VegTypeNames', index_col=None)
except IOError as error:
errorMessage += 'SpeciesModelList: Error: Could not open file for reading: ' + str(estFilename) + '\n'
errorMessage += 'SpeciesModelList: Error: Additional error info: ' + str(error) + '\n';
except xlrd.biffh.XLRDError as error:
errorMessage += 'SpeciesModelList: Error: While opening : ' + str(estFilename) + '\n'
errorMessage += 'SpeciesModelList: Error: Additional error info: ' + str(error) + '\n';
try:
mortData = pandas.read_excel(mortFilename, 'VegTypeNames', index_col=None)
except IOError as error:
errorMessage += 'SpeciesModelList: Error: Could not open file for reading: ' + str(estFilename) + '\n' #shouldn't this be mortFilename?
errorMessage += 'SpeciesModelList: Error: Additional error info: ' + str(error) + '\n';
except xlrd.biffh.XLRDError as error:
errorMessage += 'SpeciesModelList: Error: While opening : ' + str(estFilename) + '\n'
errorMessage += 'SpeciesModelList: Error: Additional error info: ' + str(error) + '\n';
if len(errorMessage):
raise RuntimeError(errorMessage);
###################################################
##
# - __Step 2__: Get the list of species from the 'Symbol'
# column. Raise exceptions as needed.
#
###################################################
try:
speciesList = estData['Symbol']
except KeyError as error:
errorMessage += 'SpeciesModelList: Error: Symbol column not defined in establishment tables \n'
raise RuntimeError(errorMessage);
###################################################
##
# - __Step 3__: Read the establishment and senescence tables.
#
# For each species, configure the P & D
# Functions for each species and push everything
# into a dictionary (dict).
#
###################################################
for spSymbol in speciesList:
spInfo = estData[ estData['Symbol'] == spSymbol ].to_dict('records')[0]
spID = spInfo['ID']
spName = spInfo['Common Name']
spModelType = spInfo['ModelType']
spHabitat = spInfo['Habitat']
spDspClass = spInfo['Dispersal Class']
spFFIBSScore = spInfo['FFIBS score']
print(('SpeciesModelList: Msg: Configuring model for species ' + str(spSymbol) + ', model type is ' + spModelType + '.'))
###########################################
# Bottomland Hardwood Forest Model
#
###########################################
if ( spModelType == 'BottomlandHardwoodForestModel'):
reader = function.ReadVegTable1D()
Pdata = None
Ddata = None
try:
Pdata = reader.read(estFilename, 'BottomlandHardwoodForest', spSymbol)
except RuntimeError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
except ValueError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
try:
Ddata = reader.read(mortFilename, 'BottomlandHardwoodForest', spSymbol)
except RuntimeError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
except ValueError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
spModel = BottomlandHardwoodForestModel(index=spID, name=spName, abr=spSymbol, habitat = spHabitat, dspClass=spDspClass, ffibsScore=spFFIBSScore, cover=0, loc=-1, Pdata=Pdata, Ddata=Ddata)
self.__setitem__(spSymbol, spModel)
###########################################
# Emergent Wetland Model
#
###########################################
elif (spModelType == 'EmergentWetlandModel'):
reader = function.ReadVegTable2D()
Pdata = None
Ddata = None
try:
Pdata = reader.read(estFilename, spSymbol)
except RuntimeError as error:
errorMessage += str(error) + '\n';
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
except ValueError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
try:
Ddata = reader.read(mortFilename, spSymbol)
except RuntimeError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
except ValueError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
spModel = EmergentWetlandModel(index=spID, name=spName, abr=spSymbol, habitat = spHabitat, dspClass=spDspClass, ffibsScore=spFFIBSScore, cover=0, loc=-1, Pdata=Pdata, Ddata=Ddata)
self.__setitem__(spSymbol, spModel)
###########################################
# Swamp Forest Model
#
###########################################
elif (spModelType == 'SwampForestModel'):
reader = function.ReadVegTable2D()
Pdata = None
Ddata = None
try:
Pdata = reader.read(estFilename, spSymbol)
except RuntimeError as error:
errorMessage += str(error) + '\n';
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
except ValueError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
try:
Ddata = reader.read(mortFilename, spSymbol)
except RuntimeError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
except ValueError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
spModel = SwampForestModel(index=spID, name=spName, abr=spSymbol, habitat = spHabitat, dspClass=spDspClass, ffibsScore=spFFIBSScore, cover=0, loc=-1, Pdata=Pdata, Ddata=Ddata)
self.__setitem__(spSymbol, spModel)
###########################################
# Floating Marsh Model
#
###########################################
elif (spModelType == 'FloatingMarshModel'):
reader = function.ReadVegTable2D()
Pdata = None
Ddata = None
try:
Pdata = reader.read(estFilename, spSymbol)
except RuntimeError as error:
errorMessage += str(error) + '\n';
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
except ValueError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
try:
Ddata = reader.read(mortFilename, spSymbol)
except RuntimeError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
except ValueError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
spModel = FloatingMarshModel(index=spID, name=spName, abr=spSymbol, habitat = spHabitat, dspClass=spDspClass, ffibsScore=spFFIBSScore, cover=0, loc=-1, Pdata=Pdata, Ddata=Ddata)
self.__setitem__(spSymbol, spModel)
###########################################
# Submerged Aquatic Vegetation Model
# NOT USED IN 2023 MASTER PLAN MODEL
###########################################
elif ( spModelType == 'SAVModel'):
savData = None
try:
savData = pandas.read_excel(estFilename, spSymbol, index_col=0 ).to_dict('dict')['Value']
except IOError as error:
errorMessage += 'SpeciesModelList: Error : Could not open file for reading : ' + estFilename + '\n'
errorMessage += 'SpeciesModelList: Extra error info: ' + str(error) + '\n'
except xlrd.biffh.XLRDError as error:
errorMessage += 'SpeciesModelList: Error : Could not find sheet name ' + spSymbol + ' in file ' + estFilename + '\n'
errorMessage += 'SpeciesModelList: Extra error info: ' + str(error) + '\n'
except KeyError as error:
errorMessage += 'SpeciesModelList: Error : Dictionary key error. SAV table probably has wrong column headings\n'
errorMessage += 'SpeciesModelList: Error : '
spModel = SAVModel(index=spID, name=spName, abr=spSymbol, habitat=spHabitat, dspClass=spDspClass, ffibsScore=spFFIBSScore, cover=0, loc=-1, SAVData=savData)
self.__setitem__(spSymbol, spModel)
###########################################
# Barrier Island Model
#
###########################################
elif ( spModelType == 'BarrierIslandModel'):
reader = function.ReadVegTable1D()
Pdata = None
Ddata = None
try:
Pdata = reader.read(estFilename, 'BarrierIsland', spSymbol)
except RuntimeError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
except ValueError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
try:
Ddata = reader.read(mortFilename, 'BarrierIsland', spSymbol)
except RuntimeError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
except ValueError as error:
errorMessage += str(error) + '\n'
errorMessage += 'SpeciesModelList: Error: error while working on species ' + str(spSymbol) + '\n'
spModel = BarrierIslandModel(index=spID, name=spName, abr=spSymbol, habitat=spHabitat, dspClass=spDspClass,ffibsScore=spFFIBSScore, cover=0, loc=-1, Pdata=Pdata, Ddata=Ddata)
self.__setitem__(spSymbol, spModel)
###########################################
# Null Model
#
###########################################
elif ( spModelType == 'NullModel'):
spModel = NullModel(index=spID, name=spName, abr=spSymbol, habitat=spHabitat, dspClass=spDspClass, ffibsScore=spFFIBSScore, cover=0, loc=-1)
self.__setitem__(spSymbol, spModel)
###########################################
# Null Model Coverage
#
###########################################
elif ( spModelType == 'NullModel_Coverage'):
spModel = NullModel_Coverage(index=spID, name=spName, abr=spSymbol, habitat=spHabitat, dspClass=spDspClass, ffibsScore=spFFIBSScore, cover=0, loc=-1)
self.__setitem__(spSymbol, spModel)
###########################################
# Error State
#
###########################################
else:
errorMessage += 'SpeciesModelList: Error: Unknown model type specified : ' + spModelType + '\n'
if len(errorMessage):
raise RuntimeError(errorMessage)
##\class Params
##\brief This class is the interface between the outside world and the model.
##\role{Machinery}
##\detail This class is an interface between the internal components of the model
# and the outside world. That is, everything that is read in from outside the
# model is stored in an object of class Params. Params then makes all of this
# information available to the other model components.
#
# It is important to note that
# there is only meant to be ONE object derived from this class, and that object
# is owned by the object of class Model.
#
# Params handles reading values from the model configuration file. Params
# also manages all of the model IO streams, as well as the landscape.Landscape
# objects that hold the spatial data files used by the model, including the
# hydrology, salinity, elevation, initial conditions and other spatial data sets. Params also
# holds a special object of type model.SpeciesModelList. This class is
# used to store the the growth and senescence tables for each species along with
# any other species specific information.
class Params(object):
##\brief Class constructor
def __init__(self):
##\brief Holds the configuration information
self.configDict = config.Config()
##\brief Model start year
self.startYear = 0
##\brief Model end year
self.endYear = 0
##\brief List of years to read data from the wetland morph output file.
self.wetlandMorphYears = []
##\brief List of model input filenames.
#
self.inputStrm = {'WaveAmplitudeFile' :None, \
'MeanSalinityFile' :None, \
'SummerMeanWaterDepthFile' :None, \
'SummerMeanSalinityFile' :None, \
'SummerMeanTempFile' :None, \
'HeightAboveWaterFile' :None, \
'BarrierIslandEstCondFile' :None, \
'BarrierIslandHeightAboveWaterFile':None, \
'WetlandMorphLandWaterFile' :None, \
'AcuteSalinityStressFile' :None, \
'TreeEstCondFile' :None }
##\brief List of model output filenames.
#
self.outputStrm = { 'OutputFile' :None}
##\brief The annual wave amplitude map
self.waveAmp = landscape.Landscape()
##\brief The annual mean salinity map
self.meanSal = landscape.Landscape()
##\brief The summer mean water depth map
self.smDepth = landscape.Landscape()
##\brief The summer mean water salinity map
self.smSal = landscape.Landscape()
##\brief The summer mean salinity map
self.smTemp = landscape.Landscape()
##\brief The barrier island establishment condition map
self.biEstCond = landscape.Landscape()
##\brief The barrier height above water file
self.biHeightAboveWater = landscape.Landscape()
##\brief The map of heights above water map
self.heightAboveWater = landscape.Landscape()
##\brief The land/water map
self.landWater = landscape.Landscape()
##\brief The map of accutue salinity stress
self.acuteSal = landscape.Landscape()
##\brief The tree establishment conditions map
self.treeEstCond = landscape.Landscape() # TreeEstCondFile
##\brief The model initial conditions.
#
self.initCond = landscape.LandscapePlus() # InitialConditionFile
##\brief The species model list (SpeciesModelList)
#
self.spModelList = SpeciesModelList()
##\brief The elevation threshold for tree establishment (soon to be deprecated).
#
self.elevationThreshold = 0.1525
self.yearFormatString = '{:02d}'
##\brief Open input/output files
##\param key The keyword name for the file as it appears in the configuration file.
##\param mode Should the file be opened for reading or writing.
##\details This is a convenience function. It checks to make sure the
# file actually exists and opens if it does. If any problems are encountered,
# such as file not existing or cannot be opened, an exception is raised.
def open_file(self, key, mode):
try:
filename = self.configDict[key];
except KeyError as error:
errorMessage = 'Params: Error: ' + str(key) + ' is not defined in the configuration file.\n'
errorMessage += 'Params: Error: Additional error info : ' + str(error) + '\n'
raise RuntimeError(errorMessage);
try:
strm = open(filename, mode)
except IOError as error:
errorMessage = 'Params: Error: Could not open the file ' + filename + (' for reading' if mode == 'r' else ' for writing') +'\n'
errorMessage += 'Params: Error: Additional error info : ' + str(error) + '\n'
raise RuntimeError(errorMessage);
return strm
##\brief Read the model configuration information.
##\param argv A object containing the name of the configuration file.
##\details This member function reads in the information
# contained in the model configuration file and sets up
# a number of program elements based on this information
#
# The function performs the follwing steps:
#
def config(self, argv):
errorMessage = ''
###################################################
##
# - __Step 1__: Read in the configuration data from the
# configuration file.
#
###################################################
try:
self.configDict.config(argv);
except RuntimeError as error:
errorMessage = 'Params: Error: An error occurred reading the configuration file.\n' + str(error)
raise RuntimeError(errorMessage)
###################################################
##
# - __Step 1.5__: Get/set some detail assets for the model
#
###################################################
if 'YearFormatString' in self.configDict:
self.yearFormatString = self.configDict['YearFormatString']
print(('Params: Msg: Using user defined year format string : ' + self.yearFormatString))
###################################################
##
# - __Step 2__: Get the start end end year of the simulation
#
###################################################
try:
self.startYear = int( self.configDict['StartYear'] )
print(('Params: Msg: StartYear = ' + str(self.startYear)))
except KeyError as error:
errorMessage += 'Params: Error: StartYear is not defined in the configuration file\n'
try:
self.endYear = int( self.configDict['EndYear'])
print(('Params: Msg: EndYear = ' + str(self.endYear)))
except KeyError as error:
errorMessage += 'Params: Error: EndYear is not defined in the configuration file\n'
###################################################
##
# - __Step 3__: Read the initial conditions file
#
###################################################
try:
print(('Params: Msg: Reading initial conditions from ' + self.configDict['InitialConditionFile']))