| 1 | # CoralReefConnectivity.py - Implements Eric Treml's coral reef
|
|---|
| 2 | # connectivity analysis.
|
|---|
| 3 | #
|
|---|
| 4 | # Copyright (C) 2008 Jason J. Roberts and Eric A. Treml
|
|---|
| 5 | #
|
|---|
| 6 | # This program is free software; you can redistribute it and/or
|
|---|
| 7 | # modify it under the terms of the GNU General Public License
|
|---|
| 8 | # as published by the Free Software Foundation; either version 2
|
|---|
| 9 | # of the License, or (at your option) any later version.
|
|---|
| 10 | #
|
|---|
| 11 | # This program is distributed in the hope that it will be useful,
|
|---|
| 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 14 | # GNU General Public License (available in the file LICENSE.TXT)
|
|---|
| 15 | # for more details.
|
|---|
| 16 | #
|
|---|
| 17 | # You should have received a copy of the GNU General Public License
|
|---|
| 18 | # along with this program; if not, write to the Free Software
|
|---|
| 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|---|
| 20 |
|
|---|
| 21 | import os
|
|---|
| 22 |
|
|---|
| 23 | from GeoEco.DataProducts.Aviso import AvisoGriddedGeostrophicCurrents, _AvisoGriddedProduct_LongDescription
|
|---|
| 24 | from GeoEco.DataProducts.HYCOM import HYCOMGOMl0044D, _HYCOMGOMl004_LongDescription, HYCOMGLBa008Equatorial4D, _HYCOMGLBa008Equatorial_LongDescription
|
|---|
| 25 | from GeoEco.DataProducts.NOAA.OSCAR import OSCAR5DayThirdDegreeCurrents, _OSCAR_LongDescription
|
|---|
| 26 | from GeoEco.DynamicDocString import DynamicDocString
|
|---|
| 27 | from GeoEco.Internationalization import _
|
|---|
| 28 | from GeoEco.Logging import Logger, ProgressReporter
|
|---|
| 29 | from GeoEco.Types import EnvelopeTypeMetadata
|
|---|
| 30 |
|
|---|
| 31 | class CoralReefConnectivity(object):
|
|---|
| 32 | __doc__ = DynamicDocString()
|
|---|
| 33 |
|
|---|
| 34 | @classmethod
|
|---|
| 35 | def CreateSimulationFromArcGISRasters(cls, simulationDirectory, reefIDsRaster, reefCoverRaster, waterMaskRaster, crosses180=False, overwriteExisting=False):
|
|---|
| 36 | cls.__doc__.Obj.ValidateMethodInvocation()
|
|---|
| 37 |
|
|---|
| 38 | # Validate the coordinate systems, extents, and cell sizes of
|
|---|
| 39 | # the input rasters.
|
|---|
| 40 |
|
|---|
| 41 | from GeoEco.ArcGIS import GeoprocessorManager
|
|---|
| 42 | gp = GeoprocessorManager.GetWrappedGeoprocessor()
|
|---|
| 43 |
|
|---|
| 44 | describeReefIDsRaster = gp.Describe(reefIDsRaster)
|
|---|
| 45 | describereefCoverRaster = gp.Describe(reefCoverRaster)
|
|---|
| 46 | describeWaterMaskRaster = gp.Describe(waterMaskRaster)
|
|---|
| 47 |
|
|---|
| 48 | if describeReefIDsRaster.SpatialReference.Type.lower() != u'projected':
|
|---|
| 49 | Logger.RaiseException(ValueError(_(u'ArcGIS reports that the reef IDs raster %(raster)s uses a %(type)s coordinate system. It must use a projected coordinate system. Please project it and try again.') % {u'raster': reefIDsRaster, u'type': describeReefIDsRaster.SpatialReference.Type.lower()}))
|
|---|
| 50 | if describeReefIDsRaster.SpatialReference.LinearUnitName.lower() != u'meter':
|
|---|
| 51 | Logger.RaiseException(ValueError(_(u'ArcGIS reports that the reef IDs raster %(raster)s uses the linear unit "%(unit)s". It must use a coordinate system that has meters as its linear unit. Please project it to a coordinate system that uses meters and try again.') % {u'raster': reefIDsRaster, u'unit': describeReefIDsRaster.SpatialReference.LinearUnitName.lower()}))
|
|---|
| 52 |
|
|---|
| 53 | reefIDsRasterCS = gp.CreateSpatialReference(describeReefIDsRaster.SpatialReference).split(';')[0]
|
|---|
| 54 | reefCoverRasterCS = gp.CreateSpatialReference(describereefCoverRaster.SpatialReference).split(';')[0]
|
|---|
| 55 | waterMaskRasterCS = gp.CreateSpatialReference(describeWaterMaskRaster.SpatialReference).split(';')[0]
|
|---|
| 56 |
|
|---|
| 57 | if reefCoverRasterCS.lower() != reefIDsRasterCS.lower():
|
|---|
| 58 | Logger.RaiseException(ValueError(_(u'The reef cover raster %(raster1)s uses a different coordinate system than the reef IDs raster, %(raster2)s. Please project the reef cover raster to the reef IDs raster\'s coordinate system and try again.') % {u'raster1': reefCoverRaster, u'raster2': reefIDsRaster}))
|
|---|
| 59 | if waterMaskRasterCS.lower() != reefIDsRasterCS.lower():
|
|---|
| 60 | Logger.RaiseException(ValueError(_(u'The water mask raster %(raster1)s uses a different coordinate system than the reef IDs raster, %(raster2)s. Please project the water mask raster to the reef IDs raster\'s coordinate system and try again.') % {u'raster1': waterMaskRaster, u'raster2': reefIDsRaster}))
|
|---|
| 61 |
|
|---|
| 62 | reefIDsRasterLeft, reefIDsRasterBottom, reefIDsRasterRight, reefIDsRasterTop = EnvelopeTypeMetadata.ParseFromArcGISString(describeReefIDsRaster.Extent)
|
|---|
| 63 | reefCoverRasterLeft, reefCoverRasterBottom, reefCoverRasterRight, reefCoverRasterTop = EnvelopeTypeMetadata.ParseFromArcGISString(describereefCoverRaster.Extent)
|
|---|
| 64 | waterMaskRasterLeft, waterMaskRasterBottom, waterMaskRasterRight, waterMaskRasterTop = EnvelopeTypeMetadata.ParseFromArcGISString(describeWaterMaskRaster.Extent)
|
|---|
| 65 |
|
|---|
| 66 | if abs(reefCoverRasterLeft - reefIDsRasterLeft) > 0.001 or abs(reefCoverRasterBottom - reefIDsRasterBottom) > 0.001 or abs(reefCoverRasterRight - reefIDsRasterRight) > 0.001 or abs(reefCoverRasterTop - reefIDsRasterTop) > 0.001 or abs(describereefCoverRaster.MeanCellWidth - describeReefIDsRaster.MeanCellWidth) > 0.001 or abs(describereefCoverRaster.MeanCellHeight - describeReefIDsRaster.MeanCellHeight) > 0.001:
|
|---|
| 67 | Logger.RaiseException(ValueError(_(u'The reef cover raster %(raster1)s has a different extent or cell size than the reef IDs raster, %(raster2)s. Please prepare a reef cover raster that has the same extent and cell size as the reef IDs raster and try again.') % {u'raster1': reefCoverRaster, u'raster2': reefIDsRaster}))
|
|---|
| 68 | if abs(waterMaskRasterLeft - reefIDsRasterLeft) > 0.001 or abs(waterMaskRasterBottom - reefIDsRasterBottom) > 0.001 or abs(waterMaskRasterRight - reefIDsRasterRight) > 0.001 or abs(waterMaskRasterTop - reefIDsRasterTop) > 0.001 or abs(describeWaterMaskRaster.MeanCellWidth - describeReefIDsRaster.MeanCellWidth) > 0.001 or abs(describeWaterMaskRaster.MeanCellHeight - describeReefIDsRaster.MeanCellHeight) > 0.001:
|
|---|
| 69 | Logger.RaiseException(ValueError(_(u'The water mask raster %(raster1)s has a different extent or cell size than the reef IDs raster, %(raster2)s. Please prepare a water mask raster that has the same extent and cell size as the reef IDs raster and try again.') % {u'raster1': reefCoverRaster, u'raster2': waterMaskRaster}))
|
|---|
| 70 |
|
|---|
| 71 | # Validate that 0 is not used as a reef ID. The MATLAB code
|
|---|
| 72 | # uses 0 to represent cells where no reefs are present.
|
|---|
| 73 |
|
|---|
| 74 | from GeoEco.DataManagement.ArcGISRasters import ArcGISRaster
|
|---|
| 75 | from GeoEco.DataManagement.Directories import Directory, TemporaryDirectory
|
|---|
| 76 | import numpy
|
|---|
| 77 |
|
|---|
| 78 | tempDir = TemporaryDirectory()
|
|---|
| 79 | reefIDsImage, reefIDsNoDataValue = ArcGISRaster.ToNumpyArray(reefIDsRaster, tempRasterPath=os.path.join(tempDir.Path, u'reef_ids'))
|
|---|
| 80 | if numpy.any(reefIDsImage == 0) and reefIDsNoDataValue != 0:
|
|---|
| 81 | Logger.RaiseException(ValueError(_(u'The reef IDs raster %(raster)s uses 0 as a reef ID. This is not allowed. Please remove the value 0 from the reef IDs raster and try again.') % {u'raster': reefIDsRaster}))
|
|---|
| 82 |
|
|---|
| 83 | # Validate that reef cover raster ranges between 0.0 and 1.0.
|
|---|
| 84 |
|
|---|
| 85 | reefCoverImage, noDataValue = ArcGISRaster.ToNumpyArray(reefCoverRaster, tempRasterPath=os.path.join(tempDir.Path, u'reef_areas'))
|
|---|
| 86 | if noDataValue is not None:
|
|---|
| 87 | reefCoverImage[reefCoverImage == noDataValue] = 0
|
|---|
| 88 | if numpy.any(reefCoverImage < 0) or numpy.any(reefCoverImage > 1):
|
|---|
| 89 | Logger.RaiseException(ValueError(_(u'The reef cover raster %(raster)s includes values that are less than 0 or are greater than 1. The values of a cell of this raster is supposed to represent the proportion of the cell\'s area that is occupied by reef, thus the value is supposed to be between 0 and 1. Please prepare a raster that has the correct values and try again.') % {u'raster': reefCoverRaster}))
|
|---|
| 90 |
|
|---|
| 91 | # Create the simulation directory and the ReefData
|
|---|
| 92 | # subdirectory.
|
|---|
| 93 |
|
|---|
| 94 | oldLogInfoAsDebug = Logger.LogInfoAndSetInfoToDebug(_(u'Creating and initializing the simulation directory %(dir)s...') % {u'dir': simulationDirectory})
|
|---|
| 95 | Logger.SetLogInfoAsDebug(True)
|
|---|
| 96 | try:
|
|---|
| 97 | from GeoEco.DataManagement.Directories import Directory, TemporaryDirectory
|
|---|
| 98 |
|
|---|
| 99 | Directory.Create(simulationDirectory)
|
|---|
| 100 | Directory.Create(os.path.join(simulationDirectory, u'ReefData'))
|
|---|
| 101 |
|
|---|
| 102 | # Copy the reef IDs raster into the ReefData directory.
|
|---|
| 103 |
|
|---|
| 104 | ArcGISRaster.Copy(reefIDsRaster, os.path.join(simulationDirectory, u'ReefData', u'reef_ids'))
|
|---|
| 105 |
|
|---|
| 106 | # Copy the reef cover raster into the ReefData directory,
|
|---|
| 107 | # setting the NoData values and non-reef cells to 0 in the process.
|
|---|
| 108 |
|
|---|
| 109 | if GeoprocessorManager.GetArcGISMajorVersion() >= 10:
|
|---|
| 110 | mapAlgebraExpression = u'float(con(isnull( [%(raster1)s] ) == 1 || isnull( [%(raster2)s] ) == 1, 0.0, [%(raster1)s] ))' % {u'raster1': reefCoverRaster, u'raster2': reefIDsRaster}
|
|---|
| 111 | else:
|
|---|
| 112 | mapAlgebraExpression = u'float(con(isnull( %(raster1)s ) == 1 || isnull( %(raster2)s ) == 1, 0.0, %(raster1)s ))' % {u'raster1': reefCoverRaster, u'raster2': reefIDsRaster}
|
|---|
| 113 | gp.SingleOutputMapAlgebra_sa(mapAlgebraExpression, os.path.join(tempDir.Path, u'reef_areas2'))
|
|---|
| 114 | ArcGISRaster.Copy(os.path.join(tempDir.Path, u'reef_areas2'), os.path.join(simulationDirectory, u'ReefData', u'reef_areas'))
|
|---|
| 115 |
|
|---|
| 116 | # Copy the water mask raster into the ReefData directory,
|
|---|
| 117 | # normalizing it to integer values where 1 is water, 0 is
|
|---|
| 118 | # land.
|
|---|
| 119 |
|
|---|
| 120 | if GeoprocessorManager.GetArcGISMajorVersion() >= 10:
|
|---|
| 121 | mapAlgebraExpression = u'con(isnull( [%(raster)s] ) || [%(raster)s] == 0, 0, 1)' % {u'raster': waterMaskRaster}
|
|---|
| 122 | else:
|
|---|
| 123 | mapAlgebraExpression = u'con(isnull( %(raster)s ) || %(raster)s == 0, 0, 1)' % {u'raster': waterMaskRaster}
|
|---|
| 124 | gp.SingleOutputMapAlgebra_sa(mapAlgebraExpression, os.path.join(tempDir.Path, u'water_mask'))
|
|---|
| 125 | ArcGISRaster.Copy(os.path.join(tempDir.Path, u'water_mask'), os.path.join(simulationDirectory, u'ReefData', u'water_mask'))
|
|---|
| 126 |
|
|---|
| 127 | # Create the reef_geometry file by calling Spatial
|
|---|
| 128 | # Analyst's Zonal Geometry As Table tool. (Note that this
|
|---|
| 129 | # tool will create a .dbf file no matter what, even if we
|
|---|
| 130 | # give it a .csv or .txt extension. This is very annoying,
|
|---|
| 131 | # because we can't read it easily without going through a
|
|---|
| 132 | # database API, which is slow.)
|
|---|
| 133 |
|
|---|
| 134 | gp.ZonalGeometryAsTable_sa(os.path.join(simulationDirectory, u'ReefData', u'reef_ids'), u'Value', os.path.join(simulationDirectory, u'ReefData', u'reef_geometry.dbf'), describeReefIDsRaster.MeanCellWidth)
|
|---|
| 135 |
|
|---|
| 136 | # Create the directories that will hold the currents
|
|---|
| 137 | # rasters.
|
|---|
| 138 |
|
|---|
| 139 | Directory.Create(os.path.join(simulationDirectory, u'Currents'))
|
|---|
| 140 | Directory.Create(os.path.join(simulationDirectory, u'Currents', u'u'))
|
|---|
| 141 | Directory.Create(os.path.join(simulationDirectory, u'Currents', u'v'))
|
|---|
| 142 |
|
|---|
| 143 | # Create the config file that stores properties of the
|
|---|
| 144 | # simulation.
|
|---|
| 145 |
|
|---|
| 146 | from ConfigParser import SafeConfigParser
|
|---|
| 147 |
|
|---|
| 148 | scp = SafeConfigParser()
|
|---|
| 149 | scp.add_section(u'Simulation')
|
|---|
| 150 | scp.set(u'Simulation', u'Crosses180', unicode(crosses180))
|
|---|
| 151 | scp.set(u'Simulation', u'CurrentsLoaded', unicode(False))
|
|---|
| 152 | scp.set(u'Simulation', u'CurrentsProduct', u'')
|
|---|
| 153 | f = file(os.path.join(simulationDirectory, u'Simulation.ini'), 'w')
|
|---|
| 154 | try:
|
|---|
| 155 | scp.write(f)
|
|---|
| 156 | finally:
|
|---|
| 157 | try:
|
|---|
| 158 | f.close()
|
|---|
| 159 | except:
|
|---|
| 160 | pass
|
|---|
| 161 |
|
|---|
| 162 | finally:
|
|---|
| 163 | Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
|
|---|
| 164 |
|
|---|
| 165 | @classmethod
|
|---|
| 166 | def LoadAvisoGeostrophicCurrentsIntoSimulation(cls, simulationDirectory, username, password, product, startDate, endDate, timeout=60, maxRetryTime=120, cacheDirectory=None):
|
|---|
| 167 | cls.__doc__.Obj.ValidateMethodInvocation()
|
|---|
| 168 |
|
|---|
| 169 | # Parse and validate the Simulation.ini file.
|
|---|
| 170 |
|
|---|
| 171 | scp, crosses180, currentsLoaded, currentsProduct = cls._ReadCurrentsInfoFromSimulationINI(simulationDirectory)
|
|---|
| 172 |
|
|---|
| 173 | # If the simulation already has currents loaded in it from a
|
|---|
| 174 | # different product, report an error.
|
|---|
| 175 |
|
|---|
| 176 | if currentsLoaded and currentsProduct != u'Aviso ' + product:
|
|---|
| 177 | Logger.RaiseException(ValueError(_(u'Cannot load Aviso %(prod1)s currents data into the simulation in directory %(dir)s because that simulation already has %(prod2)s currents data loaded into it. You can load additional %(prod2)s data, if you like, but to use Aviso %(prod1)s data, you must create a new simulation.') % {u'dir': simulationDirectory, u'prod1': product, u'prod2': currentsProduct}))
|
|---|
| 178 |
|
|---|
| 179 | # First, download and create Aviso current rasters in an
|
|---|
| 180 | # Aviso-specific directory. These will have the Aviso
|
|---|
| 181 | # projection, extent, and cell size. We still need to project
|
|---|
| 182 | # them to the simulation's projection, extent, and cell size.
|
|---|
| 183 | #
|
|---|
| 184 | # TODO: Need to handle rotation?
|
|---|
| 185 |
|
|---|
| 186 | avisoCurrentsDirectory = os.path.join(simulationDirectory, 'OriginalAvisoCurrents')
|
|---|
| 187 | AvisoGriddedGeostrophicCurrents.CreateArcGISRasters(username, password, product, u'u', avisoCurrentsDirectory, rasterNameExpressions=['u', '%%Y', 'u%%Y%%j0000.img'], startDate=startDate, endDate=endDate, timeout=timeout, maxRetryTime=maxRetryTime, cacheDirectory=cacheDirectory)
|
|---|
| 188 | AvisoGriddedGeostrophicCurrents.CreateArcGISRasters(username, password, product, u'v', avisoCurrentsDirectory, rasterNameExpressions=['v', '%%Y', 'v%%Y%%j0000.img'], startDate=startDate, endDate=endDate, timeout=timeout, maxRetryTime=maxRetryTime, cacheDirectory=cacheDirectory)
|
|---|
| 189 |
|
|---|
| 190 | # Record in the Simulation.ini file that we downloaded some
|
|---|
| 191 | # currents and then project, snap, and clip them to the
|
|---|
| 192 | # projection, extent, and cell size of the reef IDs raster.
|
|---|
| 193 |
|
|---|
| 194 | cls._FinishLoadingCurrents(simulationDirectory, u'Aviso ' + product, u'Center', 86400, avisoCurrentsDirectory, u'setnull( inputRaster > 1000000 || inputRaster < -1000000, inputRaster / 100)') # Use Map Algebra to Convert from cm/s to to m/s and mask bogus values introduced by ArcGIS
|
|---|
| 195 |
|
|---|
| 196 | # Return successfully.
|
|---|
| 197 |
|
|---|
| 198 | return simulationDirectory
|
|---|
| 199 |
|
|---|
| 200 | @classmethod
|
|---|
| 201 | def LoadOSCARCurrentsIntoSimulation(cls, simulationDirectory, startDate, endDate, timeout=60, maxRetryTime=120, cacheDirectory=None):
|
|---|
| 202 | cls.__doc__.Obj.ValidateMethodInvocation()
|
|---|
| 203 |
|
|---|
| 204 | # Parse and validate the Simulation.ini file.
|
|---|
| 205 |
|
|---|
| 206 | scp, crosses180, currentsLoaded, currentsProduct = cls._ReadCurrentsInfoFromSimulationINI(simulationDirectory)
|
|---|
| 207 |
|
|---|
| 208 | # If the simulation already has currents loaded in it from a
|
|---|
| 209 | # different product, report an error.
|
|---|
| 210 |
|
|---|
| 211 | if currentsLoaded and currentsProduct != u'OSCAR':
|
|---|
| 212 | Logger.RaiseException(ValueError(_(u'Cannot load OSCAR currents data into the simulation in directory %(dir)s because that simulation already has %(prod2)s currents data loaded into it. You can load additional %(prod2)s data, if you like, but to use OSCAR data, you must create a new simulation.') % {u'dir': simulationDirectory, u'prod2': currentsProduct}))
|
|---|
| 213 |
|
|---|
| 214 | # First, download and create OSCAR current rasters in an
|
|---|
| 215 | # OSCAR-specific directory. These will have the OSCAR
|
|---|
| 216 | # projection, extent, and cell size. We still need to project
|
|---|
| 217 | # them to the simulation's projection, extent, and cell size.
|
|---|
| 218 | #
|
|---|
| 219 | # TODO: Need to handle rotation?
|
|---|
| 220 |
|
|---|
| 221 | oscarCurrentsDirectory = os.path.join(simulationDirectory, 'OriginalOSCARCurrents')
|
|---|
| 222 | OSCAR5DayThirdDegreeCurrents.CreateArcGISRasters(u'u', oscarCurrentsDirectory, rasterNameExpressions=['u', '%%Y', 'u%%Y%%j0000.img'], startDate=startDate, endDate=endDate, timeout=timeout, maxRetryTime=maxRetryTime, cacheDirectory=cacheDirectory)
|
|---|
| 223 | OSCAR5DayThirdDegreeCurrents.CreateArcGISRasters(u'v', oscarCurrentsDirectory, rasterNameExpressions=['v', '%%Y', 'v%%Y%%j0000.img'], startDate=startDate, endDate=endDate, timeout=timeout, maxRetryTime=maxRetryTime, cacheDirectory=cacheDirectory)
|
|---|
| 224 |
|
|---|
| 225 | # Record in the Simulation.ini file that we downloaded some
|
|---|
| 226 | # currents and then project, snap, and clip them to the
|
|---|
| 227 | # projection, extent, and cell size of the reef IDs raster.
|
|---|
| 228 |
|
|---|
| 229 | cls._FinishLoadingCurrents(simulationDirectory, u'OSCAR', u'Center', 6*86400, oscarCurrentsDirectory)
|
|---|
| 230 |
|
|---|
| 231 | # Return successfully.
|
|---|
| 232 |
|
|---|
| 233 | return simulationDirectory
|
|---|
| 234 |
|
|---|
| 235 | @classmethod
|
|---|
| 236 | def LoadHYCOMGOMl0044DCurrentsIntoSimulation(cls, simulationDirectory, startDate, endDate, depth=0., timeout=600, maxRetryTime=None, cacheDirectory=None):
|
|---|
| 237 | cls.__doc__.Obj.ValidateMethodInvocation()
|
|---|
| 238 |
|
|---|
| 239 | # Parse and validate the Simulation.ini file.
|
|---|
| 240 |
|
|---|
| 241 | scp, crosses180, currentsLoaded, currentsProduct = cls._ReadCurrentsInfoFromSimulationINI(simulationDirectory)
|
|---|
| 242 |
|
|---|
| 243 | # If the simulation already has currents loaded in it from a
|
|---|
| 244 | # different product or depth, report an error.
|
|---|
| 245 |
|
|---|
| 246 | if currentsLoaded and currentsProduct != u'HYCOM GOMl0.04 ' + unicode(int(depth)) + u' m':
|
|---|
| 247 | Logger.RaiseException(ValueError(_(u'Cannot load %(prod1)s currents data into the simulation in directory %(dir)s because that simulation already has %(prod2)s currents data loaded into it. You can load additional %(prod2)s data, if you like, but to use %(prod1)s data, you must create a new simulation.') % {u'dir': simulationDirectory, u'prod1': u'HYCOM GOMl0.04 ' + unicode(int(depth)) + u' m', u'prod2': currentsProduct}))
|
|---|
| 248 |
|
|---|
| 249 | # First, download and create HYCOM current rasters in a
|
|---|
| 250 | # HYCOM-specific directory. These will have the HYCOM
|
|---|
| 251 | # projection, extent, and cell size. We still need to project
|
|---|
| 252 | # them to the simulation's projection, extent, and cell size.
|
|---|
| 253 |
|
|---|
| 254 | hycomCurrentsDirectory = os.path.join(simulationDirectory, 'OriginalHYCOMCurrents')
|
|---|
| 255 | HYCOMGOMl0044D.CreateArcGISRasters(u'u', hycomCurrentsDirectory, rasterNameExpressions=['%(VariableName)s', '%%Y', '%(VariableName)s%%Y%%j0000.img'], minDepth=depth, maxDepth=depth, startDate=startDate, endDate=endDate, timeout=timeout, maxRetryTime=maxRetryTime, cacheDirectory=cacheDirectory)
|
|---|
| 256 | HYCOMGOMl0044D.CreateArcGISRasters(u'v', hycomCurrentsDirectory, rasterNameExpressions=['%(VariableName)s', '%%Y', '%(VariableName)s%%Y%%j0000.img'], minDepth=depth, maxDepth=depth, startDate=startDate, endDate=endDate, timeout=timeout, maxRetryTime=maxRetryTime, cacheDirectory=cacheDirectory)
|
|---|
| 257 |
|
|---|
| 258 | # Record in the Simulation.ini file that we downloaded some
|
|---|
| 259 | # currents and then project, snap, and clip them to the
|
|---|
| 260 | # projection, extent, and cell size of the reef IDs raster.
|
|---|
| 261 |
|
|---|
| 262 | cls._FinishLoadingCurrents(simulationDirectory, u'HYCOM GOMl0.04 ' + unicode(int(depth)) + u' m', u'Center', 86400, hycomCurrentsDirectory)
|
|---|
| 263 |
|
|---|
| 264 | # Return successfully.
|
|---|
| 265 |
|
|---|
| 266 | return simulationDirectory
|
|---|
| 267 |
|
|---|
| 268 | @classmethod
|
|---|
| 269 | def LoadHYCOMGLBa0084DEquatorialCurrentsIntoSimulation(cls, simulationDirectory, startDate, endDate, depth=0., extendYExtent=False, timeout=60, maxRetryTime=120, cacheDirectory=None):
|
|---|
| 270 | cls.__doc__.Obj.ValidateMethodInvocation()
|
|---|
| 271 |
|
|---|
| 272 | # Parse and validate the Simulation.ini file.
|
|---|
| 273 |
|
|---|
| 274 | scp, crosses180, currentsLoaded, currentsProduct = cls._ReadCurrentsInfoFromSimulationINI(simulationDirectory)
|
|---|
| 275 |
|
|---|
| 276 | # If the simulation already has currents loaded in it from a
|
|---|
| 277 | # different product or depth, report an error.
|
|---|
| 278 |
|
|---|
| 279 | if currentsLoaded and currentsProduct != u'HYCOM GLBa0.08 Equatorial ' + unicode(int(depth)) + u' m':
|
|---|
| 280 | Logger.RaiseException(ValueError(_(u'Cannot load %(prod1)s currents data into the simulation in directory %(dir)s because that simulation already has %(prod2)s currents data loaded into it. You can load additional %(prod2)s data, if you like, but to use %(prod1)s data, you must create a new simulation.') % {u'dir': simulationDirectory, u'prod1': u'HYCOM GLBa0.08 Equatorial ' + unicode(int(depth)) + u' m', u'prod2': currentsProduct}))
|
|---|
| 281 |
|
|---|
| 282 | # First, download and create HYCOM current rasters in a
|
|---|
| 283 | # HYCOM-specific directory. These will have the HYCOM
|
|---|
| 284 | # projection, extent, and cell size. We still need to project
|
|---|
| 285 | # them to the simulation's projection, extent, and cell size.
|
|---|
| 286 |
|
|---|
| 287 | hycomCurrentsDirectory = os.path.join(simulationDirectory, 'OriginalHYCOMCurrents')
|
|---|
| 288 | HYCOMGLBa008Equatorial4D.CreateArcGISRasters(u'u', hycomCurrentsDirectory, rasterNameExpressions=['%(VariableName)s', '%%Y', '%(VariableName)s%%Y%%j0000.img'], extendYExtent=extendYExtent, minDepth=depth, maxDepth=depth, startDate=startDate, endDate=endDate, timeout=timeout, maxRetryTime=maxRetryTime, cacheDirectory=cacheDirectory)
|
|---|
| 289 | HYCOMGLBa008Equatorial4D.CreateArcGISRasters(u'v', hycomCurrentsDirectory, rasterNameExpressions=['%(VariableName)s', '%%Y', '%(VariableName)s%%Y%%j0000.img'], extendYExtent=extendYExtent, minDepth=depth, maxDepth=depth, startDate=startDate, endDate=endDate, timeout=timeout, maxRetryTime=maxRetryTime, cacheDirectory=cacheDirectory)
|
|---|
| 290 |
|
|---|
| 291 | # Record in the Simulation.ini file that we downloaded some
|
|---|
| 292 | # currents and then project, snap, and clip them to the
|
|---|
| 293 | # projection, extent, and cell size of the reef IDs raster.
|
|---|
| 294 |
|
|---|
| 295 | cls._FinishLoadingCurrents(simulationDirectory, u'HYCOM GLBa0.08 Equatorial ' + unicode(int(depth)) + u' m', u'Center', 86400, hycomCurrentsDirectory)
|
|---|
| 296 |
|
|---|
| 297 | # Return successfully.
|
|---|
| 298 |
|
|---|
| 299 | return simulationDirectory
|
|---|
| 300 |
|
|---|
| 301 | @classmethod
|
|---|
| 302 | def _FinishLoadingCurrents(cls, simulationDirectory, currentsProduct, currentsDateType, maxSecondsBetweenCurrentsImages, originalCurrentsDirectory, mapAlgebraExpression=None):
|
|---|
| 303 |
|
|---|
| 304 | # Write the Simulation.ini file, so that any new rasters
|
|---|
| 305 | # loaded into the simulation must be from the same product and
|
|---|
| 306 | # depth.
|
|---|
| 307 |
|
|---|
| 308 | scp.set(u'Simulation', u'CurrentsLoaded', unicode(True))
|
|---|
| 309 | scp.set(u'Simulation', u'CurrentsProduct', currentsProduct)
|
|---|
| 310 | scp.set(u'Simulation', u'CurrentsDateType', currentsDateType)
|
|---|
| 311 | scp.set(u'Simulation', u'MaxSecondsBetweenCurrentsImages', unicode(maxSecondsBetweenCurrentsImages))
|
|---|
| 312 | f = file(os.path.join(simulationDirectory, u'Simulation.ini'), 'w')
|
|---|
| 313 | try:
|
|---|
| 314 | scp.write(f)
|
|---|
| 315 | finally:
|
|---|
| 316 | try:
|
|---|
| 317 | f.close()
|
|---|
| 318 | except:
|
|---|
| 319 | pass
|
|---|
| 320 |
|
|---|
| 321 | # Obtain the projection, extent, and cell size of the reef IDs
|
|---|
| 322 | # raster, so we can project, snap, and clip the currents
|
|---|
| 323 | # rasters to match it.
|
|---|
| 324 |
|
|---|
| 325 | from GeoEco.ArcGIS import GeoprocessorManager
|
|---|
| 326 | gp = GeoprocessorManager.GetWrappedGeoprocessor()
|
|---|
| 327 |
|
|---|
| 328 | describeReefIDsRaster = gp.Describe(os.path.join(simulationDirectory, u'ReefData', u'reef_ids'))
|
|---|
| 329 | reefIDsRasterCS = gp.CreateSpatialReference(describeReefIDsRaster.SpatialReference).split(';')[0]
|
|---|
| 330 | reefIDsRasterLeft, reefIDsRasterBottom, reefIDsRasterRight, reefIDsRasterTop = EnvelopeTypeMetadata.ParseFromArcGISString(describeReefIDsRaster.Extent)
|
|---|
| 331 | reefIDsCellSize = describeReefIDsRaster.MeanCellWidth
|
|---|
| 332 |
|
|---|
| 333 | # Use a GeoEco function that calls Project_management to
|
|---|
| 334 | # project, snap, and clip the rasters all in one step.
|
|---|
| 335 |
|
|---|
| 336 | from GeoEco.DataManagement.ArcGISRasters import ArcGISRaster
|
|---|
| 337 |
|
|---|
| 338 | oldGPExtent = gp.Extent
|
|---|
| 339 | gp.Extent = describeReefIDsRaster.Extent
|
|---|
| 340 | try:
|
|---|
| 341 | ArcGISRaster.FindAndProjectClipAndOrExecuteMapAlgebra(originalCurrentsDirectory,
|
|---|
| 342 | os.path.join(simulationDirectory, u'Currents'),
|
|---|
| 343 | projectedCoordinateSystem=reefIDsRasterCS,
|
|---|
| 344 | resamplingTechnique=u'BILINEAR',
|
|---|
| 345 | projectedCellSize=reefIDsCellSize,
|
|---|
| 346 | registrationPoint=u'%g %g' % (reefIDsRasterLeft, reefIDsRasterBottom),
|
|---|
| 347 | mapAlgebraExpression=mapAlgebraExpression,
|
|---|
| 348 | wildcard=u'*.img',
|
|---|
| 349 | searchTree=True,
|
|---|
| 350 | outputRasterPythonExpression=u'os.path.join(outputWorkspace, os.path.splitext(inputRaster[len(workspaceToSearch)+1:])[0])',
|
|---|
| 351 | modulesToImport=[u'os'],
|
|---|
| 352 | skipExisting=True)
|
|---|
| 353 |
|
|---|
| 354 | # Reset the geoprocessing extent environment setting to
|
|---|
| 355 | # whatever the caller had before.
|
|---|
| 356 |
|
|---|
| 357 | finally:
|
|---|
| 358 | if oldGPExtent is not None:
|
|---|
| 359 | gp.Extent = oldGPExtent
|
|---|
| 360 |
|
|---|
| 361 | @classmethod
|
|---|
| 362 | def _ReadCurrentsInfoFromSimulationINI(cls, simulationDirectory):
|
|---|
| 363 | if not os.path.isfile(os.path.join(simulationDirectory, u'Simulation.ini')):
|
|---|
| 364 | Logger.RaiseException(ValueError(_(u'The directory %(dir)s does not appear to be a properly-initialized coral reef connectivity simulation directory: it does not contain a file called Simulation.ini. Please create a simulation directory using the Create Coral Reef Connectivity Simulation tool and try again.') % {u'dir': simulationDirectory}))
|
|---|
| 365 |
|
|---|
| 366 | from ConfigParser import SafeConfigParser
|
|---|
| 367 |
|
|---|
| 368 | scp = SafeConfigParser()
|
|---|
| 369 | f = file(os.path.join(simulationDirectory, u'Simulation.ini'), 'r')
|
|---|
| 370 | try:
|
|---|
| 371 | try:
|
|---|
| 372 | scp.readfp(f, os.path.join(simulationDirectory, u'Simulation.ini'))
|
|---|
| 373 | except:
|
|---|
| 374 | Logger.LogExceptionAsError(_(u'The directory %(dir)s does not appear to be a properly-initialized coral reef connectivity simulation directory: the file Simulation.ini in that directory could not be parsed. Please create a simulation directory using the Create Coral Reef Connectivity Simulation tool and try again.') % {u'dir': simulationDirectory})
|
|---|
| 375 | raise
|
|---|
| 376 | finally:
|
|---|
| 377 | try:
|
|---|
| 378 | f.close()
|
|---|
| 379 | except:
|
|---|
| 380 | pass
|
|---|
| 381 |
|
|---|
| 382 | try:
|
|---|
| 383 | crosses180 = scp.getboolean(u'Simulation', u'Crosses180')
|
|---|
| 384 | except:
|
|---|
| 385 | Logger.LogExceptionAsError(_(u'The directory %(dir)s does not appear to be a properly-initialized coral reef connectivity simulation directory: failed to parse a boolean option named Crosses180 from the file Simulation.ini in that directory. Please create a simulation directory using the Create Coral Reef Connectivity Simulation tool and try again.') % {u'dir': simulationDirectory})
|
|---|
| 386 | raise
|
|---|
| 387 |
|
|---|
| 388 | try:
|
|---|
| 389 | currentsLoaded = scp.getboolean(u'Simulation', u'CurrentsLoaded')
|
|---|
| 390 | except:
|
|---|
| 391 | Logger.LogExceptionAsError(_(u'The directory %(dir)s does not appear to be a properly-initialized coral reef connectivity simulation directory: failed to parse a boolean option named CurrentsLoaded from the file Simulation.ini in that directory. Please create a simulation directory using the Create Coral Reef Connectivity Simulation tool and try again.') % {u'dir': simulationDirectory})
|
|---|
| 392 | raise
|
|---|
| 393 |
|
|---|
| 394 | try:
|
|---|
| 395 | currentsProduct = unicode(scp.get(u'Simulation', u'CurrentsProduct'))
|
|---|
| 396 | except:
|
|---|
| 397 | Logger.LogExceptionAsError(_(u'The directory %(dir)s does not appear to be a properly-initialized coral reef connectivity simulation directory: failed to parse a string option named CurrentsProduct from the file Simulation.ini in that directory. Please create a simulation directory using the Create Coral Reef Connectivity Simulation tool and try again.') % {u'dir': simulationDirectory})
|
|---|
| 398 | raise
|
|---|
| 399 |
|
|---|
| 400 | return scp, crosses180, currentsLoaded, currentsProduct
|
|---|
| 401 |
|
|---|
| 402 | @classmethod
|
|---|
| 403 | def RunSimulation(cls, simulationDirectory, outputDirectory, startDate, duration=30.0, simulationTimeStep=2.4, summarizationPeriod=10, initialLarvaeDensity=10000.0, densityRasterCutoff=0.1, diffusivity=25.0, includeReefIDs=None, excludeReefIDs=None, overwriteExisting=False):
|
|---|
| 404 | cls.__doc__.Obj.ValidateMethodInvocation()
|
|---|
| 405 |
|
|---|
| 406 | # Parse and validate the Simulation.ini file.
|
|---|
| 407 |
|
|---|
| 408 | if not os.path.isfile(os.path.join(simulationDirectory, u'Simulation.ini')):
|
|---|
| 409 | Logger.RaiseException(ValueError(_(u'The directory %(dir)s does not appear to be a properly-initialized coral reef connectivity simulation directory: it does not contain a file called Simulation.ini. Please create a simulation directory using the Create Coral Reef Connectivity Simulation tool and try again.') % {u'dir': simulationDirectory}))
|
|---|
| 410 |
|
|---|
| 411 | from ConfigParser import SafeConfigParser
|
|---|
| 412 |
|
|---|
| 413 | scp = SafeConfigParser()
|
|---|
| 414 | f = file(os.path.join(simulationDirectory, u'Simulation.ini'), 'r')
|
|---|
| 415 | try:
|
|---|
| 416 | try:
|
|---|
| 417 | scp.readfp(f, os.path.join(simulationDirectory, u'Simulation.ini'))
|
|---|
| 418 | except:
|
|---|
| 419 | Logger.LogExceptionAsError(_(u'The directory %(dir)s does not appear to be a properly-initialized coral reef connectivity simulation directory: the file Simulation.ini in that directory could not be parsed. Please create a simulation directory using the Create Coral Reef Connectivity Simulation tool and try again.') % {u'dir': simulationDirectory})
|
|---|
| 420 | raise
|
|---|
| 421 | finally:
|
|---|
| 422 | try:
|
|---|
| 423 | f.close()
|
|---|
| 424 | except:
|
|---|
| 425 | pass
|
|---|
| 426 |
|
|---|
| 427 | try:
|
|---|
| 428 | crosses180 = scp.getboolean(u'Simulation', u'Crosses180')
|
|---|
| 429 | except:
|
|---|
| 430 | Logger.LogExceptionAsError(_(u'The directory %(dir)s does not appear to be a properly-initialized coral reef connectivity simulation directory: failed to parse a boolean option named Crosses180 from the file Simulation.ini in that directory. Please create a simulation directory using the Create Coral Reef Connectivity Simulation tool and try again.') % {u'dir': simulationDirectory})
|
|---|
| 431 | raise
|
|---|
| 432 |
|
|---|
| 433 | try:
|
|---|
| 434 | currentsLoaded = scp.getboolean(u'Simulation', u'CurrentsLoaded')
|
|---|
| 435 | except:
|
|---|
| 436 | Logger.LogExceptionAsError(_(u'The directory %(dir)s does not appear to be a properly-initialized coral reef connectivity simulation directory: failed to parse a boolean option named CurrentsLoaded from the file Simulation.ini in that directory. Please create a simulation directory using the Create Coral Reef Connectivity Simulation tool and try again.') % {u'dir': simulationDirectory})
|
|---|
| 437 | raise
|
|---|
| 438 | if not currentsLoaded:
|
|---|
| 439 | Logger.RaiseException(ValueError(_(u'The coral reef connectivity simulation in directory %(dir)s does not contain any ocean currents data. Please load ocean currents into it using a tool designed for this purpose, and try again.') % {u'dir': simulationDirectory}))
|
|---|
| 440 |
|
|---|
| 441 | try:
|
|---|
| 442 | currentsProduct = unicode(scp.get(u'Simulation', u'CurrentsProduct'))
|
|---|
| 443 | except:
|
|---|
| 444 | Logger.LogExceptionAsError(_(u'The directory %(dir)s does not appear to be a properly-initialized coral reef connectivity simulation directory: failed to parse a string option named CurrentsProduct from the file Simulation.ini in that directory. Please create a simulation directory using the Create Coral Reef Connectivity Simulation tool, load ocean currents into it using a tool designed for this purpose, and try again.') % {u'dir': simulationDirectory})
|
|---|
| 445 | raise
|
|---|
| 446 |
|
|---|
| 447 | try:
|
|---|
| 448 | currentsDateType = unicode(scp.get(u'Simulation', u'CurrentsDateType'))
|
|---|
| 449 | except:
|
|---|
| 450 | Logger.LogExceptionAsError(_(u'The directory %(dir)s does not appear to be a properly-initialized coral reef connectivity simulation directory: failed to parse a string option named CurrentsProduct from the file Simulation.ini in that directory. Please create a simulation directory using the Create Coral Reef Connectivity Simulation tool, load ocean currents into it using a tool designed for this purpose, and try again.') % {u'dir': simulationDirectory})
|
|---|
| 451 | raise
|
|---|
| 452 | if currentsDateType.lower() not in [u'center']:
|
|---|
| 453 | Logger.RaiseException(ValueError(_(u'The directory %(dir)s does not appear to be a properly-initialized coral reef connectivity simulation directory: the CurrentsDataType option in the Simulation.ini file has the unknown value %(val)s. Please create a simulation directory using the Create Coral Reef Connectivity Simulation tool, load ocean currents into it using a tool designed for this purpose, and try again.') % {u'dir': simulationDirectory, u'val': currentsDateType}))
|
|---|
| 454 |
|
|---|
| 455 | try:
|
|---|
| 456 | maxSecondsBetweenCurrentsImages = scp.getint(u'Simulation', u'MaxSecondsBetweenCurrentsImages')
|
|---|
| 457 | except:
|
|---|
| 458 | Logger.LogExceptionAsError(_(u'The directory %(dir)s does not appear to be a properly-initialized coral reef connectivity simulation directory: failed to parse an integer option named MaxSecondsBetweenCurrentsImages from the file Simulation.ini in that directory. Please create a simulation directory using the Create Coral Reef Connectivity Simulation tool, load ocean currents into it using a tool designed for this purpose, and try again.') % {u'dir': simulationDirectory})
|
|---|
| 459 | raise
|
|---|
| 460 | if maxSecondsBetweenCurrentsImages <= 0:
|
|---|
| 461 | Logger.RaiseException(ValueError(_(u'The directory %(dir)s does not appear to be a properly-initialized coral reef connectivity simulation directory: the MaxSecondsBetweenCurrentsImages option in the Simulation.ini file is less than or equal to zero. It must be greater than zero. Please create a simulation directory using the Create Coral Reef Connectivity Simulation tool, load ocean currents into it using a tool designed for this purpose, and try again.') % {u'dir': simulationDirectory}))
|
|---|
| 462 |
|
|---|
| 463 | # Validate other input parameters.
|
|---|
| 464 |
|
|---|
| 465 | if duration <= 0:
|
|---|
| 466 | Logger.RaiseException(ValueError(_(u'The simulation duration must be greater than zero.')))
|
|---|
| 467 |
|
|---|
| 468 | if duration - simulationTimeStep/24 <= 0:
|
|---|
| 469 | Logger.RaiseException(ValueError(_(u'The time step must be shorter than or equal to the simulation duration. For accurate results, the time step should be significantly shorter than the simulation duration. For example, if the simulation duration is 60 days, a time step of 1 hour would be appropriate.')))
|
|---|
| 470 |
|
|---|
| 471 | if includeReefIDs is not None and excludeReefIDs is not None:
|
|---|
| 472 | Logger.RaiseException(ValueError(_(u'You cannot specify both a list of reefs to include and a list of reefs to exclude. You must specify one, or the other, or neither.')))
|
|---|
| 473 |
|
|---|
| 474 | # Build lists of the currents rasters that are loaded into the
|
|---|
| 475 | # simulation, and validate that we have currents for the start
|
|---|
| 476 | # date and duration specified by the caller.
|
|---|
| 477 |
|
|---|
| 478 | import datetime
|
|---|
| 479 | import glob
|
|---|
| 480 |
|
|---|
| 481 | uRasters = glob.glob(os.path.join(simulationDirectory, u'Currents', u'u', u'*', u'u[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'))
|
|---|
| 482 | uRasters.sort()
|
|---|
| 483 | vRasters = glob.glob(os.path.join(simulationDirectory, u'Currents', u'v', u'*', u'v[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'))
|
|---|
| 484 | vRasters.sort()
|
|---|
| 485 |
|
|---|
| 486 | if len(uRasters) <= 0:
|
|---|
| 487 | Logger.RaiseException(ValueError(_(u'The coral reef connectivity simulation in directory %(dir)s does not contain any ocean currents data. Please load ocean currents into it using a tool designed for this purpose, and try again.') % {u'dir': simulationDirectory}))
|
|---|
| 488 | if len(uRasters) != len(vRasters):
|
|---|
| 489 | Logger.RaiseException(ValueError(_(u'The ocean currents data in the coral reef connectivity simulation in directory %(dir)s appears to be incompletely loaded. The number of "u" rasters does not equal the number of "v" rasters, indicating that the load operation did not complete successfully. Please try loading ocean currents again, and then try to run the simulation.') % {u'dir': simulationDirectory}))
|
|---|
| 490 |
|
|---|
| 491 | rasterDates = []
|
|---|
| 492 |
|
|---|
| 493 | for i in range(len(uRasters)):
|
|---|
| 494 | uRasterName = os.path.basename(uRasters[i])
|
|---|
| 495 | if uRasterName[1:] != os.path.basename(vRasters[i])[1:]:
|
|---|
| 496 | Logger.RaiseException(ValueError(_(u'The ocean currents data in the coral reef connectivity simulation in directory %(dir)s appears to be incompletely loaded. The "u" raster %(r1)s could not be matched up with a "v" raster with the same date (the next available "v" raster is %(r2)s). Please try loading ocean currents again, and then try to run the simulation.') % {u'dir': simulationDirectory, u'r1': uRasters[i], u'r2': vRasters[i]}))
|
|---|
| 497 | rasterDates.append(datetime.datetime(int(uRasterName[1:5]), 1, 1) + datetime.timedelta(days=int(uRasterName[5:8]) - 1, hours=int(uRasterName[8:10]), minutes=int(uRasterName[10:12])))
|
|---|
| 498 |
|
|---|
| 499 | if currentsDateType.lower() == u'center':
|
|---|
| 500 | currentsDateStartDelta = datetime.timedelta(seconds=maxSecondsBetweenCurrentsImages / 2)
|
|---|
| 501 | currentsDateEndDelta = datetime.timedelta(seconds=maxSecondsBetweenCurrentsImages / 2)
|
|---|
| 502 | else:
|
|---|
| 503 | Logger.RaiseException(NotImplementedError(_(u'This tool does not currently support a CurrentsDateType of "%(type)s". Please contact the author of this tool for assistance.') % {u'type': currentsDateType}))
|
|---|
| 504 |
|
|---|
| 505 | if startDate < rasterDates[0] - currentsDateStartDelta:
|
|---|
| 506 | Logger.RaiseException(ValueError(_(u'The start date of the simulation (%(start)s) occurs too far before the date of the first ocean currents image (%(date)s) that is loaded in the coral reef connectivity simulation in directory %(dir)s. To fix this problem, either move the start date forward or load some older ocean currents data into the simulation, so that the start date matches up with the currents data.') % {u'dir': simulationDirectory, u'start': str(startDate), u'date': str(rasterDates[0])}))
|
|---|
| 507 |
|
|---|
| 508 | if startDate > rasterDates[-1] + currentsDateEndDelta:
|
|---|
| 509 | Logger.RaiseException(ValueError(_(u'The start date of the simulation (%(start)s) occurs too far after the date of the last ocean currents image (%(date)s) that is loaded in the coral reef connectivity simulation in directory %(dir)s. To fix this problem, either move the start date backward or load some more recent ocean currents data into the simulation, so that the start date matches up with the currents data.') % {u'dir': simulationDirectory, u'start': str(startDate), u'date': str(rasterDates[-1])}))
|
|---|
| 510 |
|
|---|
| 511 | endDate = startDate + datetime.timedelta(days=duration)
|
|---|
| 512 |
|
|---|
| 513 | if endDate > rasterDates[-1] + currentsDateEndDelta:
|
|---|
| 514 | Logger.RaiseException(ValueError(_(u'The end date of the simulation (%(end)s) occurs too far after the date of the last ocean currents image (%(date)s) that is loaded in the coral reef connectivity simulation in directory %(dir)s. To fix this problem, either move the start date backward, reduce the duration of the simulation, or load some more recent ocean currents data into the simulation, so that the end date matches up with the currents data.') % {u'dir': simulationDirectory, u'end': str(endDate), u'date': str(rasterDates[-1])}))
|
|---|
| 515 |
|
|---|
| 516 | startRasterIndex = 0
|
|---|
| 517 | while startDate > rasterDates[startRasterIndex] + currentsDateEndDelta:
|
|---|
| 518 | startRasterIndex += 1
|
|---|
| 519 |
|
|---|
| 520 | endRasterIndex = startRasterIndex
|
|---|
| 521 | while endDate > rasterDates[endRasterIndex] + currentsDateEndDelta:
|
|---|
| 522 | endRasterIndex += 1
|
|---|
| 523 | if rasterDates[endRasterIndex] - rasterDates[endRasterIndex-1] > datetime.timedelta(seconds=maxSecondsBetweenCurrentsImages):
|
|---|
| 524 | Logger.RaiseException(ValueError(_(u'The ocean currents data that is loaded in the coral reef connectivity simulation in directory %(dir)s has a data gap in the range of dates between the simulation start date (%(start)s) and end date (%(end)s). A gap of %(gap)s occurs between %(d1)s and %(d2)s, which is larger than the maximum time permitted between images (%(max)s) for %(prod)s data. To fix this problem, either adjust the start date or duration, or load ocean currents data into the simulation that fills the gap.') % {u'dir': simulationDirectory, u'start': str(startDate), u'end': str(endDate), u'gap': str(rasterDates[endRasterIndex] - rasterDates[endRasterIndex-1]), u'd1': rasterDates[endRasterIndex-1], u'd2': rasterDates[endRasterIndex], u'max': datetime.timedelta(seconds=maxSecondsBetweenCurrentsImages), u'prod': currentsProduct}))
|
|---|
| 525 |
|
|---|
| 526 | # Read the reef rasters and geometry table into 2D numpy
|
|---|
| 527 | # arrays.
|
|---|
| 528 |
|
|---|
| 529 | Logger.Info(_(u'Reading coral reef data...'))
|
|---|
| 530 |
|
|---|
| 531 | from GeoEco.DataManagement.ArcGISRasters import ArcGISRaster
|
|---|
| 532 |
|
|---|
| 533 | reefIDsImage, reefIDsNoDataValue = ArcGISRaster.ToNumpyArray(os.path.join(simulationDirectory, u'ReefData', u'reef_ids'))
|
|---|
| 534 | reefIDsNoDataValue = int(reefIDsNoDataValue)
|
|---|
| 535 | reefCoverImage = ArcGISRaster.ToNumpyArray(os.path.join(simulationDirectory, u'ReefData', u'reef_areas'))[0]
|
|---|
| 536 | waterMaskImage = ArcGISRaster.ToNumpyArray(os.path.join(simulationDirectory, u'ReefData', u'water_mask'))[0]
|
|---|
| 537 |
|
|---|
| 538 | from GeoEco.DatabaseAccess.ArcGIS import ArcGIS91DatabaseConnection
|
|---|
| 539 | from GeoEco.DatabaseAccess.InMemory import InMemoryDatabaseConnection
|
|---|
| 540 |
|
|---|
| 541 | arcGISConn = ArcGIS91DatabaseConnection()
|
|---|
| 542 | inMemoryConn = InMemoryDatabaseConnection()
|
|---|
| 543 |
|
|---|
| 544 | if includeReefIDs is not None:
|
|---|
| 545 | inMemoryConn.ImportTable(arcGISConn, os.path.join(simulationDirectory, u'ReefData', u'reef_geometry.dbf'), u'reef_geometry', [u'VALUE', u'XCENTROID', u'YCENTROID'], where=u'"VALUE" IN (%s)' % u', '.join(map(unicode, includeReefIDs)), orderBy=[u'VALUE'], directions=[u'Ascending'])
|
|---|
| 546 | if inMemoryConn.GetRowCount(u'reef_geometry') <= 0:
|
|---|
| 547 | Logger.RaiseException(ValueError(_(u'The list of reefs IDs to include in the simulation does contain any IDs that also exist in the simulation directory %(dir)s. Please specify at least one existing reef ID.') % {u'dir': simulationDirectory}))
|
|---|
| 548 |
|
|---|
| 549 | elif excludeReefIDs is not None:
|
|---|
| 550 | inMemoryConn.ImportTable(arcGISConn, os.path.join(simulationDirectory, u'ReefData', u'reef_geometry.dbf'), u'reef_geometry', [u'VALUE', u'XCENTROID', u'YCENTROID'], where=u'"VALUE" NOT IN (%s)' % u', '.join(map(unicode, excludeReefIDs)), orderBy=[u'VALUE'], directions=[u'Ascending'])
|
|---|
| 551 | if inMemoryConn.GetRowCount(u'reef_geometry') <= 0:
|
|---|
| 552 | Logger.RaiseException(ValueError(_(u'The list of reefs IDs to exclude from the simulation excluded all of the reefs in the simulation directory %(dir)s. Please remove some IDs from this list so that at least one reef will be included in the simulation.') % {u'dir': simulationDirectory}))
|
|---|
| 553 |
|
|---|
| 554 | else:
|
|---|
| 555 | inMemoryConn.ImportTable(arcGISConn, os.path.join(simulationDirectory, u'ReefData', u'reef_geometry.dbf'), u'reef_geometry', [u'VALUE', u'XCENTROID', u'YCENTROID'], orderBy=[u'VALUE'], directions=[u'Ascending'])
|
|---|
| 556 | if inMemoryConn.GetRowCount(u'reef_geometry') <= 0:
|
|---|
| 557 | Logger.RaiseException(ValueError(_(u'The reef data in simulation directory %(dir)s does not contain any reefs. Please recreate the simulation using input rasters that contain at least one reef.') % {u'dir': simulationDirectory}))
|
|---|
| 558 |
|
|---|
| 559 | # Read the ocean currents into parallel lists of 2D numpy
|
|---|
| 560 | # arrays.
|
|---|
| 561 |
|
|---|
| 562 | import numpy
|
|---|
| 563 |
|
|---|
| 564 | imagesToRead = (endRasterIndex - startRasterIndex + 1) * 2
|
|---|
| 565 | Logger.Info(_(u'Reading %i ocean currents images...') % imagesToRead)
|
|---|
| 566 | progressReporter = ProgressReporter(progressMessage1=_(u'Still reading: %(elapsed)s elapsed, %(opsCompleted)i images read, %(perOp)s per image, %(opsRemaining)i remaining, estimated completion time: %(etc)s.'),
|
|---|
| 567 | completionMessage=_(u'Finished reading: %(elapsed)s elapsed, %(opsCompleted)i images read, %(perOp)s per image.'))
|
|---|
| 568 | progressReporter.Start(imagesToRead)
|
|---|
| 569 |
|
|---|
| 570 | uImageList = []
|
|---|
| 571 | vImageList = []
|
|---|
| 572 | uvDateList = []
|
|---|
| 573 |
|
|---|
| 574 | i = startRasterIndex
|
|---|
| 575 | while i >= startRasterIndex and i <= endRasterIndex:
|
|---|
| 576 | imageDate = rasterDates[i]
|
|---|
| 577 | uvDateList.append(imageDate)
|
|---|
| 578 |
|
|---|
| 579 | image, noDataValue = ArcGISRaster.ToNumpyArray(os.path.join(simulationDirectory, u'Currents', u'u', unicode(imageDate.year), imageDate.strftime('u%Y%j%H%M')))
|
|---|
| 580 | image[image == noDataValue] = numpy.nan
|
|---|
| 581 | uImageList.append(image)
|
|---|
| 582 | progressReporter.ReportProgress()
|
|---|
| 583 |
|
|---|
| 584 | image, noDataValue = ArcGISRaster.ToNumpyArray(os.path.join(simulationDirectory, u'Currents', u'v', unicode(imageDate.year), imageDate.strftime('v%Y%j%H%M')))
|
|---|
| 585 | image[image == noDataValue] = numpy.nan
|
|---|
| 586 | vImageList.append(image)
|
|---|
| 587 | progressReporter.ReportProgress()
|
|---|
| 588 |
|
|---|
| 589 | i += 1
|
|---|
| 590 |
|
|---|
| 591 | # Stack the numpy arrays into two 3D arrays that we will pass
|
|---|
| 592 | # to the MATLAB function.
|
|---|
| 593 | #
|
|---|
| 594 | # Note that with numpy, it appears that 2D arrays are
|
|---|
| 595 | # traditionally indexed [y,x] but that 3D arrays are [y,x,t].
|
|---|
| 596 | # This is what is output by numpy's dstack function. This is
|
|---|
| 597 | # kind of screwy, because when you print a 3D numpy array, it
|
|---|
| 598 | # looks much better if ordered [t,y,x] than [y,x,t]. But
|
|---|
| 599 | # MATLAB was the inspiration for numpy and [y,x,t] is
|
|---|
| 600 | # traditional in MATLAB as well. Finally, Eric Treml's
|
|---|
| 601 | # original MATLAB code used [y,x,z].
|
|---|
| 602 |
|
|---|
| 603 | uImages = numpy.dstack(tuple(uImageList))
|
|---|
| 604 | del uImageList
|
|---|
| 605 |
|
|---|
| 606 | vImages = numpy.dstack(tuple(vImageList))
|
|---|
| 607 | del vImageList
|
|---|
| 608 |
|
|---|
| 609 | # Build a list that specifies the t index into the 3D arrays
|
|---|
| 610 | # for each time step. Note that when we pass this list to
|
|---|
| 611 | # MATLAB, we must increment all of the indices by 1, because
|
|---|
| 612 | # MATLAB uses 1-based indexing (Python uses 0-based).
|
|---|
| 613 |
|
|---|
| 614 | import math
|
|---|
| 615 |
|
|---|
| 616 | numTimeSteps = int(math.ceil(duration / (simulationTimeStep/24)))
|
|---|
| 617 | uvIndexForTimestep = [0]
|
|---|
| 618 | for i in range(1, numTimeSteps):
|
|---|
| 619 | if startDate + datetime.timedelta(hours=simulationTimeStep*i) <= uvDateList[uvIndexForTimestep[-1]] + currentsDateEndDelta:
|
|---|
| 620 | uvIndexForTimestep.append(uvIndexForTimestep[-1])
|
|---|
| 621 | else:
|
|---|
| 622 | uvIndexForTimestep.append(uvIndexForTimestep[-1] + 1)
|
|---|
| 623 |
|
|---|
| 624 | # Look up the cell size of the rasters.
|
|---|
| 625 |
|
|---|
| 626 | from GeoEco.ArcGIS import GeoprocessorManager
|
|---|
| 627 | gp = GeoprocessorManager.GetWrappedGeoprocessor()
|
|---|
| 628 | describeReefIDsRaster = gp.Describe(os.path.join(simulationDirectory, u'ReefData', u'reef_ids'))
|
|---|
| 629 | cellSize = describeReefIDsRaster.MeanCellWidth
|
|---|
| 630 |
|
|---|
| 631 | # Calculate and report the maximum Courant number. Issue a
|
|---|
| 632 | # warning if it is greater than or equal to 1.0 because the
|
|---|
| 633 | # simulation is likely to be unstable. Provide an estimate of
|
|---|
| 634 | # the largest time step that would allow the Courant number to
|
|---|
| 635 | # be less than 1.0.
|
|---|
| 636 |
|
|---|
| 637 | hasData = numpy.logical_and(numpy.logical_not(numpy.isnan(uImages)), numpy.logical_not(numpy.isnan(vImages)))
|
|---|
| 638 | maxVelocity = max(numpy.max(uImages[hasData]), numpy.max(vImages[hasData]))
|
|---|
| 639 | maxCourant = maxVelocity * (simulationTimeStep*3600) / cellSize
|
|---|
| 640 |
|
|---|
| 641 | if maxCourant <= 0.25:
|
|---|
| 642 | Logger.Info(_(u'The maximum Courant number is %(mc)f, which is less than or equal to 0.25. The simulation is likely to be numerically stable.') % {u'mc': maxCourant})
|
|---|
| 643 | else:
|
|---|
| 644 | maxTimeStep = cellSize / maxVelocity / 3600 * 0.25
|
|---|
| 645 | if maxCourant <= 0.5:
|
|---|
| 646 | Logger.Warning(_(u'The maximum Courant number is %(mc)f, which is greater than 0.25 and less than or equal to 0.5. The simulation may exhibit some instability. Please review the results carefully. To improve the chance that the simulation will be stable, we recommend you reduce the time step to %(mts)g or less, so that the maximum Courant number is less than or equal to 0.25.') % {u'mc': maxCourant, u'mts': maxTimeStep})
|
|---|
| 647 | else:
|
|---|
| 648 | Logger.Warning(_(u'The maximum Courant number is %(mc)f, which is greater than 0.5. The simulation is likely to be unstable. Please review the results carefully. To improve the chance that the simulation will be stable, we recommend you reduce the time step to %(mts)g or less, so that the maximum Courant number is less than or equal to 0.25.') % {u'mc': maxCourant, u'mts': maxTimeStep})
|
|---|
| 649 |
|
|---|
| 650 | # Create a temporary directory and write the arrays to it in
|
|---|
| 651 | # binary format.
|
|---|
| 652 |
|
|---|
| 653 | reefIDs = inMemoryConn.GetFieldValues(u'reef_geometry', u'VALUE')
|
|---|
| 654 |
|
|---|
| 655 | from GeoEco.DataManagement.Directories import TemporaryDirectory
|
|---|
| 656 | tempDir = TemporaryDirectory()
|
|---|
| 657 |
|
|---|
| 658 | try:
|
|---|
| 659 | reefIDsArray = numpy.array(reefIDs)
|
|---|
| 660 | reefIDsDataType = reefIDsArray.dtype.name
|
|---|
| 661 | reefIDsFile = os.path.join(tempDir.Path, 'ReefIDs.bin')
|
|---|
| 662 | reefIDsArray.tofile(reefIDsFile)
|
|---|
| 663 |
|
|---|
| 664 | reefIDsImageDataType = reefIDsImage.dtype.name
|
|---|
| 665 | reefIDsImageFile = os.path.join(tempDir.Path, 'ReefIDsImage.bin')
|
|---|
| 666 | reefIDsImage.tofile(reefIDsImageFile)
|
|---|
| 667 |
|
|---|
| 668 | reefCoverImageDataType = reefCoverImage.dtype.name
|
|---|
| 669 | reefCoverImageFile = os.path.join(tempDir.Path, 'ReefCoverImage.bin')
|
|---|
| 670 | reefCoverImage.tofile(reefCoverImageFile)
|
|---|
| 671 |
|
|---|
| 672 | waterMaskImageDataType = waterMaskImage.dtype.name
|
|---|
| 673 | waterMaskImageFile = os.path.join(tempDir.Path, 'waterMaskImage.bin')
|
|---|
| 674 | waterMaskImage.tofile(waterMaskImageFile)
|
|---|
| 675 |
|
|---|
| 676 | uImagesDataType = uImages.dtype.name
|
|---|
| 677 | uImagesFile = os.path.join(tempDir.Path, 'uImages.bin')
|
|---|
| 678 | uImages.tofile(uImagesFile)
|
|---|
| 679 |
|
|---|
| 680 | vImagesDataType = vImages.dtype.name
|
|---|
| 681 | vImagesFile = os.path.join(tempDir.Path, 'vImages.bin')
|
|---|
| 682 | vImages.tofile(vImagesFile)
|
|---|
| 683 |
|
|---|
| 684 | uvIndexForTimestepArray = numpy.array(uvIndexForTimestep) + 1
|
|---|
| 685 | uvIndexForTimestepDataType = uvIndexForTimestepArray.dtype.name
|
|---|
| 686 | uvIndexForTimestepFile = os.path.join(tempDir.Path, 'UVIndexForTimestep.bin')
|
|---|
| 687 | uvIndexForTimestepArray.tofile(uvIndexForTimestepFile)
|
|---|
| 688 |
|
|---|
| 689 | # Execute RunLarvalDispersal.py to run the simulation.
|
|---|
| 690 | # This script calls MATLAB functions. We prefer to call
|
|---|
| 691 | # those functions directly right here but there is a
|
|---|
| 692 | # continuing incompatibility between MATLAB DLLs and
|
|---|
| 693 | # ArcGIS DLLs (they both try to load their own
|
|---|
| 694 | # incompatible versions of xerces-c_2_7.dll) so we have to
|
|---|
| 695 | # do it in a separate process.
|
|---|
| 696 |
|
|---|
| 697 | dispersalMatrixFile = os.path.join(tempDir.Path, u'DispersalMatrix.bin')
|
|---|
| 698 | densityImagesFile = os.path.join(tempDir.Path, u'DensityImages.bin')
|
|---|
| 699 |
|
|---|
| 700 | from GeoEco.DataManagement.Processes import ChildProcess
|
|---|
| 701 | import win32api
|
|---|
| 702 |
|
|---|
| 703 | ChildProcess.ExecuteProgram(win32api.FindExecutable(os.path.join(os.path.dirname(__file__), 'RunLarvalDispersal.py'), os.path.dirname(__file__))[1],
|
|---|
| 704 | arguments=[os.path.join(os.path.dirname(__file__), 'RunLarvalDispersal.py'),
|
|---|
| 705 | repr(uImages.shape[2]), # t
|
|---|
| 706 | repr(uImages.shape[0]), # y
|
|---|
| 707 | repr(uImages.shape[1]), # x
|
|---|
| 708 | reefIDsFile,
|
|---|
| 709 | reefIDsDataType,
|
|---|
| 710 | reefIDsImageFile,
|
|---|
| 711 | reefIDsImageDataType,
|
|---|
| 712 | reefCoverImageFile,
|
|---|
| 713 | reefCoverImageDataType,
|
|---|
| 714 | waterMaskImageFile,
|
|---|
| 715 | waterMaskImageDataType,
|
|---|
| 716 | uImagesFile,
|
|---|
| 717 | uImagesDataType,
|
|---|
| 718 | vImagesFile,
|
|---|
| 719 | vImagesDataType,
|
|---|
| 720 | repr(cellSize),
|
|---|
| 721 | repr(simulationTimeStep * 3600.0),
|
|---|
| 722 | repr(initialLarvaeDensity / 1000000.0),
|
|---|
| 723 | repr(summarizationPeriod),
|
|---|
| 724 | repr(diffusivity),
|
|---|
| 725 | uvIndexForTimestepFile,
|
|---|
| 726 | uvIndexForTimestepDataType,
|
|---|
| 727 | dispersalMatrixFile,
|
|---|
| 728 | densityImagesFile],
|
|---|
| 729 | stdoutLogLevel=u'Info',
|
|---|
| 730 | windowState=u'invisible',
|
|---|
| 731 | maxRunTime=None)
|
|---|
| 732 |
|
|---|
| 733 | del uImages, vImages
|
|---|
| 734 |
|
|---|
| 735 | # Read the output files.
|
|---|
| 736 |
|
|---|
| 737 | dispersalMatrix = numpy.fromfile(dispersalMatrixFile, 'float32')
|
|---|
| 738 | dispersalMatrix = dispersalMatrix.reshape(len(reefIDs), len(reefIDs), len(dispersalMatrix) / len(reefIDs) / len(reefIDs))
|
|---|
| 739 |
|
|---|
| 740 | densityImages = numpy.fromfile(densityImagesFile, 'float32')
|
|---|
| 741 | densityImages = densityImages.reshape(reefIDsImage.shape[0], reefIDsImage.shape[1], len(densityImages) / reefIDsImage.shape[0] / reefIDsImage.shape[1])
|
|---|
| 742 |
|
|---|
| 743 | finally:
|
|---|
| 744 | del tempDir
|
|---|
| 745 |
|
|---|
| 746 | # The DisperseLarvae function returns densities in particles
|
|---|
| 747 | # per square meter. Convert to particles per square km.
|
|---|
| 748 |
|
|---|
| 749 | densityImages *= 1000000.0
|
|---|
| 750 |
|
|---|
| 751 | # Mask cells that are land and that have a density that is
|
|---|
| 752 | # below the threshold.
|
|---|
| 753 |
|
|---|
| 754 | densityImages[waterMaskImage == 0, :] = 0
|
|---|
| 755 | if densityRasterCutoff is not None:
|
|---|
| 756 | densityImages[densityImages < initialLarvaeDensity * densityRasterCutoff / 100.0] = 0
|
|---|
| 757 |
|
|---|
| 758 | # Create the output personal geodatabase in the output
|
|---|
| 759 | # directory.
|
|---|
| 760 |
|
|---|
| 761 | outputGDB = os.path.join(outputDirectory, u'ConnectivityGeodatabase.mdb')
|
|---|
| 762 | if gp.Exists(outputGDB):
|
|---|
| 763 | if not overwriteExisting:
|
|---|
| 764 | Logger.RaiseException(ValueError(_(u'The output geodatabase %s already exists. Please delete it or specify that existing outputs should be overwritten and try again.') % outputGDB))
|
|---|
| 765 | gp.Delete_management(outputGDB)
|
|---|
| 766 |
|
|---|
| 767 | gp.CreatePersonalGDB_management(outputDirectory, u'ConnectivityGeodatabase.mdb')
|
|---|
| 768 |
|
|---|
| 769 | # Create the edge list feature class.
|
|---|
| 770 |
|
|---|
| 771 | gp.CreateFeatureClass_management(outputGDB, u'Edges', u'POLYLINE', None, u'DISABLED', u'DISABLED', gp.CreateSpatialReference(describeReefIDsRaster.SpatialReference).split(';')[0])
|
|---|
| 772 | gp.AddField_management(os.path.join(outputGDB, u'Edges'), u'FromReefID', u'LONG')
|
|---|
| 773 | gp.AddField_management(os.path.join(outputGDB, u'Edges'), u'ToReefID', u'LONG')
|
|---|
| 774 | gp.AddField_management(os.path.join(outputGDB, u'Edges'), u'MaxDispersal', u'FLOAT')
|
|---|
| 775 |
|
|---|
| 776 | # Populate the edge list feature class.
|
|---|
| 777 |
|
|---|
| 778 | maxDispersal = dispersalMatrix[:,:,1:].max(2)
|
|---|
| 779 | for fromReef in range(len(reefIDs)):
|
|---|
| 780 | for toReef in range(len(reefIDs)):
|
|---|
| 781 | if fromReef != toReef:
|
|---|
| 782 | maxDispersal[fromReef, toReef] /= dispersalMatrix[fromReef, fromReef, 0]
|
|---|
| 783 | else:
|
|---|
| 784 | maxDispersal[fromReef, toReef] = 0
|
|---|
| 785 |
|
|---|
| 786 | nonZeroEdges = sum(sum(maxDispersal > 0.0001))
|
|---|
| 787 | xCentroids = inMemoryConn.GetFieldValues(u'reef_geometry', u'XCENTROID')
|
|---|
| 788 | yCentroids = inMemoryConn.GetFieldValues(u'reef_geometry', u'YCENTROID')
|
|---|
| 789 | shapeFieldName = gp.Describe(os.path.join(outputGDB, u'Edges')).ShapeFieldName
|
|---|
| 790 |
|
|---|
| 791 | if nonZeroEdges > 0:
|
|---|
| 792 | Logger.Info(_(u'Writing %i edges to the edge list in the output geodatabase...') % nonZeroEdges)
|
|---|
| 793 | cur = arcGISConn.OpenInsertCursor(os.path.join(outputGDB, u'Edges'), rowCount=nonZeroEdges)
|
|---|
| 794 | for fromReef in range(len(reefIDs)):
|
|---|
| 795 | for toReef in range(len(reefIDs)):
|
|---|
| 796 | if maxDispersal[fromReef, toReef] > 0.0001:
|
|---|
| 797 | point = gp.CreateObject(u'Point')
|
|---|
| 798 | line = gp.CreateObject(u'Array')
|
|---|
| 799 | point.X = xCentroids[fromReef]
|
|---|
| 800 | point.Y = yCentroids[fromReef]
|
|---|
| 801 | line.Add(point)
|
|---|
| 802 | point.X = xCentroids[toReef]
|
|---|
| 803 | point.Y = yCentroids[toReef]
|
|---|
| 804 | line.Add(point)
|
|---|
| 805 | cur.SetValue(shapeFieldName, line)
|
|---|
| 806 | cur.SetValue(u'FromReefID', reefIDs[fromReef])
|
|---|
| 807 | cur.SetValue(u'ToReefID', reefIDs[toReef])
|
|---|
| 808 | cur.SetValue(u'MaxDispersal', float(maxDispersal[fromReef, toReef])) # Must convert from numpy float to Python float
|
|---|
| 809 | cur.InsertRow()
|
|---|
| 810 | else:
|
|---|
| 811 | Logger.Warning(_(u'The edge list in the output geodatabase will be empty because none of the reefs are connected.'))
|
|---|
| 812 |
|
|---|
| 813 | # Create the DensityRasters subdirectory, if it does not
|
|---|
| 814 | # already exist.
|
|---|
| 815 |
|
|---|
| 816 | from GeoEco.DataManagement.Directories import Directory
|
|---|
| 817 | from GeoEco.DataManagement.ArcGISRasters import ArcGISRaster
|
|---|
| 818 |
|
|---|
| 819 | if not Directory.Exists(os.path.join(outputDirectory, u'DensityRasters'))[0]:
|
|---|
| 820 | Directory.Create(os.path.join(outputDirectory, u'DensityRasters'))
|
|---|
| 821 |
|
|---|
| 822 | # If the directory already exists and the caller requested
|
|---|
| 823 | # that we overwrite existing outputs, delete any existing
|
|---|
| 824 | # density rasters.
|
|---|
| 825 |
|
|---|
| 826 | elif overwriteExisting:
|
|---|
| 827 | oldLogInfoAsDebug = Logger.GetLogInfoAsDebug()
|
|---|
| 828 | Logger.SetLogInfoAsDebug(True)
|
|---|
| 829 | try:
|
|---|
| 830 | ArcGISRaster.FindAndDelete(os.path.join(outputDirectory, u'DensityRasters'), u'*')
|
|---|
| 831 | finally:
|
|---|
| 832 | Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
|
|---|
| 833 |
|
|---|
| 834 | # Create the density rasters in the subdirectory.
|
|---|
| 835 |
|
|---|
| 836 | coordinateSystem = gp.CreateSpatialReference(describeReefIDsRaster.SpatialReference).split(';')[0]
|
|---|
| 837 |
|
|---|
| 838 | Logger.Info(_(u'Writing %i density rasters to the output directory...') % densityImages.shape[2])
|
|---|
| 839 | progressReporter = ProgressReporter(progressMessage1=_(u'Still writing density rasters: %(elapsed)s elapsed, %(opsCompleted)i rasters written, %(perOp)s per raster, %(opsRemaining)i remaining, estimated completion time: %(etc)s.'),
|
|---|
| 840 | completionMessage=_(u'Finished writing density rasters: %(elapsed)s elapsed, %(opsCompleted)i rasters written, %(perOp)s per raster.'))
|
|---|
| 841 | progressReporter.Start(densityImages.shape[2])
|
|---|
| 842 |
|
|---|
| 843 | for i in range(densityImages.shape[2]):
|
|---|
| 844 | oldLogInfoAsDebug = Logger.GetLogInfoAsDebug()
|
|---|
| 845 | Logger.SetLogInfoAsDebug(True)
|
|---|
| 846 | try:
|
|---|
| 847 | ArcGISRaster.FromNumpyArray(densityImages[:,:,i].copy(), # Copy is currently needed because the current implementation of ArcGISRaster.FromNumpyArray requires the array to be in C order.
|
|---|
| 848 | os.path.join(outputDirectory, u'DensityRasters', (startDate + datetime.timedelta(seconds=simulationTimeStep*3600.0*summarizationPeriod*i)).strftime('d%Y%j%H%M')),
|
|---|
| 849 | EnvelopeTypeMetadata.ParseFromArcGISString(describeReefIDsRaster.Extent)[0],
|
|---|
| 850 | EnvelopeTypeMetadata.ParseFromArcGISString(describeReefIDsRaster.Extent)[1],
|
|---|
| 851 | cellSize,
|
|---|
| 852 | nodataValue=0,
|
|---|
| 853 | coordinateSystem=coordinateSystem,
|
|---|
| 854 | buildPyramids=True,
|
|---|
| 855 | overwriteExisting=overwriteExisting)
|
|---|
| 856 | finally:
|
|---|
| 857 | Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
|
|---|
| 858 |
|
|---|
| 859 | progressReporter.ReportProgress()
|
|---|
| 860 |
|
|---|
| 861 | # Create a raster catalog in the output geodatabase for
|
|---|
| 862 | # the density rasters, so they can be easily animated. Add
|
|---|
| 863 | # and populate StartTime and EndTime fields, which define
|
|---|
| 864 | # the period for which the raster applies, as recommended
|
|---|
| 865 | # by the ArcGIS documentation.
|
|---|
| 866 |
|
|---|
| 867 | Logger.Info(_(u'Creating a raster catalog for the density rasters...'))
|
|---|
| 868 |
|
|---|
| 869 | gp.CreateRasterCatalog_management(outputGDB, u'DensityRasters', coordinateSystem, coordinateSystem, None, None, None, None, u'Unmanaged')
|
|---|
| 870 | gp.AddField_management(os.path.join(outputGDB, u'DensityRasters'), u'StartTime', u'DATE')
|
|---|
| 871 | gp.AddField_management(os.path.join(outputGDB, u'DensityRasters'), u'EndTime', u'DATE')
|
|---|
| 872 | gp.WorkspaceToRasterCatalog(os.path.join(outputDirectory, u'DensityRasters'), os.path.join(outputGDB, u'DensityRasters'))
|
|---|
| 873 |
|
|---|
| 874 | # Populate the StartTime and EndTime fields of the raster
|
|---|
| 875 | # catalog. Originally, I implemented this using the ArcGIS
|
|---|
| 876 | # Calculate Fields tool, but it kept crashing in 9.3,
|
|---|
| 877 | # regardless of whether I used Python or VB, and regardless of
|
|---|
| 878 | # whether I created the geoprocessor using
|
|---|
| 879 | # arcgisscripting.create or win32com.client.Dispatch. To work
|
|---|
| 880 | # around this ArcGIS bug, I'm using the MGET Calculate Fields
|
|---|
| 881 | # tool instead. It is slower (due to slow ArcGIS cursors) but
|
|---|
| 882 | # does not crash.
|
|---|
| 883 |
|
|---|
| 884 | from GeoEco.DataManagement.Fields import Field
|
|---|
| 885 | Field.CalculateFields(arcGISConn, os.path.join(outputGDB, u'DensityRasters'), [u'StartTime', u'EndTime'], [u"(datetime.datetime(int(row.Name[1:5]), 1, 1, int(row.Name[8:10]), int(row.Name[10:12])) + datetime.timedelta(days=int(row.Name[5:8])-1)).strftime('%Y-%m-%d %H:%M:%S')", u"(datetime.datetime(int(row.Name[1:5]), 1, 1, int(row.Name[8:10]), int(row.Name[10:12])) + datetime.timedelta(days=int(row.Name[5:8])-1) + datetime.timedelta(seconds=" + unicode(simulationTimeStep*3600.0*summarizationPeriod) + u")).strftime('%Y-%m-%d %H:%M:%S')"], modulesToImport=[u'datetime'])
|
|---|
| 886 |
|
|---|
| 887 | # Return successfully.
|
|---|
| 888 |
|
|---|
| 889 | return outputDirectory
|
|---|
| 890 |
|
|---|
| 891 | ###############################################################################
|
|---|
| 892 | # Metadata: module
|
|---|
| 893 | ###############################################################################
|
|---|
| 894 |
|
|---|
| 895 | from GeoEco.ArcGIS import ArcGISDependency, ArcGISExtensionDependency
|
|---|
| 896 | from GeoEco.Dependencies import PythonAggregatedModuleDependency
|
|---|
| 897 | from GeoEco.Matlab import MatlabDependency
|
|---|
| 898 | from GeoEco.Metadata import *
|
|---|
| 899 | from GeoEco.Types import *
|
|---|
| 900 |
|
|---|
| 901 | AddModuleMetadata(shortDescription=_(u'Implements Eric Treml\'s coral reef connectivity analysis.'))
|
|---|
| 902 |
|
|---|
| 903 | ###############################################################################
|
|---|
| 904 | # Metadata: CoralReefConnectivity class
|
|---|
| 905 | ###############################################################################
|
|---|
| 906 |
|
|---|
| 907 | AddClassMetadata(CoralReefConnectivity,
|
|---|
| 908 | shortDescription=_(u'Implements Eric Treml\'s coral reef connectivity analysis.'),
|
|---|
| 909 | isExposedAsCOMServer=True,
|
|---|
| 910 | comIID=u'{1B3A8B7F-8921-4A69-AF39-D209FAA0D588}',
|
|---|
| 911 | comCLSID=u'{BAD2EBA8-1077-4A5B-B737-D4906466B60A}')
|
|---|
| 912 |
|
|---|
| 913 | # Public method: CoralReefConnectivity.CreateSimulationFromArcGISRasters
|
|---|
| 914 |
|
|---|
| 915 | AddMethodMetadata(CoralReefConnectivity.CreateSimulationFromArcGISRasters,
|
|---|
| 916 | shortDescription=_(u'Creates a coral reef connectivity simulation and initializes it with reef data in ArcGIS rasters.'),
|
|---|
| 917 | isExposedToPythonCallers=True,
|
|---|
| 918 | isExposedByCOM=True,
|
|---|
| 919 | isExposedAsArcGISTool=True,
|
|---|
| 920 | arcGISDisplayName=_(u'Create Coral Reef Connectivity Simulation From ArcGIS Rasters'),
|
|---|
| 921 | arcGISToolCategory=_(u'Connectivity Analysis\\Coral Reef Larval Connectivity'),
|
|---|
| 922 | dependencies=[ArcGISDependency(9, 2), ArcGISExtensionDependency(u'spatial'), PythonAggregatedModuleDependency('numpy')])
|
|---|
| 923 |
|
|---|
| 924 | AddArgumentMetadata(CoralReefConnectivity.CreateSimulationFromArcGISRasters, u'cls',
|
|---|
| 925 | typeMetadata=ClassOrClassInstanceTypeMetadata(cls=CoralReefConnectivity),
|
|---|
| 926 | description=_(u'%s class or an instance of it.') % CoralReefConnectivity.__name__)
|
|---|
| 927 |
|
|---|
| 928 | AddArgumentMetadata(CoralReefConnectivity.CreateSimulationFromArcGISRasters, u'simulationDirectory',
|
|---|
| 929 | typeMetadata=DirectoryTypeMetadata(deleteIfParameterIsTrue=u'overwriteExisting', createParentDirectories=True),
|
|---|
| 930 | description=_(
|
|---|
| 931 | u"""Output directory to create to contain the simulation's data.
|
|---|
| 932 |
|
|---|
| 933 | After creating the simulation directory, you must load ocean currents
|
|---|
| 934 | data into it using other tools before you can run the simulation. Use
|
|---|
| 935 | the MGET tools designed for this purpose. Unless you know what you are
|
|---|
| 936 | doing, do not modify the contents of the simulation directory
|
|---|
| 937 | yourself."""),
|
|---|
| 938 | direction=u'Output',
|
|---|
| 939 | arcGISDisplayName=_(u'Simulation directory to create'))
|
|---|
| 940 |
|
|---|
| 941 | AddArgumentMetadata(CoralReefConnectivity.CreateSimulationFromArcGISRasters, u'reefIDsRaster',
|
|---|
| 942 | typeMetadata=ArcGISRasterLayerTypeMetadata(mustExist=True, allowedPixelTypes=[u'S8', u'U8', u'S16', u'U16', u'S32', u'U32', u'S64', u'U64']),
|
|---|
| 943 | description=_(
|
|---|
| 944 | u"""Integer raster specifying the locations and IDs of reefs.
|
|---|
| 945 |
|
|---|
| 946 | The raster value specifies the ID of the reef contained by that cell.
|
|---|
| 947 | NoData indicates that the cell does not contain a reef. The value 0
|
|---|
| 948 | may not be used as a reef ID.
|
|---|
| 949 |
|
|---|
| 950 | The raster also defines the coordinate system, extent, and cell size
|
|---|
| 951 | for the analysis. The raster must use a projected coordinate system,
|
|---|
| 952 | with meters as the linear unit. The reef cover and water mask rasters
|
|---|
| 953 | must have the same coordinate system, extent, and cell size. When
|
|---|
| 954 | ocean currents data are loaded into the simulation, they will be
|
|---|
| 955 | automatically projected and clipped as needed into this coordinate
|
|---|
| 956 | system, extent, and cell size."""),
|
|---|
| 957 | arcGISDisplayName=_(u'Reef IDs raster'))
|
|---|
| 958 |
|
|---|
| 959 | AddArgumentMetadata(CoralReefConnectivity.CreateSimulationFromArcGISRasters, u'reefCoverRaster',
|
|---|
| 960 | typeMetadata=ArcGISRasterLayerTypeMetadata(mustExist=True),
|
|---|
| 961 | description=_(
|
|---|
| 962 | u"""Floating-point raster specifying the proportion of each cell's
|
|---|
| 963 | area that is occupied by reef.
|
|---|
| 964 |
|
|---|
| 965 | This raster determines the density of coral larvae released into the
|
|---|
| 966 | cell at the start of the simulation. The density for a cell is
|
|---|
| 967 | determined by multiplying this raster's value by the larvae density
|
|---|
| 968 | parameter you specify when you run the simulation.
|
|---|
| 969 |
|
|---|
| 970 | This raster must have the same coordinate system, extent, and cell
|
|---|
| 971 | size as the reef IDs raster.
|
|---|
| 972 |
|
|---|
| 973 | The raster values must be greater than or equal to 0 and less than or
|
|---|
| 974 | equal to 1. The value 1 indicates that the entire cell is occupied by
|
|---|
| 975 | reef, while 0.5 indicates that only half of it is. If the cell size
|
|---|
| 976 | was 25 km by 25 km, this would mean the cell contained either 625 or
|
|---|
| 977 | 312.5 square km of reef, respectively.
|
|---|
| 978 |
|
|---|
| 979 | If the value is 0 or NoData, it is assumed that the cell does not
|
|---|
| 980 | contain any reef, even if the reef IDs raster indicates that a reef is
|
|---|
| 981 | there. If the value is greater than 0 but the corresponding reef IDs
|
|---|
| 982 | raster contains NoData, it is assumed that the cell does not contain
|
|---|
| 983 | any reef."""),
|
|---|
| 984 | arcGISDisplayName=_(u'Reef cover raster'))
|
|---|
| 985 |
|
|---|
| 986 | AddArgumentMetadata(CoralReefConnectivity.CreateSimulationFromArcGISRasters, u'waterMaskRaster',
|
|---|
| 987 | typeMetadata=ArcGISRasterLayerTypeMetadata(mustExist=True),
|
|---|
| 988 | description=_(
|
|---|
| 989 | u"""Raster specifying the locations of land and water. 0 or NoData
|
|---|
| 990 | indicates land; any other value indicates water.
|
|---|
| 991 |
|
|---|
| 992 | This raster must have the same coordinate system, dimensions, and cell
|
|---|
| 993 | size as the reef IDs raster."""),
|
|---|
| 994 | arcGISDisplayName=_(u'Water mask raster'))
|
|---|
| 995 |
|
|---|
| 996 | AddArgumentMetadata(CoralReefConnectivity.CreateSimulationFromArcGISRasters, u'crosses180',
|
|---|
| 997 | typeMetadata=BooleanTypeMetadata(),
|
|---|
| 998 | description=_(
|
|---|
| 999 | u"""Set this option to True if your study area crosses the 180th
|
|---|
| 1000 | meridian (i.e. 180 W / 180 E). This will happen if you are studying
|
|---|
| 1001 | reefs in the tropical Pacific, for example."""),
|
|---|
| 1002 | arcGISDisplayName=_(u'Study area crosses the 180th meridian'))
|
|---|
| 1003 |
|
|---|
| 1004 | AddArgumentMetadata(CoralReefConnectivity.CreateSimulationFromArcGISRasters, u'overwriteExisting',
|
|---|
| 1005 | typeMetadata=BooleanTypeMetadata(),
|
|---|
| 1006 | description=_(
|
|---|
| 1007 | u"""If True, the simulation directory will be deleted and recreated,
|
|---|
| 1008 | if it exists. If False, a ValueError will be raised if the simulation
|
|---|
| 1009 | directory exists."""),
|
|---|
| 1010 | initializeToArcGISGeoprocessorVariable=u'OverwriteOutput')
|
|---|
| 1011 |
|
|---|
| 1012 | # Public method: CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation
|
|---|
| 1013 |
|
|---|
| 1014 | AddMethodMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation,
|
|---|
| 1015 | shortDescription=_(u'Downloads Aviso geostrophic currents into a coral reef connectivity simulation.'),
|
|---|
| 1016 | longDescription=_AvisoGriddedProduct_LongDescription % {u'name': 'tool'},
|
|---|
| 1017 | isExposedToPythonCallers=True,
|
|---|
| 1018 | isExposedByCOM=True,
|
|---|
| 1019 | isExposedAsArcGISTool=True,
|
|---|
| 1020 | arcGISDisplayName=_(u'Load Aviso Geostrophic Currents Into Coral Reef Connectivity Simulation'),
|
|---|
| 1021 | arcGISToolCategory=_(u'Connectivity Analysis\\Coral Reef Larval Connectivity'),
|
|---|
| 1022 | dependencies=[ArcGISDependency(9, 2), ArcGISExtensionDependency(u'spatial'), PythonAggregatedModuleDependency('numpy')])
|
|---|
| 1023 |
|
|---|
| 1024 | CopyArgumentMetadata(CoralReefConnectivity.CreateSimulationFromArcGISRasters, u'cls', CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'cls')
|
|---|
| 1025 |
|
|---|
| 1026 | AddArgumentMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'simulationDirectory',
|
|---|
| 1027 | typeMetadata=DirectoryTypeMetadata(mustExist=True),
|
|---|
| 1028 | description=_(
|
|---|
| 1029 | u"""Existing coral reef connectivity simulation directory that should
|
|---|
| 1030 | recieve the geostrophic currents data.
|
|---|
| 1031 |
|
|---|
| 1032 | The directory must have been created using the Create Coral Reef
|
|---|
| 1033 | Connectivity Simulation tool.
|
|---|
| 1034 |
|
|---|
| 1035 | If you have already loaded geostrophic currents data into the
|
|---|
| 1036 | simulation, you can use this tool to add data for an additional range
|
|---|
| 1037 | of dates so long as the data is from the same Aviso product. If you
|
|---|
| 1038 | try to add a different product to existing data, this tool will report
|
|---|
| 1039 | an error.
|
|---|
| 1040 |
|
|---|
| 1041 | If you try to load data for a range of dates that have been already
|
|---|
| 1042 | loaded into the simulation, the downloads for those dates will be
|
|---|
| 1043 | skipped. There is no way to delete or overwrite the data that has
|
|---|
| 1044 | already been loaded into the simulation. If you want to overwrite your
|
|---|
| 1045 | existing data (e.g. you want to switch to using a different Aviso
|
|---|
| 1046 | product), you must create a new simulation."""),
|
|---|
| 1047 | arcGISDisplayName=_(u'Simulation directory to recieve geostrophic currents data'))
|
|---|
| 1048 |
|
|---|
| 1049 | CopyArgumentMetadata(AvisoGriddedGeostrophicCurrents.CreateArcGISRasters, u'username', CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'username')
|
|---|
| 1050 | CopyArgumentMetadata(AvisoGriddedGeostrophicCurrents.CreateArcGISRasters, u'password', CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'password')
|
|---|
| 1051 |
|
|---|
| 1052 | AddArgumentMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'product',
|
|---|
| 1053 | typeMetadata=UnicodeStringTypeMetadata(allowedValues=filter(lambda s: s.find(u'MADT') >= 0, AvisoGriddedGeostrophicCurrents.Products)),
|
|---|
| 1054 | description=_(
|
|---|
| 1055 | u"""Aviso geostrophic currents product to load into the simulation.
|
|---|
| 1056 | Please see the Aviso web site (http://www.aviso.oceanobs.com) for
|
|---|
| 1057 | descriptions of the products.
|
|---|
| 1058 |
|
|---|
| 1059 | At the time of this writing, this tool supported all of the
|
|---|
| 1060 | geostrophic currents products that Aviso made available for download
|
|---|
| 1061 | over OPeNDAP. If you find that Aviso publishes a new product that is
|
|---|
| 1062 | not available using this tool, please contact the author of this tool
|
|---|
| 1063 | to have support for it added.
|
|---|
| 1064 |
|
|---|
| 1065 | The product name that you must pass for this parameter is case
|
|---|
| 1066 | sensitive. If you invoke this tool programmatically, be sure to
|
|---|
| 1067 | specify the product name using the proper case."""),
|
|---|
| 1068 | arcGISDisplayName=_(u'Aviso geostrophic currents product to download'))
|
|---|
| 1069 |
|
|---|
| 1070 | AddArgumentMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'startDate',
|
|---|
| 1071 | typeMetadata=DateTimeTypeMetadata(),
|
|---|
| 1072 | description=_(
|
|---|
| 1073 | u"""Start date for the data to load into the simulation. Data that
|
|---|
| 1074 | occurs on or after the start date and on or before the end date will
|
|---|
| 1075 | be loaded into the simulation."""),
|
|---|
| 1076 | arcGISDisplayName=_(u'Start date'))
|
|---|
| 1077 |
|
|---|
| 1078 | AddArgumentMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'endDate',
|
|---|
| 1079 | typeMetadata=DateTimeTypeMetadata(),
|
|---|
| 1080 | description=_(
|
|---|
| 1081 | u"""End date for the data to load into the simulation. Data that
|
|---|
| 1082 | occurs on or after the start date and on or before the end date will
|
|---|
| 1083 | be loaded into the simulation."""),
|
|---|
| 1084 | arcGISDisplayName=_(u'End date'))
|
|---|
| 1085 |
|
|---|
| 1086 | CopyArgumentMetadata(AvisoGriddedGeostrophicCurrents.CreateArcGISRasters, u'timeout', CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'timeout')
|
|---|
| 1087 | CopyArgumentMetadata(AvisoGriddedGeostrophicCurrents.CreateArcGISRasters, u'maxRetryTime', CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'maxRetryTime')
|
|---|
| 1088 | CopyArgumentMetadata(AvisoGriddedGeostrophicCurrents.CreateArcGISRasters, u'cacheDirectory', CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'cacheDirectory')
|
|---|
| 1089 |
|
|---|
| 1090 | AddResultMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'updatedSimulationDirectory',
|
|---|
| 1091 | typeMetadata=DirectoryTypeMetadata(),
|
|---|
| 1092 | description=_(u'Updated simulation directory.'),
|
|---|
| 1093 | arcGISDisplayName=_(u'Updated simulation directory'))
|
|---|
| 1094 |
|
|---|
| 1095 | # Public method: CoralReefConnectivity.LoadOSCARCurrentsIntoSimulation
|
|---|
| 1096 |
|
|---|
| 1097 | AddMethodMetadata(CoralReefConnectivity.LoadOSCARCurrentsIntoSimulation,
|
|---|
| 1098 | shortDescription=_(u'Downloads NOAA OSCAR 5-day unfiltered 1/3 degree ocean surface currents into a coral reef connectivity simulation.'),
|
|---|
| 1099 | longDescription=_OSCAR_LongDescription % {u'name': 'tool'},
|
|---|
| 1100 | isExposedToPythonCallers=True,
|
|---|
| 1101 | isExposedByCOM=True,
|
|---|
| 1102 | isExposedAsArcGISTool=True,
|
|---|
| 1103 | arcGISDisplayName=_(u'Load OSCAR Currents Into Coral Reef Connectivity Simulation'),
|
|---|
| 1104 | arcGISToolCategory=_(u'Connectivity Analysis\\Coral Reef Larval Connectivity'),
|
|---|
| 1105 | dependencies=[ArcGISDependency(9, 2), ArcGISExtensionDependency(u'spatial'), PythonAggregatedModuleDependency('numpy')])
|
|---|
| 1106 |
|
|---|
| 1107 | CopyArgumentMetadata(CoralReefConnectivity.CreateSimulationFromArcGISRasters, u'cls', CoralReefConnectivity.LoadOSCARCurrentsIntoSimulation, u'cls')
|
|---|
| 1108 |
|
|---|
| 1109 | AddArgumentMetadata(CoralReefConnectivity.LoadOSCARCurrentsIntoSimulation, u'simulationDirectory',
|
|---|
| 1110 | typeMetadata=DirectoryTypeMetadata(mustExist=True),
|
|---|
| 1111 | description=_(
|
|---|
| 1112 | u"""Existing coral reef connectivity simulation directory that should
|
|---|
| 1113 | recieve the OSCAR currents data.
|
|---|
| 1114 |
|
|---|
| 1115 | The directory must have been created using the Create Coral Reef
|
|---|
| 1116 | Connectivity Simulation tool.
|
|---|
| 1117 |
|
|---|
| 1118 | If you have already loaded OSCAR currents data into the simulation,
|
|---|
| 1119 | you can use this tool to add data for an additional range of dates. If
|
|---|
| 1120 | you try to load data for a range of dates that have been already
|
|---|
| 1121 | loaded into the simulation, the downloads for those dates will be
|
|---|
| 1122 | skipped."""),
|
|---|
| 1123 | arcGISDisplayName=_(u'Simulation directory to recieve OSCAR currents data'))
|
|---|
| 1124 |
|
|---|
| 1125 | CopyArgumentMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'startDate', CoralReefConnectivity.LoadOSCARCurrentsIntoSimulation, u'startDate')
|
|---|
| 1126 | CopyArgumentMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'endDate', CoralReefConnectivity.LoadOSCARCurrentsIntoSimulation, u'endDate')
|
|---|
| 1127 | CopyArgumentMetadata(OSCAR5DayThirdDegreeCurrents.CreateArcGISRasters, u'timeout', CoralReefConnectivity.LoadOSCARCurrentsIntoSimulation, u'timeout')
|
|---|
| 1128 | CopyArgumentMetadata(OSCAR5DayThirdDegreeCurrents.CreateArcGISRasters, u'maxRetryTime', CoralReefConnectivity.LoadOSCARCurrentsIntoSimulation, u'maxRetryTime')
|
|---|
| 1129 | CopyArgumentMetadata(OSCAR5DayThirdDegreeCurrents.CreateArcGISRasters, u'cacheDirectory', CoralReefConnectivity.LoadOSCARCurrentsIntoSimulation, u'cacheDirectory')
|
|---|
| 1130 |
|
|---|
| 1131 | CopyResultMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'updatedSimulationDirectory', CoralReefConnectivity.LoadOSCARCurrentsIntoSimulation, u'updatedSimulationDirectory')
|
|---|
| 1132 |
|
|---|
| 1133 | # Public method: CoralReefConnectivity.LoadHYCOMGOMl0044DCurrentsIntoSimulation
|
|---|
| 1134 |
|
|---|
| 1135 | AddMethodMetadata(CoralReefConnectivity.LoadHYCOMGOMl0044DCurrentsIntoSimulation,
|
|---|
| 1136 | shortDescription=_(u'Downloads HYCOM GOMl0.04 ocean currents into a coral reef connectivity simulation.'),
|
|---|
| 1137 | longDescription=_HYCOMGOMl004_LongDescription % {u'name': 'tool'},
|
|---|
| 1138 | isExposedToPythonCallers=True,
|
|---|
| 1139 | isExposedByCOM=True,
|
|---|
| 1140 | isExposedAsArcGISTool=True,
|
|---|
| 1141 | arcGISDisplayName=_(u'Load HYCOM GOMl0.04 Currents Into Coral Reef Connectivity Simulation'),
|
|---|
| 1142 | arcGISToolCategory=_(u'Connectivity Analysis\\Coral Reef Larval Connectivity'),
|
|---|
| 1143 | dependencies=[ArcGISDependency(9, 2), ArcGISExtensionDependency(u'spatial'), PythonAggregatedModuleDependency('numpy')])
|
|---|
| 1144 |
|
|---|
| 1145 | CopyArgumentMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'cls', CoralReefConnectivity.LoadHYCOMGOMl0044DCurrentsIntoSimulation, u'cls')
|
|---|
| 1146 |
|
|---|
| 1147 | AddArgumentMetadata(CoralReefConnectivity.LoadHYCOMGOMl0044DCurrentsIntoSimulation, u'simulationDirectory',
|
|---|
| 1148 | typeMetadata=DirectoryTypeMetadata(mustExist=True),
|
|---|
| 1149 | description=_(
|
|---|
| 1150 | u"""Existing coral reef connectivity simulation directory that should
|
|---|
| 1151 | recieve the currents.
|
|---|
| 1152 |
|
|---|
| 1153 | The directory must have been created using the Create Coral Reef
|
|---|
| 1154 | Connectivity Simulation tool.
|
|---|
| 1155 |
|
|---|
| 1156 | If you have already loaded HYCOM GOMl0.04 currents into the
|
|---|
| 1157 | simulation, you can use this tool to add currents for an additional
|
|---|
| 1158 | range of dates so long as they are for the same depth as the original
|
|---|
| 1159 | currents. If you try to add a different currents product to the
|
|---|
| 1160 | simulation (e.g. geostrophic currents from Aviso), or for a different
|
|---|
| 1161 | depth, this tool will report an error.
|
|---|
| 1162 |
|
|---|
| 1163 | If you try to load data for a range of dates that have been already
|
|---|
| 1164 | loaded into the simulation, the downloads for those dates will be
|
|---|
| 1165 | skipped. There is no way to delete or overwrite the data that has
|
|---|
| 1166 | already been loaded into the simulation. If you want to overwrite your
|
|---|
| 1167 | existing data (e.g. you want to switch to using a different depth),
|
|---|
| 1168 | you must create a new simulation."""),
|
|---|
| 1169 | arcGISDisplayName=_(u'Simulation directory to recieve HYCOM currents'))
|
|---|
| 1170 |
|
|---|
| 1171 | CopyArgumentMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'startDate', CoralReefConnectivity.LoadHYCOMGOMl0044DCurrentsIntoSimulation, u'startDate')
|
|---|
| 1172 | CopyArgumentMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'endDate', CoralReefConnectivity.LoadHYCOMGOMl0044DCurrentsIntoSimulation, u'endDate')
|
|---|
| 1173 |
|
|---|
| 1174 | AddArgumentMetadata(CoralReefConnectivity.LoadHYCOMGOMl0044DCurrentsIntoSimulation, u'depth',
|
|---|
| 1175 | typeMetadata=FloatTypeMetadata(allowedValues=[0., 5., 10., 15., 20., 25., 30., 40., 50., 60., 70., 80., 90., 100., 125., 150., 200., 250., 300., 400., 500., 600., 700., 800., 900., 1000., 1100., 1200., 1300., 1400., 1500., 1750., 2000., 2500., 3000., 3500., 4000., 4500., 5000., 5500.]),
|
|---|
| 1176 | description=_(
|
|---|
| 1177 | u"""HYCOM depth layer to download currents from.
|
|---|
| 1178 |
|
|---|
| 1179 | This tool was designed primarily to study larvae that float at or near
|
|---|
| 1180 | the surface. The default depth is 0. If you are studying larvae that
|
|---|
| 1181 | stay submerged, you can choose a deeper depth, but be aware of two
|
|---|
| 1182 | important points:
|
|---|
| 1183 |
|
|---|
| 1184 | * This tool assumes the larvae remain at that depth for the entire
|
|---|
| 1185 | simulation. It does not implement vertical migration or other
|
|---|
| 1186 | behaviors that might be appropriate for your species. A newer
|
|---|
| 1187 | version of this tool, to be released in 2012, will support vertical
|
|---|
| 1188 | migration.
|
|---|
| 1189 |
|
|---|
| 1190 | * Be aware that the spatial extent of available currents data will
|
|---|
| 1191 | shrink as depth increases. For example, if you choose a deep depth
|
|---|
| 1192 | such as 250 m, there will be no data available for regions close to
|
|---|
| 1193 | shore because the ocean is typically shallower than 250 m in those
|
|---|
| 1194 | regions. Data for very deep depths will only be available near the
|
|---|
| 1195 | center of the Gulf of Mexico.
|
|---|
| 1196 | """),
|
|---|
| 1197 | arcGISDisplayName=_(u'Minimum depth'))
|
|---|
| 1198 |
|
|---|
| 1199 | CopyArgumentMetadata(HYCOMGOMl0044D.CreateArcGISRasters, u'timeout', CoralReefConnectivity.LoadHYCOMGOMl0044DCurrentsIntoSimulation, u'timeout')
|
|---|
| 1200 | CopyArgumentMetadata(HYCOMGOMl0044D.CreateArcGISRasters, u'maxRetryTime', CoralReefConnectivity.LoadHYCOMGOMl0044DCurrentsIntoSimulation, u'maxRetryTime')
|
|---|
| 1201 | CopyArgumentMetadata(HYCOMGOMl0044D.CreateArcGISRasters, u'cacheDirectory', CoralReefConnectivity.LoadHYCOMGOMl0044DCurrentsIntoSimulation, u'cacheDirectory')
|
|---|
| 1202 |
|
|---|
| 1203 | CopyResultMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'updatedSimulationDirectory', CoralReefConnectivity.LoadHYCOMGOMl0044DCurrentsIntoSimulation, u'updatedSimulationDirectory')
|
|---|
| 1204 |
|
|---|
| 1205 | # Public method: CoralReefConnectivity.LoadHYCOMGLBa0084DEquatorialCurrentsIntoSimulation
|
|---|
| 1206 |
|
|---|
| 1207 | AddMethodMetadata(CoralReefConnectivity.LoadHYCOMGLBa0084DEquatorialCurrentsIntoSimulation,
|
|---|
| 1208 | shortDescription=_(u'Downloads HYCOM GLBa0.08 ocean currents into a coral reef connectivity simulation.'),
|
|---|
| 1209 | longDescription=_HYCOMGLBa008Equatorial_LongDescription % {u'name': 'tool'},
|
|---|
| 1210 | isExposedToPythonCallers=True,
|
|---|
| 1211 | isExposedByCOM=True,
|
|---|
| 1212 | isExposedAsArcGISTool=True,
|
|---|
| 1213 | arcGISDisplayName=_(u'Load HYCOM GLBa0.08 Currents Into Coral Reef Connectivity Simulation'),
|
|---|
| 1214 | arcGISToolCategory=_(u'Connectivity Analysis\\Coral Reef Larval Connectivity'),
|
|---|
| 1215 | dependencies=[ArcGISDependency(9, 2), ArcGISExtensionDependency(u'spatial'), PythonAggregatedModuleDependency('numpy')])
|
|---|
| 1216 |
|
|---|
| 1217 | CopyArgumentMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'cls', CoralReefConnectivity.LoadHYCOMGLBa0084DEquatorialCurrentsIntoSimulation, u'cls')
|
|---|
| 1218 |
|
|---|
| 1219 | AddArgumentMetadata(CoralReefConnectivity.LoadHYCOMGLBa0084DEquatorialCurrentsIntoSimulation, u'simulationDirectory',
|
|---|
| 1220 | typeMetadata=DirectoryTypeMetadata(mustExist=True),
|
|---|
| 1221 | description=_(
|
|---|
| 1222 | u"""Existing coral reef connectivity simulation directory that should
|
|---|
| 1223 | recieve the currents.
|
|---|
| 1224 |
|
|---|
| 1225 | The directory must have been created using the Create Coral Reef
|
|---|
| 1226 | Connectivity Simulation tool.
|
|---|
| 1227 |
|
|---|
| 1228 | If you have already loaded HYCOM GLBa0.08 currents into the
|
|---|
| 1229 | simulation, you can use this tool to add currents for an additional
|
|---|
| 1230 | range of dates so long as they are for the same depth as the original
|
|---|
| 1231 | currents. If you try to add a different currents product to the
|
|---|
| 1232 | simulation (e.g. geostrophic currents from Aviso), or for a different
|
|---|
| 1233 | depth, this tool will report an error.
|
|---|
| 1234 |
|
|---|
| 1235 | If you try to load data for a range of dates that have been already
|
|---|
| 1236 | loaded into the simulation, the downloads for those dates will be
|
|---|
| 1237 | skipped. There is no way to delete or overwrite the data that has
|
|---|
| 1238 | already been loaded into the simulation. If you want to overwrite your
|
|---|
| 1239 | existing data (e.g. you want to switch to using a different depth),
|
|---|
| 1240 | you must create a new simulation."""),
|
|---|
| 1241 | arcGISDisplayName=_(u'Simulation directory to recieve HYCOM currents'))
|
|---|
| 1242 |
|
|---|
| 1243 | CopyArgumentMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'startDate', CoralReefConnectivity.LoadHYCOMGLBa0084DEquatorialCurrentsIntoSimulation, u'startDate')
|
|---|
| 1244 | CopyArgumentMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'endDate', CoralReefConnectivity.LoadHYCOMGLBa0084DEquatorialCurrentsIntoSimulation, u'endDate')
|
|---|
| 1245 |
|
|---|
| 1246 | AddArgumentMetadata(CoralReefConnectivity.LoadHYCOMGLBa0084DEquatorialCurrentsIntoSimulation, u'depth',
|
|---|
| 1247 | typeMetadata=FloatTypeMetadata(allowedValues=[0., 10., 20., 30., 50., 75., 100., 125., 150., 200., 250., 300., 400., 500., 600., 700., 800., 900., 1000., 1100., 1200., 1300., 1400., 1500., 1750., 2000., 2500., 3000., 3500., 4000., 4500., 5000., 5500.]),
|
|---|
| 1248 | description=_(
|
|---|
| 1249 | u"""HYCOM depth layer to download currents from.
|
|---|
| 1250 |
|
|---|
| 1251 | This tool was designed primarily to study larvae that float at or near
|
|---|
| 1252 | the surface. The default depth is 0. If you are studying larvae that
|
|---|
| 1253 | stay submerged, you can choose a deeper depth, but be aware of two
|
|---|
| 1254 | important points:
|
|---|
| 1255 |
|
|---|
| 1256 | * This tool assumes the larvae remain at that depth for the entire
|
|---|
| 1257 | simulation. It does not implement vertical migration or other
|
|---|
| 1258 | behaviors that might be appropriate for your species. A newer
|
|---|
| 1259 | version of this tool, to be released in 2012, will support vertical
|
|---|
| 1260 | migration.
|
|---|
| 1261 |
|
|---|
| 1262 | * Be aware that the spatial extent of available currents data will
|
|---|
| 1263 | shrink as depth increases. For example, if you choose a deep depth
|
|---|
| 1264 | such as 250 m, there will be no data available for regions close to
|
|---|
| 1265 | shore because the ocean is typically shallower than 250 m in those
|
|---|
| 1266 | regions.
|
|---|
| 1267 | """),
|
|---|
| 1268 | arcGISDisplayName=_(u'Minimum depth'))
|
|---|
| 1269 |
|
|---|
| 1270 | CopyArgumentMetadata(HYCOMGLBa008Equatorial4D.CreateArcGISRasters, u'extendYExtent', CoralReefConnectivity.LoadHYCOMGLBa0084DEquatorialCurrentsIntoSimulation, u'extendYExtent')
|
|---|
| 1271 | CopyArgumentMetadata(HYCOMGLBa008Equatorial4D.CreateArcGISRasters, u'timeout', CoralReefConnectivity.LoadHYCOMGLBa0084DEquatorialCurrentsIntoSimulation, u'timeout')
|
|---|
| 1272 | CopyArgumentMetadata(HYCOMGLBa008Equatorial4D.CreateArcGISRasters, u'maxRetryTime', CoralReefConnectivity.LoadHYCOMGLBa0084DEquatorialCurrentsIntoSimulation, u'maxRetryTime')
|
|---|
| 1273 | CopyArgumentMetadata(HYCOMGLBa008Equatorial4D.CreateArcGISRasters, u'cacheDirectory', CoralReefConnectivity.LoadHYCOMGLBa0084DEquatorialCurrentsIntoSimulation, u'cacheDirectory')
|
|---|
| 1274 |
|
|---|
| 1275 | CopyResultMetadata(CoralReefConnectivity.LoadAvisoGeostrophicCurrentsIntoSimulation, u'updatedSimulationDirectory', CoralReefConnectivity.LoadHYCOMGLBa0084DEquatorialCurrentsIntoSimulation, u'updatedSimulationDirectory')
|
|---|
| 1276 |
|
|---|
| 1277 | # Public method: CoralReefConnectivity.RunSimulation
|
|---|
| 1278 |
|
|---|
| 1279 | AddMethodMetadata(CoralReefConnectivity.RunSimulation,
|
|---|
| 1280 | shortDescription=_(u'Executes a coral coral reef connectivity simulation.'),
|
|---|
| 1281 | isExposedToPythonCallers=True,
|
|---|
| 1282 | isExposedByCOM=True,
|
|---|
| 1283 | isExposedAsArcGISTool=True,
|
|---|
| 1284 | arcGISDisplayName=_(u'Run Coral Reef Connectivity Simulation'),
|
|---|
| 1285 | arcGISToolCategory=_(u'Connectivity Analysis\\Coral Reef Larval Connectivity'),
|
|---|
| 1286 | dependencies=[ArcGISDependency(9, 2), ArcGISExtensionDependency(u'spatial'), PythonAggregatedModuleDependency('numpy')])
|
|---|
| 1287 |
|
|---|
| 1288 | CopyArgumentMetadata(CoralReefConnectivity.CreateSimulationFromArcGISRasters, u'cls', CoralReefConnectivity.RunSimulation, u'cls')
|
|---|
| 1289 |
|
|---|
| 1290 | AddArgumentMetadata(CoralReefConnectivity.RunSimulation, u'simulationDirectory',
|
|---|
| 1291 | typeMetadata=DirectoryTypeMetadata(mustExist=True),
|
|---|
| 1292 | description=_(
|
|---|
| 1293 | u"""Existing coral reef connectivity simulation directory that has
|
|---|
| 1294 | been loaded with ocean currents data.
|
|---|
| 1295 |
|
|---|
| 1296 | The directory must have been created using the Create Coral Reef
|
|---|
| 1297 | Connectivity Simulation tool and then loaded with ocean currents data
|
|---|
| 1298 | using one of the tools provided for this purpose.
|
|---|
| 1299 |
|
|---|
| 1300 | The simulation may take hours to complete, due to the complex
|
|---|
| 1301 | mathematics involved. The run time is goverened by the size of your
|
|---|
| 1302 | study area, the number of reefs include in the simulation, and the
|
|---|
| 1303 | duration and time step of the simulation."""),
|
|---|
| 1304 | arcGISDisplayName=_(u'Simulation directory'))
|
|---|
| 1305 |
|
|---|
| 1306 | AddArgumentMetadata(CoralReefConnectivity.RunSimulation, u'outputDirectory',
|
|---|
| 1307 | typeMetadata=DirectoryTypeMetadata(mustExist=True),
|
|---|
| 1308 | description=_(
|
|---|
| 1309 | u"""Output directory to receive the results of the simulation.
|
|---|
| 1310 |
|
|---|
| 1311 | The directory must already exist. Within it, the simulator creates:
|
|---|
| 1312 |
|
|---|
| 1313 | * DensityRasters - this subdirectory will contain a time series of
|
|---|
| 1314 | rasters that represent snapshots of the larvae density throughout
|
|---|
| 1315 | the study area, in particles per square km. A raster will be created
|
|---|
| 1316 | each time the simulation is summarized; the summarization frequency
|
|---|
| 1317 | is controlled by the Simulation Summarization Period parameter. The
|
|---|
| 1318 | rasters' names will be of the form dYYYYDDDHHMM, where YYYY is the
|
|---|
| 1319 | year, DDD is the day of the year (e.g. February 1 is day 032), HH is
|
|---|
| 1320 | the hour, and MM is the minute.
|
|---|
| 1321 |
|
|---|
| 1322 | * DensityRasters raster catalog in ConnectivityGeodatabase.mdb - this
|
|---|
| 1323 | catalog references the rasters created in the DensityRasters
|
|---|
| 1324 | subdirectory. The StartDate and EndDate columns of the catalog
|
|---|
| 1325 | specify the applicable timeframe for each raster, and may be used to
|
|---|
| 1326 | animate the raster time series using the Animation toolbar available
|
|---|
| 1327 | in ArcMap and other ArcGIS applications.
|
|---|
| 1328 |
|
|---|
| 1329 | * Edges feature class in ConnectivityGeodatabase.mdb - this line
|
|---|
| 1330 | feature class shows which reefs are connected by larval dispersal.
|
|---|
| 1331 | Each line represents a direction link between two reefs. The
|
|---|
| 1332 | FromReefID and ToReefID fields specify the IDs of the source reef
|
|---|
| 1333 | and sink reef, respectively. The MaxDispersal field shows the
|
|---|
| 1334 | maximum quantity of larvae from the source reef found over the sink
|
|---|
| 1335 | reef during the series of simulation summaries. The quantity is
|
|---|
| 1336 | expressed as the fraction of larvae initially released from the
|
|---|
| 1337 | source reef that are over the sink reef, and ranges from 0.0 to 1.0.
|
|---|
| 1338 | For example, the value 0.01 means that 1% of the larvae initially
|
|---|
| 1339 | released by the source reef were found over the sink reef, when
|
|---|
| 1340 | dispersal from the source to the sink peaked.
|
|---|
| 1341 | """),
|
|---|
| 1342 | arcGISDisplayName=_(u'Output directory'))
|
|---|
| 1343 |
|
|---|
| 1344 | AddArgumentMetadata(CoralReefConnectivity.RunSimulation, u'startDate',
|
|---|
| 1345 | typeMetadata=DateTimeTypeMetadata(),
|
|---|
| 1346 | description=_(
|
|---|
| 1347 | u"""Start date of the simulation.
|
|---|
| 1348 |
|
|---|
| 1349 | The larvae are released from the reefs on this date. Selecting an
|
|---|
| 1350 | appropriate value requires knowledge of the reproductive biology of
|
|---|
| 1351 | the species you are studying."""),
|
|---|
| 1352 | arcGISDisplayName=_(u'Start date'))
|
|---|
| 1353 |
|
|---|
| 1354 | AddArgumentMetadata(CoralReefConnectivity.RunSimulation, u'duration',
|
|---|
| 1355 | typeMetadata=FloatTypeMetadata(minValue=0.0),
|
|---|
| 1356 | description=_(
|
|---|
| 1357 | u"""Duration of the simulation, in days.
|
|---|
| 1358 |
|
|---|
| 1359 | Larger values require more computer memory and require more processing
|
|---|
| 1360 | time. To avoid extreme scenarios, this parameter can be no larger that
|
|---|
| 1361 | 365 days."""),
|
|---|
| 1362 | arcGISDisplayName=_(u'Duration'))
|
|---|
| 1363 |
|
|---|
| 1364 | AddArgumentMetadata(CoralReefConnectivity.RunSimulation, u'simulationTimeStep',
|
|---|
| 1365 | typeMetadata=FloatTypeMetadata(minValue=0.0),
|
|---|
| 1366 | description=_(
|
|---|
| 1367 | u"""Time step of the simulation, in hours.
|
|---|
| 1368 |
|
|---|
| 1369 | The time step defines the simulated time period at which larvae
|
|---|
| 1370 | density is recalculated using a Eulerian advection/diffusion model.
|
|---|
| 1371 | Smaller time steps increase the stability of the model and accuracy of
|
|---|
| 1372 | the results but also the run time and computer memory requirements of
|
|---|
| 1373 | the simulation. The original study from which this tool was developed
|
|---|
| 1374 | (Treml et al. 2008) used a time step of 2.4 hours.
|
|---|
| 1375 |
|
|---|
| 1376 | To check the model stability, this tool reports the effective Courant
|
|---|
| 1377 | number for the model, calculated from the simulation time step, grid
|
|---|
| 1378 | cell size, and average current velocity. The Courant number reflects
|
|---|
| 1379 | the portion of a cell that the larvae will traverse by advection in
|
|---|
| 1380 | one time step. If the Courant number is greater than 1, the model is
|
|---|
| 1381 | likely to be unstable and inaccurate. If it is significantly less than
|
|---|
| 1382 | 1 (e.g. 0.1), it is likely to be stable and accurate."""),
|
|---|
| 1383 | arcGISDisplayName=_(u'Temp step'),
|
|---|
| 1384 | arcGISCategory=_(u'Simulation options'))
|
|---|
| 1385 |
|
|---|
| 1386 | AddArgumentMetadata(CoralReefConnectivity.RunSimulation, u'summarizationPeriod',
|
|---|
| 1387 | typeMetadata=IntegerTypeMetadata(minValue=1),
|
|---|
| 1388 | description=_(
|
|---|
| 1389 | u"""Period, expressed as a number of simulation time steps, at which
|
|---|
| 1390 | the simulation should be summarized.
|
|---|
| 1391 |
|
|---|
| 1392 | The period specifies how frequently summarization should occur. The
|
|---|
| 1393 | first summarization will occur at the start of the simulation, and
|
|---|
| 1394 | subsequent summarizations will occur every time the period elapses.
|
|---|
| 1395 | For example, if the time step is 1 hour and the summarization period
|
|---|
| 1396 | is 24, summarizations will occur every 24 hours.
|
|---|
| 1397 |
|
|---|
| 1398 | The summarization procedure governs the production of simulation
|
|---|
| 1399 | outputs. Please see the documentation of the Output Directory
|
|---|
| 1400 | parameter for more information."""),
|
|---|
| 1401 | arcGISDisplayName=_(u'Sumulation summarization period'),
|
|---|
| 1402 | arcGISCategory=_(u'Simulation options'))
|
|---|
| 1403 |
|
|---|
| 1404 | AddArgumentMetadata(CoralReefConnectivity.RunSimulation, u'initialLarvaeDensity',
|
|---|
| 1405 | typeMetadata=FloatTypeMetadata(minValue=1.0),
|
|---|
| 1406 | description=_(
|
|---|
| 1407 | u"""Density of larvae, in particles per square km, released at the
|
|---|
| 1408 | start of the simulation.
|
|---|
| 1409 |
|
|---|
| 1410 | The original study from which this tool was developed (Treml et al.
|
|---|
| 1411 | 2008) used 10,000 particles per square km. This is consistent with
|
|---|
| 1412 | previous studies (Cowen et al. 2000; James et al. 2002; Largier 2003)
|
|---|
| 1413 | and was selected based on exploratory modeling efforts using densities
|
|---|
| 1414 | ranging from 1,000 to 100,000 particles per square km. For particular
|
|---|
| 1415 | taxa, these initial densities may need to be larger or smaller, based
|
|---|
| 1416 | on the specific fecundity and density characteristics of that species
|
|---|
| 1417 | of interest (Richmond 1987; Largier 2003)."""),
|
|---|
| 1418 | arcGISDisplayName=_(u'Initial larvae density'),
|
|---|
| 1419 | arcGISCategory=_(u'Simulation options'))
|
|---|
| 1420 |
|
|---|
| 1421 | AddArgumentMetadata(CoralReefConnectivity.RunSimulation, u'densityRasterCutoff',
|
|---|
| 1422 | typeMetadata=FloatTypeMetadata(minValue=0.0, maxValue=100.0, canBeNone=True),
|
|---|
| 1423 | description=_(
|
|---|
| 1424 | u"""Minimum larvae density, expressed as a percentage of the initial
|
|---|
| 1425 | larvae density, that a larvae density raster cell must be to not be
|
|---|
| 1426 | masked.
|
|---|
| 1427 |
|
|---|
| 1428 | This parameter is a percent of the initial larvae density. For
|
|---|
| 1429 | example, if the initial larvae density is 10000 particles per km and
|
|---|
| 1430 | this parameter is 1, a density of 100 particles per km will be used as
|
|---|
| 1431 | the cutoff. Larvae density cells that are less than this value will
|
|---|
| 1432 | set to NoData.
|
|---|
| 1433 |
|
|---|
| 1434 | This parameter does not affect the computations performed during the
|
|---|
| 1435 | simulation. It only affects the production of density rasters after
|
|---|
| 1436 | the simulation is complete, and is provided as a convenience for
|
|---|
| 1437 | visualization.
|
|---|
| 1438 |
|
|---|
| 1439 | If you set this parameter to 0, the density rasters will be produced
|
|---|
| 1440 | with no masking. The results may seem surprising. For most
|
|---|
| 1441 | simulations, larvae will have spread throughout the entire study area,
|
|---|
| 1442 | albeit in very small quantities for most cells. This is a surprising
|
|---|
| 1443 | effect of the diffusion component of the Eularian hydrodynamic
|
|---|
| 1444 | calculations. Diffiusion occurs equally in all directions at the rate
|
|---|
| 1445 | specified by the Diffusivity parameter. Given enough time, an
|
|---|
| 1446 | infinitesimal fraction of larvae from any given reef can theoretically
|
|---|
| 1447 | spread throughout the entire ocean simply by diffusion. To avoid a
|
|---|
| 1448 | confusing visualization, use this parameter to mask the extremely
|
|---|
| 1449 | density values that result from diffiusion."""),
|
|---|
| 1450 | arcGISDisplayName=_(u'Cutoff percentage for larvae density rasters'),
|
|---|
| 1451 | arcGISCategory=_(u'Simulation options'))
|
|---|
| 1452 |
|
|---|
| 1453 | ##AddArgumentMetadata(CoralReefConnectivity.RunSimulation, u'deathRate',
|
|---|
| 1454 | ## typeMetadata=FloatTypeMetadata(minValue=0.0, maxValue=1.0, canBeNone=True),
|
|---|
| 1455 | ## description=_(
|
|---|
| 1456 | ##u"""Death rate of the larvae, as proportion of the population that
|
|---|
| 1457 | ##dies per day.
|
|---|
| 1458 | ##
|
|---|
| 1459 | ##Reliable mortality estimates for invertebrate larvae are rare due to
|
|---|
| 1460 | ##the difficulty in sampling and identifying the same larval cohort in
|
|---|
| 1461 | ##the plankton through time (Rumrill 1990; Morgan 1995). In a review of
|
|---|
| 1462 | ##larval mortality rates, Rumrill (1990) showed that this parameter
|
|---|
| 1463 | ##varied greatly between invertebrate species, from 0.016 to .357 per
|
|---|
| 1464 | ##day, with an average of .223 per day. A recent study on several
|
|---|
| 1465 | ##Pacific corals measuring larval survival, recruitment rates, and gene
|
|---|
| 1466 | ##flow, reports the mortality of a broadcast-spawning coral to be around
|
|---|
| 1467 | ##4 - 6% per day (Nishikawa et al. 2003; Nishikawa and Sakai 2005). For
|
|---|
| 1468 | ##this reason, the study from which this tool was developed (Treml et
|
|---|
| 1469 | ##al. 2008) used a constant mortality of 6% per day. Although this rate
|
|---|
| 1470 | ##is lower than the 18% per day reported for reef fish (Cowen et al.
|
|---|
| 1471 | ##2000; James et al. 2002), it may be more representative of
|
|---|
| 1472 | ##invertebrate taxa (Rumrill 1990, Ellien et al. 2004)."""),
|
|---|
| 1473 | ## arcGISDisplayName=_(u'Larvae death rate'),
|
|---|
| 1474 | ## arcGISCategory=_(u'Simulation options'))
|
|---|
| 1475 |
|
|---|
| 1476 | AddArgumentMetadata(CoralReefConnectivity.RunSimulation, u'diffusivity',
|
|---|
| 1477 | typeMetadata=FloatTypeMetadata(minValue=0.0),
|
|---|
| 1478 | description=_(
|
|---|
| 1479 | u"""The diffusion coefficent, in meters squared per second, to use in
|
|---|
| 1480 | the simulation.
|
|---|
| 1481 |
|
|---|
| 1482 | It is recommended that you consult an oceanographer to determine this
|
|---|
| 1483 | value. The original study from which this tool was developed (Treml et
|
|---|
| 1484 | al. 2008) used the value 25."""),
|
|---|
| 1485 | arcGISDisplayName=_(u'Diffusivity'),
|
|---|
| 1486 | arcGISCategory=_(u'Simulation options'))
|
|---|
| 1487 |
|
|---|
| 1488 | AddArgumentMetadata(CoralReefConnectivity.RunSimulation, u'includeReefIDs',
|
|---|
| 1489 | typeMetadata=ListTypeMetadata(elementType=IntegerTypeMetadata(), canBeNone=True, minLength=1),
|
|---|
| 1490 | description=_(
|
|---|
| 1491 | u"""List of IDs of the reefs to include in the simulation. If the list
|
|---|
| 1492 | is empty, all of the reefs will be included, unless some reefs are
|
|---|
| 1493 | listed in the "exclude reefs" parameter."""),
|
|---|
| 1494 | arcGISDisplayName=_(u'IDs of reefs to include in the simulation'),
|
|---|
| 1495 | arcGISCategory=_(u'Simulation options'))
|
|---|
| 1496 |
|
|---|
| 1497 | AddArgumentMetadata(CoralReefConnectivity.RunSimulation, u'excludeReefIDs',
|
|---|
| 1498 | typeMetadata=ListTypeMetadata(elementType=IntegerTypeMetadata(), canBeNone=True, minLength=1),
|
|---|
| 1499 | description=_(
|
|---|
| 1500 | u"""List of IDs of the reefs to exclude from the simulation. This list
|
|---|
| 1501 | may only be provided if the "include reefs" list is omitted (an error
|
|---|
| 1502 | will be reported if both lists are provided). If this list is
|
|---|
| 1503 | provided, all of the reefs will be included in the simulation except
|
|---|
| 1504 | those in this list."""),
|
|---|
| 1505 | arcGISDisplayName=_(u'IDs of reefs to exclude from the simulation'),
|
|---|
| 1506 | arcGISCategory=_(u'Simulation options'))
|
|---|
| 1507 |
|
|---|
| 1508 | AddArgumentMetadata(CoralReefConnectivity.RunSimulation, u'overwriteExisting',
|
|---|
| 1509 | typeMetadata=BooleanTypeMetadata(),
|
|---|
| 1510 | description=_(
|
|---|
| 1511 | u"""If True, the outputs will be overwritten, if it exists. If False,
|
|---|
| 1512 | a ValueError will be raised if the outputs exist."""),
|
|---|
| 1513 | initializeToArcGISGeoprocessorVariable=u'OverwriteOutput')
|
|---|
| 1514 |
|
|---|
| 1515 | AddResultMetadata(CoralReefConnectivity.RunSimulation, u'updatedOutputDirectory',
|
|---|
| 1516 | typeMetadata=DirectoryTypeMetadata(),
|
|---|
| 1517 | description=_(u'Updated output directory.'),
|
|---|
| 1518 | arcGISDisplayName=_(u'Updated output directory'))
|
|---|
| 1519 |
|
|---|
| 1520 | ###############################################################################
|
|---|
| 1521 | # Names exported by this module
|
|---|
| 1522 | ###############################################################################
|
|---|
| 1523 |
|
|---|
| 1524 | __all__ = ['CoralReefConnectivity']
|
|---|