API
EcoSISTEM.NATURALEARTH_LEVELSEcoSISTEM.AbsoluteChangeEcoSISTEM.AbstractAccumulationPeriodEcoSISTEM.AbstractBoundaryConditionEcoSISTEM.AbstractCategoricalToleranceEcoSISTEM.AbstractChangeModeEcoSISTEM.AbstractChangeSpecEcoSISTEM.AbstractClimateEcoSISTEM.AbstractCombineStageEcoSISTEM.AbstractCoverageEcoSISTEM.AbstractDecisionSourceEcoSISTEM.AbstractDemandEcoSISTEM.AbstractEcosystemEcoSISTEM.AbstractHabitatEcoSISTEM.AbstractKernelEcoSISTEM.AbstractLayerEcoSISTEM.AbstractLayerChangeEcoSISTEM.AbstractLayerFateEcoSISTEM.AbstractLazySpecEcoSISTEM.AbstractMovementEcoSISTEM.AbstractNicheFitEcoSISTEM.AbstractOperationEcoSISTEM.AbstractParamsEcoSISTEM.AbstractProblemSeverityEcoSISTEM.AbstractRegimeEcoSISTEM.AbstractRegionEcoSISTEM.AbstractReportStageEcoSISTEM.AbstractScheduleEcoSISTEM.AbstractSeriesCalendarEcoSISTEM.AbstractSeriesEndEcoSISTEM.AbstractShapeOperationEcoSISTEM.AbstractShapeSpecEcoSISTEM.AbstractSpatialRelationEcoSISTEM.AbstractSpecEcoSISTEM.AbstractSpeciesEcoSISTEM.AbstractSpeciesRequirementEcoSISTEM.AbstractSupplyEcoSISTEM.AbstractSyntheticLayerSpecEcoSISTEM.AbstractSyntheticMaskSpecEcoSISTEM.AbstractSyntheticSpecEcoSISTEM.AbstractToleranceEcoSISTEM.AbstractTopologyEcoSISTEM.ActiveCellsEcoSISTEM.AddAbundanceEcoSISTEM.AddSpeciesEcoSISTEM.AdditiveFitEcoSISTEM.AdditiveFit2EcoSISTEM.AdditiveFit3EcoSISTEM.AdoptedFromLayersEcoSISTEM.AgreedByAllLayersEcoSISTEM.AllCellsEcoSISTEM.AllTerritoriesEcoSISTEM.AltitudeEcoSISTEM.AlwaysMovementEcoSISTEM.AsBuiltEcoSISTEM.AsInvestigatedEcoSISTEM.AtTimeEcoSISTEM.AtTimesEcoSISTEM.AxisNodeEcoSISTEM.BetweenTimesEcoSISTEM.BirthOnlyMovementEcoSISTEM.BoundedEcoSISTEM.BrownianEcoSISTEM.CERAEcoSISTEM.CODE_TYPEEcoSISTEM.CRUTSEcoSISTEM.CacheEcoSISTEM.CachedAssetEcoSISTEM.CachedEcosystemEcoSISTEM.CachedEcosystemEcoSISTEM.CachedGridLandscapeEcoSISTEM.CachedGridLandscapeEcoSISTEM.CarbonAxisEcoSISTEM.CarbonFluxEcoSISTEM.CategoricalLayerEcoSISTEM.CategoricalRegimeEcoSISTEM.CategoricalSuitabilityEcoSISTEM.CellMaskEcoSISTEM.CellNamesEcoSISTEM.CircleMaskSpecEcoSISTEM.ClimateMoistureEcoSISTEM.ClimateMoistureAxisEcoSISTEM.ClimateMoistureRangeEcoSISTEM.ClimateRasterEcoSISTEM.ClimateTypologyEcoSISTEM.CloudCoverEcoSISTEM.CloudCoverAxisEcoSISTEM.CloudCoverRangeEcoSISTEM.CombineOnSourceGridEcoSISTEM.CombineOnTargetGridEcoSISTEM.CombinedChangeEcoSISTEM.CombiningFitEcoSISTEM.ConditionEcoSISTEM.ConstantAccumulationPeriodEcoSISTEM.ConstructedRasterSpecEcoSISTEM.ConstructedShapeSpecEcoSISTEM.ContinuousLayerEcoSISTEM.ContinuousRegimeEcoSISTEM.ContinuousToleranceEcoSISTEM.CumulativeHeatEcoSISTEM.CylinderEcoSISTEM.DatedSeriesEcoSISTEM.DayAxisEcoSISTEM.DayCountEcoSISTEM.DayOfYearEcoSISTEM.DeactivateEcoSISTEM.DefaultEcosystemEcoSISTEM.DemandEcoSISTEM.DemandCollection2EcoSISTEM.DerivedDataEcoSISTEM.DiversitySetEcoSISTEM.DiversitySetEcoSISTEM.ERAEcoSISTEM.EcoSISTEMSourceEcoSISTEM.EcosystemEcoSISTEM.EcosystemEcoSISTEM.EcosystemEcoSISTEM.EdgeTopologyEcoSISTEM.EnclosesEcoSISTEM.EqualPopEcoSISTEM.ErrorAtEndEcoSISTEM.EvapotranspirationEcoSISTEM.EvapotranspirationAxisEcoSISTEM.EvapotranspirationRangeEcoSISTEM.EveryStepEcoSISTEM.FrostChangeFrequencyEcoSISTEM.GaussEcoSISTEM.GaussianKernelEcoSISTEM.GivenByUserEcoSISTEM.GradientSpecEcoSISTEM.GridHabitatEcoSISTEM.GridLandscapeEcoSISTEM.GridLandscapeEcoSISTEM.GrowingSeasonPrecipitationEcoSISTEM.HeterogeneityEcoSISTEM.HoldAtEndEcoSISTEM.HumidityAxisEcoSISTEM.IncrementByEcoSISTEM.InterventionEcoSISTEM.InterventionSetEcoSISTEM.IsRasterDataEcoSISTEM.IslandEcoSISTEM.IsothermalityEcoSISTEM.LandCoverTypologyEcoSISTEM.LandmassesAboveEcoSISTEM.LargestLandmassEcoSISTEM.LatLongEcoSISTEM.LayerAggregatedEcoSISTEM.LayerCacheEcoSISTEM.LayerCollectionEcoSISTEM.LayerInputEcoSISTEM.LayerKeptExactlyEcoSISTEM.LayerPlanEcoSISTEM.LayerRecordEcoSISTEM.LayerResampledEcoSISTEM.LayerSpecEcoSISTEM.LegacyLossEcoSISTEM.LongTailKernelEcoSISTEM.LookupEcoSISTEM.MPIEcosystemEcoSISTEM.MPIGridLandscapeEcoSISTEM.MaskSpecEcoSISTEM.MeasuredAcrossProjectionEcoSISTEM.MonthOfYearSeriesEcoSISTEM.MultiplicativeFitEcoSISTEM.MultiplicativeFit2EcoSISTEM.MultiplicativeFit3EcoSISTEM.NaturalEarthLevelEcoSISTEM.NaturalEarthSpecEcoSISTEM.NaturalEarthSpecEcoSISTEM.NeverScheduledEcoSISTEM.NicheAxisEcoSISTEM.NicheSpecEcoSISTEM.NicheSuitabilityEcoSISTEM.NicheToleranceEcoSISTEM.NicheToleranceEcoSISTEM.NicheToleranceEcoSISTEM.NoChangeEcoSISTEM.NoFitCategoricalEcoSISTEM.NoFitContinuousEcoSISTEM.NoGrowthEcoSISTEM.NoLayerChangeEcoSISTEM.NoMovementEcoSISTEM.NoMovementEcoSISTEM.NoRealWorldPositionEcoSISTEM.OffsetByEcoSISTEM.OverlapsEcoSISTEM.ParamRoleEcoSISTEM.PatternedChangeEcoSISTEM.PatternedLayerChangeEcoSISTEM.PeakedSpecEcoSISTEM.PerCellAccumulationPeriodEcoSISTEM.PerSliceAccumulationPeriodEcoSISTEM.PeriodicEcoSISTEM.PopGrowthEcoSISTEM.PrecipitationEcoSISTEM.PrecipitationAxisEcoSISTEM.PrecipitationSeasonalityEcoSISTEM.ProblemEcoSISTEM.ProblemNoticeEcoSISTEM.ProblemWarningEcoSISTEM.RainToleranceEcoSISTEM.RandomCellsEcoSISTEM.RasterDataAcceptableCodeEcoSISTEM.RateChangeEcoSISTEM.ReactivateEcoSISTEM.RegimeCollection2EcoSISTEM.RegimeCollection3EcoSISTEM.RegionMatchEcoSISTEM.RegionReportEcoSISTEM.RelativeChangeEcoSISTEM.RelativeHumidityEcoSISTEM.RelativeHumidityAxisEcoSISTEM.RelativeHumidityRangeEcoSISTEM.RemoveAbundanceEcoSISTEM.RepeatAtEndEcoSISTEM.ReplaceWithEcoSISTEM.ResourceEcoSISTEM.RevertToLayerEcoSISTEM.RoleEcoSISTEM.RoundedFromMeasurementEcoSISTEM.SavedLandscapeEcoSISTEM.SavedLandscapeEcoSISTEM.SeriesChangeEcoSISTEM.SeriesLayerChangeEcoSISTEM.SetChangeEcoSISTEM.SetLandCoverEcoSISTEM.ShapeBufferEcoSISTEM.ShapeConvexHullEcoSISTEM.ShapeDifferenceEcoSISTEM.ShapeIntersectionEcoSISTEM.ShapeSimplifyEcoSISTEM.ShapeSpecEcoSISTEM.ShapeUnionEcoSISTEM.SimpleCategoricalToleranceEcoSISTEM.SiteWaterBalanceEcoSISTEM.SnowWaterEquivalentEcoSISTEM.SolarRadiationEcoSISTEM.SolarRadiationAxisEcoSISTEM.SolarRadiationRangeEcoSISTEM.SourceSpecEcoSISTEM.SpaceAxisEcoSISTEM.Spatial2DEcoSISTEM.SpatialKindEcoSISTEM.SpatialLocationEcoSISTEM.SpatialSizeEcoSISTEM.SpeciesListEcoSISTEM.SpeciesListEcoSISTEM.SpeciesListEcoSISTEM.SpeciesRequirementCollectionEcoSISTEM.SpreadingCellsEcoSISTEM.SteadyLayerChangeEcoSISTEM.StudyAreaEcoSISTEM.StudyAreaReportEcoSISTEM.StudyGridEcoSISTEM.SumOfLayerChangesEcoSISTEM.SupplyEcoSISTEM.SupplyCollection2EcoSISTEM.SurfaceAreaEcoSISTEM.SyntheticDataEcoSISTEM.TakenFromAlignedLayerEcoSISTEM.TempToleranceEcoSISTEM.TemperatureEcoSISTEM.TemperatureAxisEcoSISTEM.TemperatureRangeEcoSISTEM.TemperatureSeasonalityEcoSISTEM.ToleranceCollection2EcoSISTEM.ToleranceCollection3EcoSISTEM.TorusEcoSISTEM.TrapezeEcoSISTEM.TrapezoidEcoSISTEM.TypologyAxisEcoSISTEM.UndatedSeriesEcoSISTEM.UnifEcoSISTEM.UniformSpecEcoSISTEM.VapourPressureEcoSISTEM.VapourPressureDeficitEcoSISTEM.VapourPressureDeficitAxisEcoSISTEM.VapourPressureDeficitRangeEcoSISTEM.VaryingEcoSISTEM.WaterAxisEcoSISTEM.WindSpeedEcoSISTEM.WindSpeedAxisEcoSISTEM.WindSpeedRangeEcoSISTEM.WithinBase.append!Base.readBase.readBase.readBase.readBase.readBase.readBase.readEcoSISTEM.ClimatePref.downresolutionEcoSISTEM.ClimatePref.downresolution!EcoSISTEM.ClimatePref.extractvaluesEcoSISTEM.ClimatePref.readCERAEcoSISTEM.ClimatePref.readCHELSA_monthlyEcoSISTEM.ClimatePref.readCRUTSEcoSISTEM.ClimatePref.readERAEcoSISTEM.ClimatePref.readERAEcoSISTEM.ClimatePref.readERAEcoSISTEM.ClimatePref.readworldclimEcoSISTEM.ClimatePref.upresolutionEcoSISTEM.GaussTraitEcoSISTEM.HabitatLossEcoSISTEM.LayerUpdateEcoSISTEM.RainfallChangeEcoSISTEM.SurfaceSpecEcoSISTEM.TempChangeEcoSISTEM.TempFluctEcoSISTEM.Units.month_durationEcoSISTEM.Units.month_durationEcoSISTEM.abundancesEcoSISTEM.applyinterventions!EcoSISTEM.arenoderecordsemptyEcoSISTEM.assetdirEcoSISTEM.assetpathEcoSISTEM.assigntraits!EcoSISTEM.bioclimhabitatEcoSISTEM.boundingboxEcoSISTEM.boundsEcoSISTEM.brownian_motionEcoSISTEM.build_ecosystemEcoSISTEM.build_habitatEcoSISTEM.build_speciesEcoSISTEM.calc_lookup_moves!EcoSISTEM.canonicalunitEcoSISTEM.cellregimeEcoSISTEM.cellsupplyEcoSISTEM.changeunitEcoSISTEM.check_boundsEcoSISTEM.checkcoverageEcoSISTEM.checkfileEcoSISTEM.checkfileEcoSISTEM.clearcache!EcoSISTEM.compress_landcoverEcoSISTEM.continuous_evolveEcoSISTEM.convert_coordsEcoSISTEM.cyclic_changeEcoSISTEM.demandtypeEcoSISTEM.densitywidthEcoSISTEM.discrete_evolveEcoSISTEM.dispersesafelyEcoSISTEM.empty_landscapeEcoSISTEM.emptypopulate!EcoSISTEM.equalpopEcoSISTEM.erahabitatEcoSISTEM.extract_valuesEcoSISTEM.fitbrownianEcoSISTEM.gatherabundanceEcoSISTEM.gatherdiversityEcoSISTEM.generate_storageEcoSISTEM.generate_storageEcoSISTEM.genlookupsEcoSISTEM.getcellareaEcoSISTEM.getcellareasEcoSISTEM.getcellatEcoSISTEM.getcellcountEcoSISTEM.getcellsizeEcoSISTEM.getcellsizesEcoSISTEM.getdemandEcoSISTEM.getdispersaldistEcoSISTEM.getdispersalvarEcoSISTEM.getdistEcoSISTEM.getgridareaEcoSISTEM.getgridshapeEcoSISTEM.getkernelsEcoSISTEM.getlatEcoSISTEM.getlongEcoSISTEM.getlookupEcoSISTEM.getlookupEcoSISTEM.getnichefitEcoSISTEM.getprefEcoSISTEM.getprefEcoSISTEM.getprefEcoSISTEM.getregimeEcoSISTEM.getregimeEcoSISTEM.getregimeEcoSISTEM.getrngEcoSISTEM.getspeciesstorageEcoSISTEM.getsupplyEcoSISTEM.gettimesEcoSISTEM.gettoleranceEcoSISTEM.gettraitsEcoSISTEM.hasdataEcoSISTEM.in_memory_rasterEcoSISTEM.investigate_regionsEcoSISTEM.investigate_study_areaEcoSISTEM.iscategoricalEcoSISTEM.landcoverclassEcoSISTEM.landcoverhabitatEcoSISTEM.layeraxesEcoSISTEM.layeraxisEcoSISTEM.layerinfoEcoSISTEM.layerrateEcoSISTEM.layersbyaxisEcoSISTEM.layerunitEcoSISTEM.loadfileEcoSISTEM.makerngsEcoSISTEM.makeuniqueEcoSISTEM.materialiseEcoSISTEM.move!EcoSISTEM.naturalearth_levelsEcoSISTEM.naturalearth_regionsEcoSISTEM.nichefitcombineEcoSISTEM.pairEcoSISTEM.paramunitsEcoSISTEM.peakedgradhabitatEcoSISTEM.populate!EcoSISTEM.populate_by_tolerance!EcoSISTEM.raingradEcoSISTEM.raingradhabitatEcoSISTEM.randomnichesEcoSISTEM.read_distributionEcoSISTEM.readfileEcoSISTEM.regimeupdate!EcoSISTEM.repopulate!EcoSISTEM.repopulate_by_tolerance!EcoSISTEM.reroot!EcoSISTEM.resettime!EcoSISTEM.resettraits!EcoSISTEM.resource_adjustmentEcoSISTEM.retrieve_era5EcoSISTEM.root_to_tipsEcoSISTEM.setchange!EcoSISTEM.simplehabitatEcoSISTEM.simplenichehabitatEcoSISTEM.simpleregimeEcoSISTEM.simpleregimeEcoSISTEM.simulate!EcoSISTEM.simulate!EcoSISTEM.simulate!EcoSISTEM.simulate_action!EcoSISTEM.simulate_record!EcoSISTEM.simulate_record_diversity!EcoSISTEM.simulationdateEcoSISTEM.simulationtimeEcoSISTEM.sinusoidalEcoSISTEM.sourcecrsEcoSISTEM.species_blocksizeEcoSISTEM.speciesdemandEcoSISTEM.speciesdispersalEcoSISTEM.speciestoleranceEcoSISTEM.suitabilityEcoSISTEM.supplytypeEcoSISTEM.supplyupdate!EcoSISTEM.synchronise_from_cols!EcoSISTEM.synchronise_from_rows!EcoSISTEM.tempgradEcoSISTEM.tempgradhabitatEcoSISTEM.totalsupplyEcoSISTEM.unziptempEcoSISTEM.update!EcoSISTEM.update!EcoSISTEM.update_resource_usage!EcoSISTEM.updatesimulation!EcoSISTEM.varcovarEcoSISTEM.worldclimhabitatEcoSISTEM.@nicheaxis
EcoSISTEMRasterDataSourcesExt is in this list, and no other extension is. Every public name whose implementation moved into an extension keeps its docstring on a method-less stub in the parent, which is why the rest need no entry - but Base.read's dataset methods cannot take a stub (the parent would have to define read(::Type, ...), pirating Base.read for every type), so their docstrings have nowhere to live but the extension. Naming the module is what keeps them in the manual.
EcoSISTEM.CODE_TYPE — Type
CODE_TYPEThe type of a single RasterDataSources layer code as a caller may write it: an Int layer number, a Symbol key or a String. All three name the same layer - layerinfo(4), layerinfo(:bio4) and layerinfo("bio4") return one record.
This is the input vocabulary, not what gets stored. A ClimateRaster resolves whatever it is given to that dataset's preferred spelling (_preferredcode), so two rasters of one layer cannot disagree about how it is named; SourceSpec's code field takes it for the same reason.
EcoSISTEM.LayerInput — Type
LayerInputType-union of everything a regime or supply keyword accepts: one AbstractSpec - which includes a Varying wrapping one - or a Tuple/NamedTuple of them for a multi-layer environment, a named tuple keeping the caller's names.
Written into the builders' signatures, not merely documented, so that methods(GridHabitat) and the rendered docs both show what a builder accepts, and a wrong kind of argument is rejected where it was passed rather than several calls later.
Deliberately not the same as LayerSpec, which is the union of spec types: this also admits the tuple forms and the Varying wrapper, because those are things a caller writes at a keyword rather than kinds of layer recipe. A Tuple here always means several layers, one spec per member; name a single data layer with a SourceSpec, which is where its axis, unit and read options live in any case.
Two costs, both accepted. Julia does not dispatch on keyword types, so a wrong argument is refused by a TypeError naming the keyword and printing this union expanded rather than by a message suggesting a remedy - and no fallback method can improve on that, since a second method with the same positional signature replaces the first instead of adding to it. And a signature cannot see inside a container, so an element of a tuple that is not a spec is caught later, by the resolvers.
EcoSISTEM.LayerSpec — Type
LayerSpecType-union of everything accepted as a regime or supply layer: a synthetic layer spec (AbstractSyntheticLayerSpec) or any lazy data-backed spec (AbstractLazySpec).
EcoSISTEM.MaskSpec — Type
MaskSpecType-union of everything accepted as an active mask: a synthetic mask spec (AbstractSyntheticMaskSpec) or any lazy data-backed spec (AbstractLazySpec).
EcoSISTEM.NATURALEARTH_LEVELS — Constant
NATURALEARTH_LEVELSEvery kind of named region the shipped region table covers, in the order they are reported.
The cultural levels come first, coarsest grouping to finest division, then the physical landform classes. A level's name is what the table's own Level column holds.
EcoSISTEM.AbsoluteChange — Type
AbsoluteChange <: AbstractChangeMode - a position: the layer's value *is* this, in the layer's unit.EcoSISTEM.AbstractAccumulationPeriod — Type
AbstractAccumulationPeriodThe interval a layer's value accumulated over - what turns a total into an honest rate. One of ConstantAccumulationPeriod, PerSliceAccumulationPeriod or PerCellAccumulationPeriod; nothing where no period applies.
A type family rather than a bare unit because the three cases are not interchangeable: a constant period is a fixed scale factor that a layer and a species tolerance both convert by, while a period that varies makes the two readings different biological claims, and the code must be able to tell which it is holding.
EcoSISTEM.AbstractBoundaryCondition — Type
AbstractBoundaryConditionWhat happens at one edge pair of a grid: Periodic (the edges join) or Bounded (they do not). A condition on a single axis, not on the grid as a whole.
EcoSISTEM.AbstractCategoricalTolerance — Type
AbstractCategoricalTolerance{A, V} <: AbstractTolerance{A, V}A species' preference among class labels - the tolerances matched against a CategoricalRegime, where preference is membership rather than a distance.
Defined by what it answers rather than by what it stores: the suitability weight species sp gets in category c. SimpleCategoricalTolerance answers that sparsely, from a set of acceptable categories per species; a graded type could answer it densely, with a different weight for every species in every category.
Categorical, so iscontinuous is false: these are class labels, and nothing between two of them is meaningful. A species' response to how much of a class covers a cell is a continuous NicheTolerance on SurfaceArea instead.
EcoSISTEM.AbstractChangeMode — Type
AbstractChangeModeHow a change's values are to be read, and so which unit they must be in. The three that carry values differ in exactly that: AbsoluteChange is a position in the layer's own unit, RelativeChange an interval from the layer's captured values, and RateChange an interval per unit time. NoChange carries no values at all.
A mode is a type parameter of AbstractLayerChange, so every change declares one and changeunit always has an answer.
EcoSISTEM.AbstractChangeSpec — Type
AbstractChangeSpecAbstract supertype of the change recipes - a declared change that has not yet met a layer, and so has not yet been unit-checked. Materialised into an AbstractLayerChange at attach.
EcoSISTEM.AbstractClimate — Type
AbstractClimateAbstract supertype of all climate data.
EcoSISTEM.AbstractCombineStage — Type
AbstractCombineStageWhen a ConstructedRasterSpec's combine runs, relative to putting its layers on the study grid: on the target grid (CombineOnTargetGrid, the default) or on the layers' own (CombineOnSourceGrid). A type rather than a symbol, so an unrecognised stage is refused by the signature where it is written rather than by a check inside the constructor.
EcoSISTEM.AbstractCoverage — Type
AbstractCoverageHow much of what a region name covers to take - AllTerritories or LargestLandmass.
A name almost never denotes one connected piece of ground. "France" includes Guadeloupe and Martinique, "Norway" includes Bouvet Island in the South Atlantic, and "Chile" includes Easter Island, so the extent of everything a name covers can be many times the extent of the ground most people mean by it. A coverage says which of the two is wanted, and is the same choice whether a bounding box or an actual shape is being asked for.
EcoSISTEM.AbstractDecisionSource — Type
AbstractDecisionSourceWhere a study area's crs or cellsize came from - GivenByUser if you supplied it, otherwise how it was derived. StudyAreaReport records one beside each of those two values, which is what lets the area announce what it guessed without also announcing what you gave it.
EcoSISTEM.AbstractDemand — Type
AbstractDemand{A, V}A demand: how much of a Resource one individual of a species needs - the species-side mirror of AbstractSupply.
Demands are what make species compete. Summed over everything present in a cell and set against what that cell supplies, they regulate births and deaths, and so decide how many individuals the cell can hold.
This is a parametric alias for AbstractSpeciesRequirement with the role pinned to Resource, and pinning it is what keeps the constraint real: a tolerance is not an AbstractDemand, so every signature written against this name refuses one. V is the type the amount is stated in, and eltype is inherited from the shared supertype.
EcoSISTEM.AbstractEcosystem — Type
AbstractEcosystem{Part <: AbstractHabitat, SL <: AbstractSpecies,
NF <: AbstractNicheFit} <: AbstractMetacommunity{Float64,
Matrix{Int64}, Matrix{Float64}, SL, Part}A community of species in a place, changing through time: an environment (Part), the species living in it (SL), and the rule scoring how well each species suits each place (NF).
This is the whole model. What it holds is an abundance for every species in every place, and what it does is let those abundances change: individuals are born, die and disperse to neighbouring places, step by step. Conditions decide where a species can persist at all, by making it die faster where its surroundings suit it poorly; resources decide how many can persist there, because the demands of everything present are set against what the place supplies. Nothing sets a carrying capacity - it is what those two pressures leave behind.
An ecosystem is a metacommunity: a set of local communities, one per place, drawn from a shared pool of species. Diversity can therefore be asked of it at either level - of a single place, or of the landscape as a whole, accounting for the fact that the same species appears in many of them.
EcoSISTEM.AbstractHabitat — Type
AbstractHabitat{H <: AbstractRegime, B <: AbstractSupply,
L <: EcoBase.AbstractLocationData} <: AbstractPartitionThe physical world a simulation runs in, with nothing living in it yet: what each place is like (H, an AbstractRegime), what it provides (B, an AbstractSupply), and where those places are (L).
A habitat is the setting rather than the story. It says that this place is this warm and this wet and offers this much light, and that place is different - but it says nothing about who lives there or how they fare. An AbstractEcosystem is what results from putting species into one.
Its conditions and supplies need not be fixed. A habitat can warm, dry out or lose land cover as the simulation proceeds, which is how climate and land-use change enter the model; a species then experiences a different environment from one year to the next without itself having changed.
A habitat also knows where its places are, so that neighbours can be identified for dispersal and results can be put back on a map. Only that much is required: this package uses a regular grid of cells, but irregular areas or scattered points would serve equally well.
EcoSISTEM.AbstractKernel — Type
AbstractKernelThe shape of the probability distribution over where an individual's offspring lands, relative to its own cell. GaussianKernel and LongTailKernel are the concrete kernels.
A kernel says only how far and how likely. What happens when a draw crosses an edge is the grid's AbstractTopology, and what becomes of one aimed at a dead cell is disperse_safely on the movement - three separate questions, answered by three separate things.
EcoSISTEM.AbstractLayer — Type
AbstractLayer{R <: Role, A}What the environment holds: one measured quantity, stated for every cell, in one of the two Roles - a regime if it is a Condition, a supply if it is a Resource.
This is the environment's half of the model. Its counterpart is AbstractSpeciesRequirement, which is what a species brings to the same axis; the two are matched role for role and axis for axis. Concrete kinds are ContinuousLayer, CategoricalLayer and the collection LayerCollection, which holds several layers over one set of cells.
The axis is carried in the type, not merely checked when an ecosystem is built, so that a signature can require a regime and the tolerance matched to it to be on the same axis.
Note that A is the axis structure rather than always a single axis: a single layer carries its own axis (Temperature), a collection a Tuple of its members' (Tuple{Temperature, Precipitation}). That is why the parameter carries no <: NicheAxis bound, and it is what lets a matched tolerance and regime be compared as one type whatever their arity. A collection's A is always read off its members rather than chosen.
EcoSISTEM.AbstractLayerChange — Type
AbstractLayerChange{M <: AbstractChangeMode}Abstract supertype of the materialised per-timestep change rules a layer can hold, parameterised by the AbstractChangeMode that says how to read its values.
A change is applied as a pure function of (layer, elapsed, timestep) - never of the ecosystem - which is what lets MPI apply it redundantly on every rank without diverging.
EcoSISTEM.AbstractLayerFate — Type
AbstractLayerFateWhat the chosen study grid costs one layer: LayerKeptExactly, LayerAggregated or LayerResampled. Each carries exactly the detail its own case has - the aggregation factor, or the reason for resampling - so a field can never be set for a case it means nothing to.
EcoSISTEM.AbstractLazySpec — Type
AbstractLazySpec <: AbstractSpecAbstract supertype of the lazy, data-backed / derived specs. Resolved against the target grid at build time and usable in either role - a regime/supply layer or an active mask: SourceSpec (read a data source), ShapeSpec (a vector file), ConstructedRasterSpec (combine child specs by a function).
EcoSISTEM.AbstractMovement — Type
AbstractMovementWhich individuals disperse at all: BirthOnlyMovement (only the newly born, plant-like), AlwaysMovement (any individual, animal-like) or NoMovement (none).
A movement carries the per-species part of dispersal - one AbstractKernel per species, and one disperse_safely flag per species. The grid's own edges are not part of it: they belong to the GridHabitat, because two species on one grid cannot be on different topologies.
disperse_safely says what becomes of an individual dispersing into a dead cell - one off the grid, or an inactive one. true redistributes it among the reachable destinations as though it had never aimed there; false loses it, so the share of the kernel pointing at dead cells becomes mortality.
It is per species because it is a fact about the disperser, not about the map. A wind-dispersed seed blown out to sea is gone; an animal-dispersed one is carried to somewhere the animal can actually reach, so two species on one grid may legitimately differ. It cannot empty a cell outright: staying put is one of the kernel's own destinations, and a cell only disperses while it is active, so some share always survives.
EcoSISTEM.AbstractNicheFit — Type
AbstractNicheFit{A, V}How well a species is suited to a cell: the rule that scores a species' AbstractSpeciesRequirement against the AbstractLayer it is matched to.
This closes the triangle. The environment states a value, the species states what it needs, and the fit says how well the two agree - a number that raises or lowers that species' birth and death rates in that cell. Where several axes are in play, a CombiningFit reduces their scores to one.
A sits in the same slot here as in AbstractLayer and AbstractSpeciesRequirement, so a single signature can require a layer, the requirement matched to it and the fit between them to be on the same axis. As there, it is the axis structure - a single axis for one fit, a Tuple of them for a combining one.
V is the value type the two sides are compared in - the same V the requirement carries - so the fit knows the frame it is working in and a layer's values can be brought into it before scoring.
EcoSISTEM.AbstractOperation — Type
AbstractOperationWhat an Intervention does - a closed set of seven: Deactivate, Reactivate, SetLandCover, SetChange, AddAbundance, RemoveAbundance and AddSpecies.
Closed on purpose. A callback would let an intervention do anything, including the things that break reproducibility and MPI - writing a continuous layer's matrix directly, drawing from the global RNG, resizing the landscape mid-run. Seven named operations can each be checked once and then trusted.
A bound is not among them, and does not need to be. It is a property of the quantity rather than of an intervention - a supply cannot be negative because of what a resource is - so it is enforced on the layer automatically; see bounds and _enforcebounds!.
EcoSISTEM.AbstractParams — Type
AbstractParamsThe demographic rates a simulation runs on: a per-species birth rate and death rate, plus the three exponents and ceilings that say how those rates respond to the environment. EqualPop, PopGrowth and NoGrowth are the concrete forms.
Every subtype carries the same five fields, and two of them are what make the model a niche model:
longevityis the exponent on a species' own resource demand, applied to birth and death alike. It therefore sets the tempo of turnover - a body-size proxy - and cancels out of the birth/death ratio, so it does not move where a species can persist.survivalis the exponent on niche suitability, applied with opposite signs to birth and death. It does move the ratio, which is what makes it the niche.
Rates are Unitful quantities per unit time, so a run is timestep-independent: twelve one-month steps and one twelve-month step see the same rates.
EcoSISTEM.AbstractProblemSeverity — Type
AbstractProblemSeverityHow much a Problem matters: a ProblemNotice or a ProblemWarning. A type rather than a symbol, so an unrecognised severity is refused by the signature where it is written rather than by a check inside the constructor.
EcoSISTEM.AbstractRegime — Type
AbstractRegime{A}A regime: what the environment is like, on one axis, in every cell - the Condition half of AbstractLayer.
A species meets a regime with its AbstractTolerance on the same axis, and how well the two agree is its suitability there. A regime is not divided between the species present: all of them experience the same value.
EcoSISTEM.AbstractRegion — Type
AbstractRegionWhere an Intervention applies - AllCells, ActiveCells, CellMask, RandomCells or SpreadingCells.
A region resolves to the linear cell indices an operation should touch. The two random regions draw from a counter-based stream keyed on the step (see Intervention), never from a species' stream and never from the global RNG, so a selection is identical on every rank and thread and a run replays exactly.
EcoSISTEM.AbstractReportStage — Type
AbstractReportStageWhich of the two things a StudyAreaReport describes: an area as proposed (AsInvestigated) or as built (AsBuilt). Both are the same type with the same fields, so this is what says which question the numbers answer.
It matters because building can narrow the grid: a report's specs and constraints always say what was asked for, while a GridHabitat's layers may have removed cells the study area still lists.
It is therefore also what makes a built report safe to reuse. Any value carrying a report can be a StudyArea's base, and re-deriving from one would rebuild the proposed grid and discard that narrowing - so an AsBuilt base given no other keyword is copied verbatim instead, which is how build_habitat reseeds a habitat from the grid it is actually on.
EcoSISTEM.AbstractSchedule — Type
AbstractScheduleWhen an Intervention fires - EveryStep, AtTime, AtTimes, BetweenTimes or NeverScheduled.
A type rather than a predicate function, so that a schedule can be reported and checked rather than merely called, and so each rule is a method instead of a branch retaken every step.
EcoSISTEM.AbstractSeriesCalendar — Type
AbstractSeriesCalendarWhat kind of time coordinate a SeriesLayerChange's slices carry, and so what a simulation epoch is able to do with them - DatedSeries, MonthOfYearSeries or UndatedSeries. Written as the calendar keyword of SeriesChange.
A series has to say which kind it is; it cannot be inferred from the values. Coordinates of one, two and three months read equally well as the first three months of the year and as one, two and three months into my experiment, and phase-locking the second to January would be silently wrong. Only the two unambiguous cases are inferred: real dates in the lookup give a DatedSeries, and no time lookup at all gives an UndatedSeries. A climatology must say calendar = MonthOfYearSeries().
The set is extensible: a series subdivided some other way (day-of-year, say) is a new subtype supplying _calendarorigin, not a change to these.
EcoSISTEM.AbstractSeriesEnd — Type
AbstractSeriesEndWhat a SeriesLayerChange does once elapsed simulation time runs past its last stored slice - ErrorAtEnd, HoldAtEnd, RepeatAtEnd or RevertToLayer. Written as the atend keyword of SeriesChange, and a type rather than a name drawn from a list, so an unrecognised policy is refused by the signature where it is written and the behaviours are separate methods rather than a branch retaken every step.
There is no matching atstart, because before its first slice a series has only one sensible reading: it has not started, so it says nothing and the layer stands. A policy with one option is not a policy.
EcoSISTEM.AbstractShapeOperation — Type
AbstractShapeOperationHow several named regions combine into one - ShapeUnion, ShapeIntersection or ShapeDifference.
Regions compose as geometries, not as rasters. A union of outlines is exact and independent of any grid, where combining rasterised masks would have to pick a resolution before the study grid was decided and would carry two sets of edge effects into the answer.
EcoSISTEM.AbstractShapeSpec — Type
AbstractShapeSpecA mask that is a piece of ground rather than data - ShapeSpec for one given as a vector file, NaturalEarthSpec for one given by name, ConstructedShapeSpec for several combined or one transformed.
What these share, and what the abstract type is for, is that they resolve to geometry before any grid exists. That is what lets them be combined exactly and at no resolution - a study area of your own, unioned with a country you named - where combining rasterised masks would have to fix a resolution before the study grid had been decided. It is the vector mirror of ConstructedRasterSpec, which composes rasters and so does need a grid.
EcoSISTEM.AbstractSpatialRelation — Type
AbstractSpatialRelationHow a named region may relate to something you have - Encloses, Overlaps or Within.
A relation carries the thing being asked about, so Encloses(mylayer) reads as what it means and there is no argument order to get the wrong way round. It is callable, taking a region's extent and answering whether the relation holds, which also makes it usable directly as a filter.
EcoSISTEM.AbstractSpec — Type
AbstractSpecAbstract root of every build-time layer/mask recipe. A spec holds no grid array itself; materialise (or the data-driven resolvers) turns it into a real grid layer only at GridHabitat time. Two branches: AbstractLazySpec (data-backed, resolved against the target grid, usable as either a layer or a mask) and AbstractSyntheticSpec (self-contained generators, role-fixed).
EcoSISTEM.AbstractSpecies — Type
AbstractSpeciesThe species living in an ecosystem, and everything the model needs to know about them.
Species are what the simulation counts and moves. Each one brings a tolerance for every condition and a demand for every resource, so that it can be matched against the environment axis by axis; it disperses its offspring in its own way, and breeds and dies at its own rate. Those four things are what make one species behave differently from another in the same place.
Species do not currently interact directly. Two of them affect one another only by drawing on the same resource: their demands are summed against what a cell supplies, and everything present feels the result equally. There are currently no pairwise terms - no predation, no interference - so an assemblage is regulated entirely by what it collectively needs against what its surroundings provide.
EcoSISTEM.AbstractSpeciesRequirement — Type
AbstractSpeciesRequirement{R <: Role, A, V}What a species brings to its environment on one axis: a tolerance for a Condition, or a demand for a Resource.
This is the species' half of the model, and the exact mirror of AbstractLayer. A species list holds the two requirements; a habitat holds the two layers; and they are matched role for role and axis for axis:
| role | the environment holds | each species brings |
|---|---|---|
Condition | a regime - AbstractRegime | a tolerance - AbstractTolerance |
Resource | a supply - AbstractSupply | a demand - AbstractDemand |
V is the species' own response type: the type of the values the requirement is stated in, so that it can be compared with the layer's. A temperature tolerance carries kelvin, a solar demand kilojoules per day, a land-cover tolerance the class codes it accepts. For a collection of requirements V is instead the members' NamedTuple, since there is no single one.
A follows AbstractLayer exactly, including that it is the axis structure rather than always a single axis. That symmetry is the point: a tolerance and the regime it is matched against carry the same A.
Write AbstractTolerance or AbstractDemand in preference to this. Each pins the role, so a demand cannot be used where a tolerance is meant. This name is for the rarer case of saying something true of both.
EcoSISTEM.AbstractSupply — Type
AbstractSupply{A}A supply: what the environment provides, on one axis, in every cell - the Resource half of AbstractLayer.
A species meets a supply with its AbstractDemand on the same axis. Unlike a regime, a supply is shared: the demands of everything in the cell are summed against it, and that ratio is what regulates births and deaths.
EcoSISTEM.AbstractSyntheticLayerSpec — Type
AbstractSyntheticLayerSpec <: AbstractSyntheticSpecSynthetic layer recipes - UniformSpec, GradientSpec, PeakedSpec, NicheSpec - used as a regime or supply, never as a mask.
EcoSISTEM.AbstractSyntheticMaskSpec — Type
AbstractSyntheticMaskSpec <: AbstractSyntheticSpecSynthetic active-mask recipes - CircleMaskSpec - used only as an active mask.
EcoSISTEM.AbstractSyntheticSpec — Type
AbstractSyntheticSpec <: AbstractSpecAbstract supertype of the synthetic (generated, non-data) specs, split by role into AbstractSyntheticLayerSpec (regime/supply layers) and AbstractSyntheticMaskSpec (active masks).
EcoSISTEM.AbstractTolerance — Type
AbstractTolerance{A, V}A tolerance: how well a species copes with a Condition, across the range that condition can take - the species-side mirror of AbstractRegime.
A tolerance is what decides where a species can persist. Matched against the regime on the same axis, it yields that species' suitability in each cell, which raises its death rate where conditions suit it poorly and lowers it where they suit it well.
This is a parametric alias for AbstractSpeciesRequirement with the role pinned to Condition, and pinning it is what keeps the constraint real: a demand is not an AbstractTolerance, so every signature written against this name refuses one. eltype is inherited from the shared supertype.
EcoSISTEM.AbstractTopology — Type
AbstractTopologyThe shape of the simulated world - how its edges join, if they join at all.
A property of the grid, held and set on GridHabitat, so every species on one grid shares it. The name promises no particular geometry: EdgeTopology is a rectangular lattice and is the only subtype at present, but a world that is not one can subtype this.
What becomes of an individual dispersing into a dead cell is a separate question, answered per species by disperse_safely on the movement rather than by the map.
EcoSISTEM.ActiveCells — Type
ActiveCells() <: AbstractRegion - only the cells currently marked active.EcoSISTEM.AddAbundance — Type
AddAbundance(species, count)Add individuals to each cell of the region - an invasion, or a reintroduction.
Arguments
species: which species, by name or by index.count: how many per cell. AnIntegeris an exact number; a quantity per unit time is a mean rate, drawn afresh each step.
EcoSISTEM.AddSpecies — Type
AddSpecies(tolerance = nothing, demand = nothing, dispersal = nothing,
birth = nothing, death = nothing, abundance, name = nothing)Introduce a new species - an invasion, a reintroduction, a crop sown for the first time - scattered across the intervention's region.
It carries the arrival's own traits, which is what it is for: an invader can be given a niche of its own rather than inheriting one. Any trait left as nothing clones the last species instead, which is what a plain reintroduction of something already present wants.
An existing species' dispersal can be handed straight over, since speciesdispersal returns exactly what dispersal takes:
AddSpecies(dispersal = EcoSISTEM.speciesdispersal(eco, 3), abundance = 500)The recording has to have room. simulate_record! writes into an array sized before the run starts, so a run that gains species needs generate_storage(eco, times, reps, maxspecies = ...); see generate_storage. Not supported under MPI: species are partitioned across ranks, so adding one changes the partition itself, and unlike the abundance operations this is not rank-local.
Arguments
abundance: how many individuals arrive in total, scattered over the region. The one required argument.tolerance,demand: the arrival's niche and its resource requirements. Cloned from the last species if omitted.dispersal: a dispersal kernel - aGaussianKernelor aLongTailKernel- matchingbuild_species' keyword of the same name. Not anAbstractMovement: the movement type and the grid's edges belong to the whole assemblage, and only the kernel is per species.birth,death: the arrival's demographic rates.name: what to call it.
EcoSISTEM.AdditiveFit — Type
AdditiveFit{A, C} - a [`CombiningFit`](@ref) whose per-layer suitabilities are added.EcoSISTEM.AdditiveFit2 — Type
AdditiveFit2{M1, M2} - two positional nichefits, added. Deprecated plumbing: use [`AdditiveFit`](@ref).EcoSISTEM.AdditiveFit3 — Type
AdditiveFit3{M1, M2, M3} - three positional nichefits, added. Deprecated plumbing: use [`AdditiveFit`](@ref).EcoSISTEM.AdoptedFromLayers — Type
AdoptedFromLayers <: AbstractDecisionSource - a CRS adopted from the layers.EcoSISTEM.AgreedByAllLayers — Type
AgreedByAllLayers <: AbstractDecisionSource - a cell size every layer agrees on.EcoSISTEM.AllCells — Type
AllCells() <: AbstractRegion - every cell in the grid, active or not.EcoSISTEM.AllTerritories — Type
AllTerritories()Take everything the name covers, however scattered.
This is faithful to the source and is what a political question usually wants: the territory of France really does include French Guiana. It is also what makes a selection able to span the antimeridian, since a country with territory either side of the date line has no single interval of longitude containing it.
EcoSISTEM.Altitude — Type
Altitude <: NicheAxis - elevation above sea level (WorldClim Elevation; m).EcoSISTEM.AlwaysMovement — Type
AlwaysMovement{K <: AbstractKernel} <: AbstractMovementAny individual may disperse, not only the newly born - animal-like.
Fields
kernels: oneAbstractKernelper species.disperse_safely: one flag per species, as described onAbstractMovement. Defaults totruefor every species.
EcoSISTEM.AsBuilt — Type
AsBuilt <: AbstractReportStage - an area as built: this describes a `GridHabitat` that exists.EcoSISTEM.AsInvestigated — Type
AsInvestigated <: AbstractReportStage - an area as proposed: nothing has been built on it yet.EcoSISTEM.AtTime — Type
AtTime(time::Unitful.Time)Fires on the single step that reaches time - the first step whose elapsed time is at or past it.
Reaches, not equals: elapsed time accumulates as a float and a run's steps need not land on time exactly, so an equality test would silently never fire. _current solves the same problem the same way for series slices.
Arguments
time: the elapsed simulation time to fire at.
EcoSISTEM.AtTimes — Type
AtTimes(times)Fires once for each of times, on the step that reaches each - AtTime repeated.
Arguments
times: the elapsed simulation times to fire at.
EcoSISTEM.AxisNode — Type
AxisNodeOne node of the layeraxes niche-axis tree: the axis type itself, the names of shipped layers that use it directly (an abstract grouping axis never carries a layer itself - only a concrete leaf does, so this is empty for every non-leaf node), and its children - the axis types immediately below it, each an AxisNode built the same way, recursively down to the concrete leaves.
EcoSISTEM.BetweenTimes — Type
BetweenTimes(from::Unitful.Time, to::Unitful.Time)Fires on every step whose elapsed time lies in [from, to].
Arguments
from,to: the inclusive elapsed-time bounds.
EcoSISTEM.BirthOnlyMovement — Type
BirthOnlyMovement{K <: AbstractKernel} <: AbstractMovementOnly individuals that have just been born disperse - plant-like.
Fields
kernels: oneAbstractKernelper species.disperse_safely: one flag per species, as described onAbstractMovement. Defaults totruefor every species.
EcoSISTEM.Bounded — Type
Bounded <: AbstractBoundaryCondition - this axis does not wrap: it has real edges.EcoSISTEM.Brownian — Type
BrownianA fitted Brownian-motion model of trait evolution, as returned by fitbrownian. Under it a trait wanders at random along every branch, so expected divergence grows with the time two lineages have been apart.
Fields of the concrete type EcoSISTEMPhyloExt.Brownian
optimum: the maximum-likelihood parameters,[σ², z̄₀]- the diffusion rate and the inferred root state.se: their standard errors, from the Hessian;showprints each parameter with a ±2 SE interval.H: the Hessian of the negative log-likelihood at the optimum.LL: the log-likelihood there, for comparison against a competing model fitted to the same trait.
EcoSISTEM.CERA — Type
CERA <: EcoSISTEMSourceThe CERA-20C reanalysis archive, as a data source. Read one with read(CERA, dir, file, param), which returns a ClimateRaster{CERA} - the archive is one file per decade, and the reader concatenates them along time.
Fieldless, as ERA is.
EcoSISTEM.CRUTS — Type
CRUTS <: EcoSISTEMSourceThe CRU TS archive, as a data source. Read one with read(CRUTS, dir, var_name), which returns a ClimateRaster{CRUTS}.
CRU TS has no layer table of its own, so its variable codes and units are taken from WorldClim{Climate}'s.
Fieldless, as ERA is.
EcoSISTEM.Cache — Type
CacheCache houses an integer array of moves made by all species in a timestep for the update! function, netmigration.
EcoSISTEM.CachedAsset — Type
CachedAsset(owner::Type, url::AbstractString)An immutable descriptor for a file downloaded from url and cached under EcoSISTEM.assetdir(owner = owner). Nothing is downloaded at construction - call assetpath to get the local path, downloading it into the cache first if it is not there.
Fields
owner: the type the download belongs to, which names its own subdirectory of the cache so that one type's downloads cannot collide with another's.url: where to fetch it from.
EcoSISTEM.CachedEcosystem — Type
CachedEcosystem{Part <: AbstractHabitat, SL <: SpeciesList,
NF <: AbstractNicheFit} <: AbstractEcosystem{Part, SL, NF}CachedEcosystem houses the same information as Ecosystem (see ?Ecosystem), but holds the time period abundances as a CachedGridLandscape, so that they may be present or missing.
EcoSISTEM.CachedEcosystem — Method
CachedEcosystem(eco::Ecosystem, outputfile::String, times::StepRangeLen;
saveinterval::Unitful.Time = step(times))Create a CachedEcosystem given an existing Ecosystem, eco, an output folder to which the simulations are saved, outputfile, and a range of times over which to simulate, times. The step of times is the simulation timestep; saveinterval controls how often checkpoints are written to disk (a multiple of the timestep, defaulting to every step). Because the simulation always advances by the timestep, results are independent of saveinterval.
EcoSISTEM.CachedGridLandscape — Type
CachedGridLandscapeA recorded run's abundances over time: one GridLandscape per timepoint, or missing where that point has not been computed yet.
How often checkpoints reach disk is separate from how often the simulation steps, and does not affect the answer: the run always advances by timestep, so saveinterval chooses only how much is kept.
Fields
matrix: aDimArrayover aTiaxis holdingGridLandscapes andmissings. Indexed by time value, which needs a selector -matrix[Ti(At(t))], notmatrix[t], which is positional and an error for aUnitful.Time.outputfolder: where the JLD2 cache files are written.saveinterval: how often a checkpoint reaches disk. A multiple oftimestep.timestep: the simulation step, and the granularity of the time axis.
EcoSISTEM.CachedGridLandscape — Method
CachedGridLandscape(file::String, times::StepRangeLen;
saveinterval::Unitful.Time = step(times))Construct a CachedGridLandscape backed by a folder, with every timepoint still missing.
Arguments
file: the folder the cache files are written to.times: every timepoint the run will cover. Its step size is the simulation timestep.saveinterval: how often a checkpoint reaches disk. Must be a multiple of the timestep, and defaults to saving every step.
EcoSISTEM.CarbonAxis — Type
CarbonAxis <: NicheAxis - carbon-cycle niche axes.EcoSISTEM.CarbonFlux — Type
CarbonFlux <: CarbonAxis - net primary productivity, a carbon flux (BioClimPlus npp; g*m^-2*day^-1).EcoSISTEM.CategoricalLayer — Type
CategoricalLayer{A <: NicheAxis, V, Arr <: DimensionalData.AbstractDimArray{V, 2}, S <: Unitful.Quantity}A categorical (class-code) grid layer on niche axis A - always a Condition (there is no categorical supply). matrix is a DimArray over (Y, X).
EcoSISTEM.CategoricalRegime — Type
CategoricalRegime{V} - a categorical regime (a [`CategoricalLayer`](@ref), e.g. land cover), a `(Y, X)` `DimArray{V}`.EcoSISTEM.CategoricalSuitability — Type
CategoricalSuitability{A, V} <: AbstractNicheFit{A, V}The nichefit between a categorical trait on class labels of type V and its environment: it reports the weight the species' tolerance gives the cell's class.
Carries no fields, like every other leaf nichefit - the whole response, both the categories a species tolerates and the penalty it takes outside them, lives on the species side in an AbstractCategoricalTolerance. That is the same division as the continuous branch, where NicheTolerance holds the response distribution and NicheSuitability only evaluates it.
Soft and hard exclusion are therefore not different fits: they are different penalty values on the tolerance.
EcoSISTEM.CellMask — Type
CellMask(mask::AbstractMatrix{Bool})The cells where mask is true.
Arguments
mask: a(Y, X)boolean grid, the same shape as the habitat's own.
EcoSISTEM.CellNames — Type
CellNames{G} <: AbstractVector{String}The names of a grid's cells - each the cell's own extent - computed on demand rather than stored.
Lazy because the eager form is what a grid this size cannot afford. Measured on a 1.2 million-cell grid: storing the names costs ~33 MB, against 8 bytes for this. That matters here specifically - a GridHabitat's active mask was deliberately squeezed from 10.3 MB to 0.14 MB for the same reason, and getspeciesstorage exists because these runs are bound by memory. Nothing in the simulation reads a cell's name; only output does.
Fields
grid: theStudyGridthe names describe.
EcoSISTEM.CircleMaskSpec — Type
CircleMaskSpec(; radius, centre = nothing)A circular active-area mask: the cells within a given distance of a point are simulated and the rest are not. Resolved onto the grid when the habitat is built.
Arguments
radius: how far the circle reaches, as a physical distance (100.0km) rather than an angle.centre: where it is centred, as aLatLong. Defaults to the grid's own centre - and on a synthetic grid, which has no real-world coordinates, that default is the only thing supported, since a geographic centre could not be placed.
EcoSISTEM.ClimateMoisture — Type
ClimateMoisture <: ClimateMoistureAxis - climate moisture index, precipitation minus potential evapotranspiration (Climate cmi, BioClimPlus cmi_max/mean/min; mm/day).EcoSISTEM.ClimateMoistureAxis — Type
ClimateMoistureAxis <: WaterAxis - climate-moisture-index niche axes (level and range).EcoSISTEM.ClimateMoistureRange — Type
ClimateMoistureRange <: ClimateMoistureAxis - annual range of the monthly climate moisture index (BioClimPlus cmi_range; mm/day).EcoSISTEM.ClimateRaster — Type
ClimateRaster{Source, Code, Array} <: AbstractClimateType for climate data derived from RasterDataSources.
Fields
array is the grid itself, a DimensionalData array over (Y, X) - plus a third dimension for a multi-layer or monthly read. Prefer to operate on the raster rather than reaching for this: a raster broadcasts and yields a raster, so lc .!= code and sum(bands) work directly, which is what lets a ConstructedRasterSpec combine avoid naming an array type at all.
code is the layer this holds, when it is one identifiable layer of its source - or nothing for a whole-dataset read or a raster derived by arbitrary arithmetic. It is what lets a materialised layer still be looked up in the shipped table, which iscategorical needs to know whether resampling it may interpolate: the answer lives in the ValueType column, per layer, and a source type alone cannot supply it (BioClimPlus holds all three value types at once).
Write it however reads best - 4, :bio4 or "bio4" - and it is stored as the one spelling that dataset prefers, via _preferredcode. So two rasters of one layer always compare equal, and a code naming no layer is refused here rather than surfacing later.
There is deliberately no valuetype field. Whether the values are class codes or measurements is a property of the layer's niche axis, and the axis lives on the spec that declares what the layer means - see iscategorical. A copy stored here could contradict it, which is the one thing a declaration must not be able to do.
EcoSISTEM.ClimateTypology — Type
ClimateTypology <: TypologyAxis - categorical climate-classification classes (BioClimPlus kg0-5: Köppen-Geiger, Wissmann, Thornthwaite, Troll-Pfaffen).EcoSISTEM.CloudCover — Type
CloudCover <: CloudCoverAxis - total cloud cover (Climate clt, BioClimPlus clt_max/mean/min; dimensionless).EcoSISTEM.CloudCoverAxis — Type
CloudCoverAxis <: NicheAxis - cloud-cover niche axes (level and range).EcoSISTEM.CloudCoverRange — Type
CloudCoverRange <: CloudCoverAxis - annual range of the monthly total cloud cover (BioClimPlus clt_range; dimensionless).EcoSISTEM.CombineOnSourceGrid — Type
CombineOnSourceGrid <: AbstractCombineStageCombine on the layers' own shared grid first, and sample the result onto the study grid.
Needed whenever the combine does not commute with regridding: one that looks beyond its own cell (a neighbourhood, a crop, an aggregation), and equally one that is cell-wise but nonlinear, since the ratio of two interpolations is not the interpolation of the ratio. Growing-season rainfall gsp / gsl is the case that matters: divided early it is a mean daily rate, divided late a total over a mean season length, and those are different quantities.
The layers must share one native grid, checked when they are read - combining across datasets of different resolutions has no meaning before either is resampled.
EcoSISTEM.CombineOnTargetGrid — Type
CombineOnTargetGrid <: AbstractCombineStageSample every layer onto the study grid first, and combine there - the default, and right whenever the combine commutes with regridding. It is what keeps compress_landcover interpolating the per-class percentages it is given rather than argmaxing them first and interpolating between the resulting class codes, which is meaningless.
EcoSISTEM.CombinedChange — Type
spec1 + spec2
EcoSISTEM.CombinedChange(specs...)Declare that a layer carries several changes at once, added together - a stored monthly series plus a multi-year trend, say, where the trend offsets the whole seasonal pattern.
Write it as a sum. That is the spelling this exists for, and the only one most callers need:
ReplaceWith(SeriesChange(monthly)) + IncrementBy(0.02K / year)CombinedChange is the type a sum builds, and is supported (though unexported, so it needs qualifying) for the case a + chain cannot express - combining a collection whose length is not known when the code is written:
EcoSISTEM.CombinedChange(specs...) # rather than `reduce(+, specs)`Either way the parts are summed as functions of elapsed time, not applied one after another; see SumOfLayerChanges for which combinations are meaningful.
EcoSISTEM.CombiningFit — Type
CombiningFit{A, F, C <: NamedTuple} <: AbstractNicheFit{A, C}Several nichefits, one per environmental layer, together with the function that combines their per-layer suitabilities into the cell's one suitability. The fits are held by name in a NamedTuple, and must line up name for name with the regime and tolerance collections they are matched against; a Tuple is accepted and named by each member's own niche axis.
combine is handed the whole NamedTuple of results, not folded across them as a binary operator, so a rule that treats layers differently is expressible and reads by name:
CombiningFit((summer = ..., winter = ..., moisture = ...)) do s
return (s.summer + s.winter) * s.moisture
endMultiplicativeFit and AdditiveFit are the two everyone actually uses, and are aliases for combine = prod and combine = sum; over a tuple those are themselves unrolled folds, so they cost exactly what the */+ of the fixed-arity fit types cost.
EcoSISTEM.Condition — Type
Condition <: RoleWhat a cell is like - temperature, rainfall, land cover, elevation.
A condition is a state, not a stock. Every species in the cell experiences the same value; nothing is divided between them and nothing is used up. What varies is how well each species copes, which is what its AbstractTolerance says: a species with a narrow tolerance does well over a small range of the condition and poorly outside it.
Conditions therefore set where a species can persist. They do not, by themselves, limit how many individuals a cell can hold - that is what a Resource does.
EcoSISTEM.ConstantAccumulationPeriod — Type
ConstantAccumulationPeriod(duration)One fixed interval for the whole layer - year for a heat sum, month_mean_duration for a layer whose month is unknowable. The stock->rate conversion is then a constant scale factor.
Fields
duration: the interval itself, as aUnitful.Units- what an accumulated value is divided by to become a rate.
EcoSISTEM.ConstructedRasterSpec — Type
ConstructedRasterSpec(combine, layers...)The universal lazy escape hatch: read each of layers onto the working grid, then apply combine to the resulting rasters. Because combine is the first argument it can be written as a do-block:
ConstructedRasterSpec(EarthEnv{LandCover}, :open_water) do water
water .< 50 # a mask of cells less than half open water
endlayers are given as alternating dataset, code(s) - a RasterDataSources type followed by an Int/Symbol code, a vector/tuple of codes (several layers), or no code (a bare dataset => all its layers, e.g. every land-cover class band, passed to combine as one multi-band raster); a pre-built spec is also accepted directly - including a synthetic one, so a combine may mix generated layers with read ones. A bare dataset becomes a whole-dataset spec. With no layers, combine is a nullary thunk that produces the layer itself (reading a source directly, or wrapping a literal in-memory array).
combine takes rasters and must return a raster - one contract, whichever way the spec is later used, because that decision is made elsewhere and cannot be known where the combine is written. A mask is simply a raster whose element type is Bool, so the element type still distinguishes the two; only the container is fixed.
Nothing has to be wrapped or unwrapped to satisfy that: a raster broadcasts and yields a raster, as the example above shows, and sum(bands) over a multi-band combine does the same. So a combine names no array type at all, which is the point - the array type is an implementation detail, and a combine is user code.
Usable as a regime/supply layer or an active mask. Covers what the other specs don't: bespoke data, derived layers (anomalies, blends) and thresholded/combined masks. See hasdata and landcoverclass for ready-made combine building blocks. No data is read or downloaded at construction - only when materialised onto a grid (GridHabitat), mirroring SourceSpec; each layer's unit/axis is resolved from the shipped table eagerly, so an invalid code errors here rather than at materialise time.
combinestage says when combine runs - after its layers are put on the study grid (CombineOnTargetGrid, the default) or before (CombineOnSourceGrid). See AbstractCombineStage for which a given combine needs.
Fields
combine: the rule itself - a function taking one raster per layer (none, for a thunk) and returning a raster.layers: the child specs to materialise and hand it, already normalised; empty for a thunk.combinestage: when the combine runs, as above.
axis is a type parameter rather than a field, as on SourceSpec - and on this type it is the only statement of what the result means, since a derived raster has no layer code to resolve one from. That includes whether the result holds class codes: there is no valuetype keyword, because a TypologyAxis says the values are class labels and so must be resampled by nearest class, while any other axis says they may be interpolated. A separate declaration could only agree with the axis or contradict it.
EcoSISTEM.ConstructedShapeSpec — Type
ConstructedShapeSpec(operation, members...; coverage = AllTerritories(), outline = true)Combine several named regions into one mask - the union of the United Kingdom, Ireland and the Isle of Man, or a country with an island group cut out of it.
Regions combine as geometry, so the result is exact and carries no resolution of its own: the grid is still decided afterwards, and nothing is rasterised twice.
# The British Isles, including Shetland - which Natural Earth's own polygon of that name omits
ConstructedShapeSpec(ShapeUnion(),
NaturalEarthSpec("United Kingdom", coverage = AllTerritories()),
NaturalEarthSpec("Ireland", level = "ADMIN"),
NaturalEarthSpec("Isle of Man", level = "ADMIN"),
coverage = LandmassesAbove(1km^2)) # ...and without RockallArguments
operation: how they combine -ShapeUnion,ShapeIntersectionorShapeDifference, the last taking every later member away from the first.members: two or more region specs, eitherNaturalEarthSpecs or nestedConstructedShapeSpecs.coverage: which components of the result to keep, applied after the operation -AllTerritoriesby default, since a combination usually means all of what it built.outline: asNaturalEarthSpec-falseactivates the result's bounding box instead of its outline.
EcoSISTEM.ContinuousLayer — Type
ContinuousLayer{R <: Role, A <: NicheAxis, V <: Number, Arr <: DimensionalData.AbstractDimArray{V, 2}, S <: Unitful.Quantity}A continuous (numeric) grid layer of role R on niche axis A, holding a value matrix (eltype V) as a DimArray over (Y, X) - real Projected/Sampled lookups for a data-driven source, NoLookup for a synthetic one (see data/architecture.md).
A layer holds one grid of values, never a stack of them: a time-varying layer holds the values current now and carries a SeriesLayerChange as its change, which decides from elapsed time which stored slice that is. The array bound says 2 to keep it that way - the stack and the cursor that walked it were what made a layer's own state ambiguous.
EcoSISTEM.ContinuousRegime — Type
ContinuousRegime{V} - a static continuous regime (a `Condition`-role [`ContinuousLayer`](@ref) over a `(Y, X)` `DimArray{V}`).EcoSISTEM.ContinuousTolerance — Type
ContinuousTolerance{A, V <: Number} <: AbstractTolerance{A, V}A species' preference along a continuous niche axis, where suitability falls off with distance from an optimum rather than being a matter of membership. NicheTolerance is the concrete type; the matching layer is a ContinuousRegime.
EcoSISTEM.CumulativeHeat — Type
CumulativeHeat <: TemperatureAxis - accumulated growing degree-days above a threshold (BioClimPlus gdd0/gdd5/gdd10; K*day).EcoSISTEM.Cylinder — Type
Cylinder = EdgeTopology{Bounded, Periodic}A cylindrical grid: the east-west (X) edges join, the north-south ones do not. The parameter order is {Y, X}, so Bounded comes first - X is the axis that wraps.
On a grid with a real-world position a wrapping X is right only where the grid spans the whole longitude sweep, and is warned about otherwise. Where it does span it, Cylinder is exact rather than an approximation, and it is the only wrapping topology that can be: a wrapping Y is never right, because latitude does not wrap however wide the grid.
EcoSISTEM.DatedSeries — Type
DatedSeries(start::Dates.TimeType)Slices carry real dates, start being the first slice's. The epoch places the series directly: the slice current at elapsed zero is the one covering the epoch's own date.
Inferred from a source whose Ti lookup holds Dates values, so it is rarely written by hand.
EcoSISTEM.DayAxis — Type
DayAxis <: NicheAxis - day-based phenology niche axes (day-of-year positions and day counts; day).EcoSISTEM.DayCount — Type
DayCount <: DayAxis - a number of days: growing-season length, snow-cover days or days above a threshold (BioClimPlus gsl/scd/ngd*; day). Counts days rather than measuring a spread, so deliberately not named `*Range` as every genuine max-min axis is.EcoSISTEM.DayOfYear — Type
DayOfYear <: DayAxis - an ordinal day-of-year: first/last growing day or first/last day above a degree-day threshold (BioClimPlus fgd/lgd/gdgfgd*/gddlgd*; day).EcoSISTEM.Deactivate — Type
Deactivate() <: AbstractOperationDestroy the region's cells: everything living there dies, and nothing grows there again until the cells are reactivated.
Killing is the point, not a side effect. A deactivated cell is skipped entirely by the hot loop, so anything left in it would neither breed nor die - a frozen population with no ecological meaning. Left alive, stranded individuals come to outnumber the living, because they hold their numbers while the real population turns over around them.
Reactivate does not bring them back, and should not: it makes the cell habitable again so that dispersal can recolonise it, as vegetation returns to a slag heap once it stops being used.
EcoSISTEM.DefaultEcosystem — Type
DefaultEcosystemMarker selecting opt-in defaults for the builders. build_habitat(DefaultEcosystem(); ...), build_species(DefaultEcosystem(); ...) and build_ecosystem(DefaultEcosystem(); ...) fill any omitted required input from a defaults table - announcing each choice with an @info - then delegate to the strict builder. Use it to spin up a fully-parameterised runnable toy ecosystem, or to fill in only the required inputs you do not care about while passing the rest explicitly.
EcoSISTEM.Demand — Type
Demand{A <: NicheAxis, V, X} <: AbstractDemand{A, V}What each species takes from the shared pool on one niche axis - the Resource mirror of a tolerance, and one of the two halves that must line up with the environment.
Name the axis to build one, Demand{SolarRadiation}(values). The values are converted to that axis's own canonical resource unit - kJ/day for SolarRadiation, L/day for Precipitation, g/day for CarbonFlux - so any scale of the right dimension is accepted, while a wrong dimension, or an axis that declares no resource at all, is refused at the call rather than deep in the simulation loop.
Fields
resource: one demand per species, in the axis's canonical unit.exchange_rate: what a demand is measured against. Defaults to1/mean(resource), so a species' demand is read relative to the assemblage it is part of rather than as an absolute. It scales birth and death equally, so it sets the tempo of turnover without moving any equilibrium.
Type parameters
A: the niche axis these demands are stated on.V: the value type, which follows fromcanonicalunit(Resource, A).X: the exchange rate's type, the inverse ofV.
EcoSISTEM.DemandCollection2 — Type
DemandCollection2{M1, M2} - two positional demands. Deprecated plumbing: use [`SpeciesRequirementCollection`](@ref).EcoSISTEM.DerivedData — Type
DerivedData{S}Source of a raster computed from S but no longer S - the result of a ConstructedRasterSpec combine, or of an operation like compress_landcover that turns a dataset's layers into a quantity that is none of them. Summing eight land-cover bands does not give land cover, and what the result means comes from the spec's declared axis rather than from its inputs, so DerivedData{EarthEnv{LandCover}} records the lineage without claiming to be it.
Never write this type out - call _derivedfrom(S), which is what collapses nesting. Deriving from derived data is still just derived data, and no consumer asks how many steps there were; but DerivedData{DerivedData{S}} stays constructible, so the collapse is that function's job and not the type's.
S is a phantom parameter, never instantiated: it appears only as ClimateRaster's first type argument.
EcoSISTEM.DiversitySet — Type
DiversitySetDiversity measurements recorded from a CachedEcosystem over a run, held alongside the folder its cached abundances were written to.
Fields
data: the measurements so far, ormissingbefore any have been taken.folder: where the cached abundances live, which is also where results are read back from.times: every timepoint diversity is wanted at.gettimesnarrows this to the ones not yet computed.
EcoSISTEM.DiversitySet — Method
DiversitySet(cache::CachedEcosystem, times::Vector{T}) where T <: Unitful.TimeConstruct a DiversitySet from a CachedEcosystem, initialising it with the cache output folder and a vector of timepoints times for which diversity is to be recorded.
EcoSISTEM.ERA — Type
ERA <: EcoSISTEMSourceThe ERA5 reanalysis archive, as a data source. Read one with read(ERA, file, param), which returns a ClimateRaster{ERA}.
Fieldless: a source names where data came from, and the data itself lives in the ClimateRaster that carries it.
EcoSISTEM.EcoSISTEMSource — Type
EcoSISTEMSourceAbstract supertype of the sources this package defines itself, for rasters that come from no dataset - see SyntheticData and DerivedData.
EcoSISTEM.Ecosystem — Type
Ecosystem{Part <: AbstractHabitat} <:
AbstractEcosystem{Part, SL, NF}Ecosystem houses information on species and their interaction with their environment. For species, it holds abundances and locations, as well as properties such as trait information, spplist, and movement types, lookup. For environments, it provides information on environmental conditions and available resources,habitat. Finally, there is a slot for the nichefit between the environment and the characteristics of the species, nichefit. elapsed is the simulation clock (see simulationtime) and seed the seed the per-species RNG streams were derived from. epoch is the real date elapsed time zero corresponds to, or nothing for a run with no calendar - see simulationdate.
EcoSISTEM.Ecosystem — Method
```julia Ecosystem{Part <: AbstractHabitat} <: AbstractEcosystem{Part, SL, NF} ``` Ecosystem houses information on species and their interaction with their environment. For species, it holds abundances and locations, as well as properties such as trait information, `spplist`, and movement types, `lookup`. For environments, it provides information on environmental conditions and available resources,`habitat`. Finally, there is a slot for the nichefit between the environment and the characteristics of the species, `nichefit`. `elapsed` is the simulation clock (see [`simulationtime`](@ref)) and `seed` the seed the per-species RNG streams were derived from. `epoch` is the real date elapsed time zero corresponds to, or `nothing` for a run with no calendar - see [`simulationdate`](@ref).
```julia Ecosystem(spplist::SpeciesList, habitat::GridHabitat, nichefit::AbstractNicheFit) ``` Create an `Ecosystem` given a species list, an abiotic environment and trait nichefit. An optional population function can be added, `popfun`, which defaults to generic random filling of the ecosystem. A `seed` may be supplied to make the run reproducible: it deterministically seeds one random number generator per species (see [`makerngs`](@ref)), so results are identical regardless of the number of threads used. If no `seed` is given, one is drawn at random.
EcoSISTEM.Ecosystem — Method
Ecosystem(spplist::SpeciesList, habitat::GridHabitat,
nichefit::AbstractNicheFit)Create an Ecosystem given a species list, an abiotic environment and trait nichefit. An optional population function can be added, popfun, which defaults to generic random filling of the ecosystem. A seed may be supplied to make the run reproducible: it deterministically seeds one random number generator per species (see makerngs), so results are identical regardless of the number of threads used. If no seed is given, one is drawn at random.
EcoSISTEM.EdgeTopology — Type
EdgeTopology{BCY, BCX} <: AbstractTopology
EdgeTopology(; y, x)The topology of a rectangular grid: one AbstractBoundaryCondition per axis.
Three of the four combinations have names of their own - Torus, Cylinder and Island - and those are the usual way to write them. The keyword form is for the fourth, which has no ecological name.
Arguments
y: the boundary condition for the rows - northing on a projected grid - given as a type,EdgeTopology(y = Periodic, x = Bounded).x: the same for the columns, easting.
Type parameters
BCY,BCX: those two conditions, in that order.(y, x)throughout the package, matchingDimensionalData's ownY/Xdims.
EcoSISTEM.Encloses — Type
Encloses(x)Regions that completely contain x.
Answers "which named regions is my data inside?", and is the relation investigate_regions uses when none is named. It is the only one that accepts a point, since nothing can lie within a point and nothing overlaps one.
Arguments
x: what to ask about - a study area or its report, a raster, a layer, a habitat, an ecosystem, anExtents.Extent, aLatLong, or a match from an earlier report.
EcoSISTEM.EqualPop — Type
EqualPop{U <: Unitful.Units} <: AbstractParamsDemographic rates shared by every species: one birth rate and one death rate for the whole assemblage. equalpop expands it into a PopGrowth once the number of species is known.
Fields
birth,death: the rates, per unit time, the same for every species.longevity,survival: the two exponents described inAbstractParams.boost: the ceiling on the birth multiplier where resources are abundant.
EcoSISTEM.ErrorAtEnd — Type
ErrorAtEnd <: AbstractSeriesEnd - running past the last slice is an error. The default.EcoSISTEM.Evapotranspiration — Type
Evapotranspiration <: EvapotranspirationAxis - potential evapotranspiration (Climate pet, BioClimPlus pet_penman_max/mean/min; mm/day).EcoSISTEM.EvapotranspirationAxis — Type
EvapotranspirationAxis <: WaterAxis - evapotranspiration niche axes (level and range).EcoSISTEM.EvapotranspirationRange — Type
EvapotranspirationRange <: EvapotranspirationAxis - annual range of the monthly potential evapotranspiration (BioClimPlus pet_penman_range; mm/day).EcoSISTEM.EveryStep — Type
EveryStep() <: AbstractSchedule - fires on every timestep.EcoSISTEM.FrostChangeFrequency — Type
FrostChangeFrequency <: TemperatureAxis - frost change frequency, the number of days the temperature crosses 0 °C (BioClimPlus fcf; dimensionless).EcoSISTEM.Gauss — Type
Gauss{A, V} <: AbstractNicheFit{A, V}Gauss is deprecated and will be removed; use NicheSuitability instead (a Gaussian preference is the Normal case of a NicheTolerance). This shim shares NicheSuitability's 2-argument density functor and also retains the legacy 3-argument (current, opt, sd) Gaussian call for back-compatibility.
EcoSISTEM.GaussianKernel — Type
GaussianKernel(dist::Unitful.Length, thresh::Float64)A dispersal kernel whose distances are Rayleigh distributed - the two-dimensional case of dispersing a Gaussian displacement in each direction independently.
Fields
dist: the species' dispersal distance, converted to kilometres on construction.thresh: the probability below which a destination is dropped, which is what bounds the lookup table to a finite neighbourhood.
EcoSISTEM.GivenByUser — Type
GivenByUser <: AbstractDecisionSource - you supplied it.EcoSISTEM.GradientSpec — Type
GradientSpec{A <: NicheAxis, V}A layer whose value runs linearly across the grid.
The pattern is fixed in space and does not change of itself; wrap the spec in Varying to give it a change in time.
Arguments
low,high: the values at the two ends.lowmust be strictly less thanhigh.axis: the niche axis this layer is on, asUniformSpec. Required.orientation: which way the gradient runs, as a compass bearing clockwise from North.0°, the default, runs south to north;90°west to east;180°north to south; and so on for any bearing between. Must be a real angleQuantity-90°, or(pi/2)rad- since a bare number would be read as radians by Unitful's own counter-intuitive convention. Stored in degrees, so the type is not parametric on the angle unit.
EcoSISTEM.GridHabitat — Type
GridHabitat(; regime::Union{LayerInput, AbstractRegime},
supply::Union{LayerInput, AbstractSupply}, area::StudyArea,
topology::AbstractTopology = Island())Build an abiotic environment on an already-decided grid.
All three inputs are required. regime (the environmental Condition layer) and supply (the Resource layer) are each an AbstractSpec - a synthetic layer (UniformSpec/GradientSpec/PeakedSpec/NicheSpec), a SourceSpec, a ConstructedRasterSpec, or a tuple of 2-3 of these for a multi-variable environment. area is the StudyArea that decided the grid - its CRS, extent, cell size and active mask - which is where every geometric choice lives:
area = StudyArea(regime = cultivated, within = coastline, crs = EPSG(27700), cellsize = 5km)
env = GridHabitat(regime = cultivated, supply = sunlight, area = area)Use investigate_study_area first to see the grid, what it costs each layer and what it warns about, before committing to it. Omitting a required input errors - use build_habitat to fill omissions with announced defaults.
The area fixes the frame; the layers can only shrink activity. Nothing here chooses a grid: this samples regime and supply onto the area's, and where a layer has no data the cell is marked inactive. A layer that was not named when the area was decided can therefore remove cells but never move or resize the grid - so the area you inspected is the area you get - and doing so warns. Name a layer in StudyArea(...) if you want it to shape the grid; omit it and it can only subtract.
This is the type's only constructor. A habitat is described by the layers it should have and the grid they sit on; there is no form taking already-assembled parts, so new is reachable from exactly one place.
Fields
regime: the Condition layer(s) of typeH- what each cell is like.supply: the Resource layer(s) of typeB- what each cell provides.active: a boolean(Y, X)DimArraymarking which cells are simulated.topology: how the grid's edges join - seeEdgeTopology.area: theStudyAreathis habitat sits on, carrying both theStudyAreaReportit was built from - stampedAsBuiltand refined by whatever the build changed - and theStudyGridit was actually built on. The report'sactiveis the mask the habitat started with, so comparing it against the liveactiveabove says what the simulation has done since.
EcoSISTEM.GridLandscape — Type
GridLandscapeAn ecosystem's abundances: how many individuals of each species are in each cell. The same numbers are held under two names, as two views of one block of memory, because the simulation asks two different questions of them - the hot loop walks species against flat cells, while inspecting or seeding a run wants to say where.
Immutable, and that is what makes the two views agree: the only way to change shape is to build a new GridLandscape and reassign the whole field holding it, so they cannot drift apart.
Fields
matrix: species against flat grid cell, with noY/Xstructure - the per-timestep access pattern, and a plainMatrix{Int64}.grid: species againstYandX, a plainArray{Int64, 3}sharingmatrix's memory.dimmatrix:matrixas a(Dim{:species}, Dim{:location})DimArray, carrying real species names and, for each flat cell, its extent -[0.0, 1.0) x [0.0, 1.0) km.dimgrid:gridas a(Dim{:species}, Y, X)DimArray, withYandXthe habitat's own dimensions - real coordinates asUnitfullengths, or degrees on a geographic grid.
dimmatrix's cell descriptors are computed on demand from the grid rather than stored: the lookup holds a grid reference and nothing else, so it costs the same few bytes whether the grid has a hundred cells or a million. Selecting by descriptor scans, so it suits inspection rather than bulk work; dimgrid's Y and X are Sampled and select directly.
The raw arrays and the labelled views are the same memory, and both are stored on purpose. The hot loop reads matrix; asking which species or where reads dimmatrix/dimgrid.
The raw fields are what make the hot loop free, and the reason is not obvious. Ecosystem declares abundances::GridLandscape - the bare UnionAll, an abstract field. Julia can still infer a field of that container concretely provided the field's declared type does not mention the type parameters, which is exactly why matrix::Matrix{Int64} is written out rather than left as one of the parameters. Measured: reaching the labelled view through the abstract field costs about 176 bytes per cell and grows with the grid; reading the raw field is 0. Declaring these two fields in terms of Am/Ag would silently undo that.
EcoSISTEM.GridLandscape — Method
GridLandscape(sl::SavedLandscape, names::Vector{String}, grid::StudyGrid)Restore a GridLandscape from a SavedLandscape, putting its bare abundance matrix back onto dimensions.
Arguments
sl: the saved abundances.names: the species names, from the ecosystem being restored into.yx: that ecosystem'sYandXdimensions.
The saved random number streams are restored separately, by the caller that already holds the ecosystem to put them in.
EcoSISTEM.GrowingSeasonPrecipitation — Type
GrowingSeasonPrecipitation <: WaterAxis - precipitation accumulated over the growing season (BioClimPlus gsp; L*m^-2).EcoSISTEM.Heterogeneity — Type
Heterogeneity <: NicheAxis - spatial habitat-heterogeneity metrics of EVI (EarthEnv HabitatHeterogeneity; dimensionless).EcoSISTEM.HoldAtEnd — Type
HoldAtEnd <: AbstractSeriesEnd - the last slice persists for the rest of the simulation.EcoSISTEM.HumidityAxis — Type
HumidityAxis <: WaterAxis - atmospheric-water niche axes (vapour pressure, its deficit, relative humidity).EcoSISTEM.IncrementBy — Type
IncrementBy(shape)Declare that shape's values are rates: they are accumulated into the layer, in its unit per unit time.
Arguments
shape: a rate, in the layer's unit per unit time. This is the one recipe that accepts a bare constant, which gives a steady drift.
EcoSISTEM.Intervention — Type
Intervention(schedule, region, operations...)A declared change to the ecosystem - as against an AbstractLayerChange, which changes a single layer. The parts answer when (AbstractSchedule), where (AbstractRegion) and what (AbstractOperation):
Intervention(AtTime(50year), RandomCells(20), Deactivate())
Intervention(EveryStep(), AllCells(), SetChange(:rainfall, IncrementBy(-0.1mm/day/year)))Several operations share one resolved region, applied in the order written - clear an area and plant a crop on it, or reactivate a site and restock it:
Intervention(AtTime(10year), RandomCells(20), Deactivate(), AddAbundance(:wheat, 500))That sharing is the whole reason for the varargs, and it cannot be had from two interventions in a set: each resolves its own region, and a random one draws its own cells from its own stream (k is its index in the set), so two RandomCells(20) would pick different cells. A region that must be acted on twice has to be resolved once.
Pass one, or an InterventionSet, as simulate!'s intervention keyword.
EcoSISTEM.InterventionSet — Type
InterventionSet(interventions...)Several Interventions applied in the order written, every step. Any number of them, of any kinds, including several of the same kind.
EcoSISTEM.IsRasterData — Type
IsRasterData{X}Trait marking a type as one that may name a raster's data source.
Marking an abstract type covers its whole subtree, so RasterDataSources' hierarchy and this package's own each take one line. A third party's raster type needs one @traitimpl line and no change here, which is the point of a trait rather than a supertype bound.
EcoSISTEM.Island — Type
Island = EdgeTopology{Bounded, Bounded}A grid with hard edges: neither pair joins. The default on every grid.
A step past an edge is treated exactly as a step into a dead cell, so what becomes of it is answered per species by disperse_safely. With its default of true the blocked weight is redistributed among the reachable destinations, making the edge reflecting rather than absorbing.
EcoSISTEM.Isothermality — Type
Isothermality <: TemperatureAxis - isothermality, 100 * (mean diurnal range / annual range) (BioClim 3; dimensionless).EcoSISTEM.LandCoverTypology — Type
LandCoverTypology <: TypologyAxis - categorical land-cover / land-use classes (EarthEnv LandCover 1-12).EcoSISTEM.LandmassesAbove — Type
LandmassesAbove(threshold)Take every connected piece of ground the name covers that clears threshold.
This is the coverage for "everything except the specks": the United Kingdom without Rockall, which LargestLandmass can only express by counting components and so needs to know how many there are. Rockall is 0.031 km2 and the next smallest British component is 2.536 km2, an eighty-fold gap, so any threshold between them does the same thing.
Unlike the other coverages this one cannot be answered from the shipped region table, which records only the largest few components' sizes - so boundingbox refuses it, while a spec built onto a real grid has the geometry and can.
Arguments
threshold: how big a component must be to be kept, either as an area (1km^2,500u"m^2") or as a share of the region's own total (5percent, fromUnitful). A share is the more portable of the two, since what counts as a speck depends on how big the region is: the same1km^2keeps every part of Great Britain and discards most of the Maldives.A share must be written as a percentage rather than as a bare number.
0.05and5percentare the same quantity, but only one of them says which it means when read beside1km^2, and a bare number is refused for that reason.
EcoSISTEM.LargestLandmass — Type
LargestLandmass(count::Integer = 1)Take only the count largest connected pieces of ground the name covers.
Dissolving a selection and keeping its largest connected component is what turns "France" into France continentale, "United Kingdom" into Great Britain and "Scotland" into the Scottish mainland, without an area threshold or a hand-written list of exceptions. It is the largest component rather than the largest part: components are measured after neighbouring features have been merged, so a continent comes out as its mainland rather than as its largest country.
A landmass selected this way cannot cross the antimeridian, because Natural Earth splits its polygons at the date line and so no single connected component spans it.
The count is a keyword rather than a positional argument, unlike the sibling RandomCells and SpreadingCells. Those name a plural, so a bare number attaches to it and RandomCells(20) reads as twenty cells; this one names a single landmass, so a bare number would attach to nothing and could as easily be read as an ordinal. Naming it at the call site is what says which was meant.
Arguments
count: how many components to keep, largest first. Acountbeyond the number of components returns all of them, soLargestLandmass(count = 2)on a single-component region is the region.
EcoSISTEM.LatLong — Type
LatLong(lat, long)
LatLong(; lat, long)A geographic point in Unitful degrees, validated on construction: LatLong(50.0°, -3.0°). Latitude must lie in [-90°, 90°] and longitude in (-180°, 180°].
A region is an Extents.Extent rather than one of these - Extent(Y = (54.6°, 58.7°), X = (-6.2°, -1.8°)). That is the bounding-box vocabulary the whole Julia geo ecosystem shares, and reusing it beats a parallel type of our own.
Reach the components with getlat and getlong. It implements the GeoInterface PointTrait, with the usual X = longitude, Y = latitude order, stripped to plain degrees.
EcoSISTEM.LayerAggregated — Type
LayerAggregated(factor)The layer is combined factor source cells to a target cell - still exact, no interpolation.
EcoSISTEM.LayerCache — Type
LayerCache()Hold the raw source reads made while deciding a StudyArea, so that refining an area does not read the same layer twice.
Only raw reads are cached, never anything reprojected onto a grid, which would be wrong to reuse for a different area. Downloads are already cached on disk, so what this saves is decoding rather than fetching.
Fields
reads: the reads so far, keyed by what determines their content.
EcoSISTEM.LayerCollection — Type
LayerCollection{R <: Role, A, C <: NamedTuple}Several layers of the same role R over one grid (e.g. temperature + rainfall) and over the axis structure A, held by name in a NamedTuple, (Temperature = ..., Precipitation = ...). Sub-layer types stay concrete in the backing's own type, so the hot loop is exactly as type-stable as the fixed-arity named fields it replaces, and the arity is limited only by what the caller writes.
Layers are named by their axis, so a Tuple is accepted and named for you; two layers on the same axis cannot be told apart that way and are refused, asking for explicit names.
Layers are reached through the standard container interface - lc.Precipitation, lc[1], lc[:Precipitation], keys, values, pairs, iterate, length, merge and NamedTuple(lc), all forwarded to the backing (src/collections.jl). A single layer answers identically, as a one-member container.
EcoSISTEM.LayerKeptExactly — Type
LayerKeptExactly <: AbstractLayerFate - the layer is copied onto the grid, cell for cell.EcoSISTEM.LayerPlan — Type
LayerPlanOne layer's place in a study area: where it is, and what the chosen grid costs it.
Fields
name: the layer's name.crs,step,bounds: where the layer is, in its own coordinates. Stated that way so that the three agree with each other and are exact - an extent re-expressed in a distant CRS need be neither.kind: what the target grid does to it, as anAbstractLayerFate, which carries the aggregation factor or the reason for resampling along with it.
EcoSISTEM.LayerRecord — Type
LayerRecordA single layer's catalogue entry: its dataset (the table basename, e.g. :BioClim), code aliases (the ;-separated Code, e.g. ["1", "bio1"]), name, definition, physical unit (NoUnits if dimensionless), axis (a NicheAxis type, or nothing if unclassified), the sources that provide it (the full list of supporting RasterDataSources), the numslices the code expands to, its temporal native reporting period - a genuine Unitful.Units time unit (day/month_mean_duration/year), or nothing for a static/non-time-varying value - its valuetype, and its category. Returned by layerinfo / layersbyaxis.
category says what kind of quantity the layer is - :instantaneous, :range, :rate, :count, :stock, :balance or :categorical - which is a different question from valuetype and not derivable from it. It is the only machine-readable record of the rate-vs-level distinction, the one canonicalunit(::Type{<:Precipitation}) got wrong.
publishedscale is the factor a provider ships the layer at when that is not the documented one - 100 for bio4 and 10 000 for the fourteen HabitatHeterogeneity layers, blank everywhere else. It is divided out on read, so values arrive at the order of magnitude the source's own documentation claims. It lives in the catalogue rather than in code deliberately: the correction is then visible to layerinfo as documentation and applied as behaviour, instead of being buried in a reader. The test guarding it is inverted - it fires when the upstream data is repaired, since a test asserting the data is still broken is what tells us the workaround can go.
The remaining fields carry the rest of the shipped table so that no column is dead data: officialunit (the source's own documented unit string, against which unit is our Unitful reading), notes, and the file-specific group (BioClimPlus) and order (HabitatHeterogeneity), each nothing where the table has no such column. UnitDimension is deliberately validated rather than stored, because it duplicates dimension(unit) and could only drift.
Two columns have been removed from the shipped tables outright, on the same reasoning: a column that cannot disagree with what we already know is not a check, it is a second place to get wrong. IsRate said exactly category === :rate in all 139 rows. LandCover's Filename (full version)/(reduced version) held consensus_full_class_N.tif / Consensus_reduced_class_N.tif - precisely what RasterDataSources' own rastername computes from the class number, down to its odd lower/upper-case asymmetry, so we were duplicating another package's convention and would not have noticed it changing.
period is the interval the value accumulated over - an AbstractAccumulationPeriod, or nothing where none applies. It is a different question from temporal: temporal is how often the layer is sampled, twelve monthly slices, while period is what each value accumulated over. For prec those are both months and the difference does not show; for srad they differ, sampled monthly and accumulated per day; and for a single-slice layer such as bio13 there is no sampling at all.
valuetype is :categorical, :discrete or :continuous, and the distinction that matters is categorical against the other two, not the names' everyday senses: a :discrete layer (a day-of-year, or a count of growing-degree days) is an ordinary number that may be averaged, while a :categorical one is a class code - Köppen-Geiger and friends, kg0-kg5, the only six in the shipped tables - where the arithmetic mean of two classes is meaningless. Anything resampling a layer must therefore pick nearest-class (:mode) for :categorical and may interpolate the rest.
So :discrete is descriptive metadata, not a switch: every consumer in the package tests === :categorical, and nothing anywhere reads :discrete. It is kept because it is honest about the source data - gsl really does count whole days - but a three-way column is a two-way split in practice, and a layer marked :discrete becomes an ordinary ContinuousLayer that is interpolated like any other number. Do not add behaviour keyed on it without deciding that question first.
EcoSISTEM.LayerResampled — Type
LayerResampled(reason)The layer is interpolated onto the grid, introducing uncertainty - the thing the whole alignment story exists to avoid. reason says why it was unavoidable.
EcoSISTEM.LegacyLoss — Type
LegacyLoss{V} <: AbstractLayerChange{NoChange}Carries the loss rate of the deprecated HabitatLoss change function. Its mode is NoChange: the rate is a plain per-time probability, in no way the layer's own unit.
Transitional, and not a layer change at all. Habitat loss mutates the ecosystem - supply and abundances - from a layer's change slot, and draws randomly while doing it, so it satisfies neither invariant the other changes do. It survives only to keep HabitatLoss callable, and is superseded by an explicit cell-deactivating intervention.
EcoSISTEM.LongTailKernel — Type
LongTailKernel(dist::Unitful.Length, shape::Float64, thresh::Float64)A dispersal kernel with a heavier tail than GaussianKernel's, so that rare long-distance dispersal is not effectively impossible.
Fields
dist: the species' dispersal distance, converted to kilometres on construction.shape: how heavy the tail is. Smaller values reach further.thresh: the probability below which a destination is dropped, which is what bounds the lookup table to a finite neighbourhood.
EcoSISTEM.Lookup — Type
LookupOne species' dispersal neighbourhood, precomputed once and read by the hot loop: every destination its kernel can reach, as an offset from the source cell, with the probability of landing there.
The last two fields are scratch, rewritten on every cell of every timestep. Holding them here rather than allocating them per call is what keeps the movement step allocation-free.
Fields
y,x: the destination offsets, relative to the cell dispersing. In that order, as everywhere else in the package.p: the kernel's probability for each, fixed for the run.pnew: those probabilities renormalised over the destinations actually available from this cell.moves: how many individuals go to each destination this step.
EcoSISTEM.MPIEcosystem — Type
MPIEcosystem{MPIGL, Part, SL, NF} <: AbstractEcosystem{Part, SL, NF}An Ecosystem whose abundances are distributed across MPI ranks; EcoSISTEMMPIExt supplies the concrete MPIEcosystem.
Only the abundances are split. The habitat, species list and nichefit are held whole on every rank, and four extra fields record which slice of the work this rank owns.
Fields
abundances: the distributedMPIGridLandscape, in place of aGridLandscape.sppcounts,firstsp: how many species each rank holds, and the first one this rank holds.sccounts,firstsc: the same two, for grid cells.spplist,habitat,nichefit,lookup,cache,rngs,elapsed,seed,epoch: asEcosystem, and identical on every rank. Theepochmust be, or layers built redundantly per rank could phase their series differently.
Type parameters
MPIGL: theMPIGridLandscapetype holding the abundances.Part,SL,NF: habitat, species list and nichefit, asAbstractEcosystem.
EcoSISTEM.MPIGridLandscape — Type
MPIGridLandscapeAn MPIEcosystem's abundances, distributed across MPI ranks; EcoSISTEMMPIExt supplies the concrete MPIGridLandscape{RA, NT}.
The same abundances are held twice, partitioned two different ways, because the simulation needs a different split at different moments - demographics is per species, dispersal is per cell. The synchronise steps copy between the two views.
Fields
rows_matrix: this rank's species over all grid cells.cols_vector: all species over this rank's grid cells, flattened.reshaped_cols:cols_vectorseen as one species-by-cell view per MPI block, which is what the collective operations address.rows_tuple,cols_tuple: how each view is partitioned -total,first,last, and the per-rankcounts.dimgrid: the species this rank owns, by name, against the habitat's realYandX.rows_matrixcovers every cell, so the map is complete and the coordinates mean what they say.dimcols: every species, by name, against the global indices of the cells this rank owns.cols_vectoris stored one block per contributing rank, because that is what the collective produces; this presents those blocks as a single ordinary matrix without copying. Those cells are a run of the flat ordering rather than a rectangle, so there is noY/Xview of them.
One labelled view per partition, each in the shape that partition naturally has - there is no flat twin of dimgrid, because unlike a serial landscape, which has two raw arrays and gives each a counterpart, this side has only rows_matrix. They matter more here than they do serially, where the matrix simply is the whole run: a rank holds only a slice, and these say which one. They are views of the same memory, so a write through either is seen by the raw fields and vice versa.
The raw fields are what the simulation uses. A scalar index into dimcols has to find its block first, which is markedly slower than walking reshaped_cols, so it is for inspection rather than for the loop.
EcoSISTEM.MeasuredAcrossProjection — Type
MeasuredAcrossProjection <: AbstractDecisionSource - a cell size measured across the projection, no layer being in the target CRS.EcoSISTEM.MonthOfYearSeries — Type
MonthOfYearSeries()Slices are months of the year with the year unknown - a monthly climatology. The epoch selects the slice matching its own calendar month, so a run beginning in July starts on the July slice rather than on slice one.
Matching is by month number, never by elapsed duration into the year. The slices are spaced by month_mean_duration (30.44 d), so six of them reach day 182.6 while the real 1 July is day 181 - proportional matching would land a July epoch on the June slice.
EcoSISTEM.MultiplicativeFit — Type
MultiplicativeFit{A, C} - a [`CombiningFit`](@ref) whose per-layer suitabilities are multiplied.EcoSISTEM.MultiplicativeFit2 — Type
MultiplicativeFit2{M1, M2} - two positional nichefits, multiplied. Deprecated plumbing: use [`MultiplicativeFit`](@ref).EcoSISTEM.MultiplicativeFit3 — Type
MultiplicativeFit3{M1, M2, M3} - three positional nichefits, multiplied. Deprecated plumbing: use [`MultiplicativeFit`](@ref).EcoSISTEM.NaturalEarthLevel — Type
NaturalEarthLevelOne kind of named region: which Natural Earth file defines it, and which attribute of that file carries the name.
Levels are what make a name unambiguous. "Africa" is a cultural CONTINENT of 55 countries and a UN REGION_UN of 62, with different members and different extents, so a name is always looked up at a stated level.
Fields
name: the level's own name, as it is written in the shipped region table.dataset: the Natural Earth file it comes from, without the.zipextension.category:"cultural"or"physical", the source's own division and the directory it publishes each file under.field: the attribute of that file whose values name a region at this level.kind: what sort of division it is -:political,:statistical,:physicalor:code.description: what the level means, and where it is likely to surprise.within: an attribute and value restricting which features belong to this level, ornothingwhere the whole file does. The physical file holds every kind of landform in one layer, so its levels are distinguished this way.
EcoSISTEM.NaturalEarthSpec — Type
NaturalEarthSpec(name::AbstractString; level = nothing, coverage = AllTerritories(),
outline = true)Name an active-area mask as a named region - a country, a continent, an island - without reading anything. The polygons are fetched and cut to the grid when the spec is materialised, as for ShapeSpec.
The name is resolved against the shipped region table at construction, so a name that does not exist is an error where it was written rather than minutes later mid-build. It is resolved by exactly the rule boundingbox uses, which is what makes the box that function reports the box this spec's shape actually has.
Arguments
name: the region's name, matched case-insensitively but otherwise as Natural Earth spells it.level: which kind of region the name means -"ADMIN"for a country,"Physical Island"for a landmass;EcoSISTEM.naturalearth_levels()lists them. Only needed where a name means genuinely different ground at different levels, and the error says so when it does.coverage: how much of what the name covers to take -AllTerritories, the default and what the source itself means by the name, orLargestLandmassfor the principal landmass alone.outline:true, the default, activates only the cells whose centres fall inside the region.falseactivates every cell in the region's bounding box instead, which is the cheaper thing to want when the region is only being used to say where to work rather than to mask a coastline.
EcoSISTEM.NaturalEarthSpec — Method
NaturalEarthSpec(match::EcoSISTEM.RegionMatch; coverage = AllTerritories(), outline = true)Turn one match from investigate_regions into a spec, without naming it again.
A match already carries the level and the name, which is the whole of a spec's identity, so nothing is re-derived and the shape agrees with the box the report displayed.
A report cannot be converted, because it may hold several regions. Pick one first - only(report) asserts there was exactly one, first(report) takes the best by the report's own ordering, and report[i] takes a chosen one.
EcoSISTEM.NeverScheduled — Type
NeverScheduled() <: AbstractScheduleNever fires. For disabling an intervention without removing it from a set, so a configuration can keep its shape while one part of it is turned off.
EcoSISTEM.NicheAxis — Type
NicheAxisThe quantity being measured - Temperature, Precipitation, SolarRadiation - independent of the unit it arrives in and orthogonal to Role.
An axis is what makes a pairing meaningful: a species' tolerance for temperature is matched against the temperature regime and nothing else. Both sides of the model carry one, so an AbstractLayer and the AbstractSpeciesRequirement it is matched against name the same axis, and a mismatch is a type error rather than a silent comparison of unrelated quantities.
Paired axes must be identical, not merely compatible: a SoilTemperature tolerance does not meet a Temperature regime.
Extend it with @nicheaxis. Related axes are grouped under an abstract intermediate named ...Axis (TemperatureAxis, WaterAxis) that carries their shared interface.
EcoSISTEM.NicheSpec — Type
NicheSpec{A <: NicheAxis}A categorical layer of randomly assigned niche classes - the synthetic counterpart of a land cover map.
Arguments
n: how many distinct classes to draw from.axis: the niche axis this layer is on. Required.
EcoSISTEM.NicheSuitability — Type
NicheSuitability{A, V} <: AbstractNicheFit{A, V}The nichefit between a NicheTolerance continuous trait and its environment: the density of the trait's response distribution evaluated at the current regime value, parameterised on any V. Works for any Distributions.ContinuousUnivariateDistribution (e.g. Trapezoid or Uniform).
EcoSISTEM.NicheTolerance — Type
NicheTolerance{A <: NicheAxis, V, D} <: ContinuousTolerance{A, V}One species' response along a continuous niche axis, as a built probability distribution: where on the axis it does best, and how sharply that falls away.
The distributions are built once, at construction, in a frame - the unit their support is measured in, which is also the tolerance's eltype and the unit the matching regime must be in. In the hot loop the NicheSuitability nichefit fetches one and evaluates its density at a bare number already in that frame, so there is no per-call conversion and no allocation.
Fields
dists: one distribution per species. Reach them withgetdist.
Type parameters
A: the niche axis.V: the frame the distributions are built in.D: the concrete distribution type, aDistributions.ContinuousUnivariateDistributionsuch asTrapezoid{Float64}orUniform{Float64}.
EcoSISTEM.NicheTolerance — Method
NicheTolerance(axis::Type{<:NicheAxis}, ::Type{D}, dist::Matrix; support = _defaultsupport(axis),
offset = nothing, scale = nothing, probes = ...)Build a NicheTolerance from a bare parameter matrix, one species per row.
Arguments
axis: the niche axis the tolerance is on.D: the response distribution type to build.dist: the parameters, one row per species, as bare numbers read in thesupportframe.support: the frame the distributions are built in - the unit their support is measured in, the tolerance'seltype, and the unit the matching regime must be in. Defaults to the axis's canonical unit.offset,scale: references insupport, which place a shape-only distribution such asBetaorLogNormalonto the dimensioned axis through aLocationScale.probes: howD's parameter roles are determined; seeparam_roles_resolved.
EcoSISTEM.NicheTolerance — Method
NicheTolerance(axis::Type{<:NicheAxis}, ::Type{D}, params::AbstractVector...; support = _defaultsupport(axis),
offset = nothing, scale = nothing, probes = ...)Build a NicheTolerance from one vector per parameter of the distribution - the programmatic counterpart of the matrix constructor:
NicheTolerance(Temperature, Normal, opts, vars) # a mu and a sigma vector
NicheTolerance(Precipitation, Gamma, shape, scale_vec)The vectors may carry units, and each is read according to its parameter's role - a location converted as a position, a scale as an interval, a shape left dimensionless. So support = K and support = °C build the same preference, expressed in each frame.
Arguments
axis: the niche axis the tolerance is on.D: the response distribution type to build.params: one vector per parameter ofD, each with one entry per species. All must share a unit, and all must be the same length.support: the frame the distributions are built in, as for the matrix constructor.offset,scale,probes: as for the matrix constructor.
EcoSISTEM.NoChange — Type
NoChange <: AbstractChangeMode - no values, and so no `changeunit`.EcoSISTEM.NoFitCategorical — Type
NoFitCategorical{A, V} <: AbstractNicheFit{A, V}The absence of a nichefit between a categorical trait and its environment, parameterised on its axis structure A and on any V. Returns the value 1.
EcoSISTEM.NoFitContinuous — Type
NoFitContinuous{A, V} <: AbstractNicheFit{A, V}The absence of a nichefit between a continuous trait and its environment, parameterised on its axis structure A and on any V. Returns the value 1.
EcoSISTEM.NoGrowth — Type
NoGrowth{U <: Unitful.Units} <: AbstractParamsDemographic rates for a population that does not grow. The same fields as PopGrowth, but the resource adjustment is short-circuited to zero, so births and deaths are taken at their stated rates and the environment does not modulate them.
Fields
birth,death: one rate per species, per unit time.longevity,survival: the two exponents described inAbstractParams. Carried so that the same parameters can be reused with a growing model, but not read while growth is off.boost: the ceiling on the birth multiplier where resources are abundant, likewise unread.
EcoSISTEM.NoLayerChange — Type
NoLayerChange <: AbstractLayerChange{NoChange} - the layer never changes.EcoSISTEM.NoMovement — Type
NoMovement{K <: AbstractKernel} <: AbstractMovementNothing disperses: every individual stays in the cell it was born in.
Fields
kernels: oneAbstractKernelper species, carried but never drawn from, so that a model can be switched between movements without rebuilding its species.
EcoSISTEM.NoMovement — Method
NoMovement{K <: AbstractKernel} <: AbstractMovementNothing disperses: every individual stays in the cell it was born in.
Fields
kernels: oneAbstractKernelper species, carried but never drawn from, so that a model can be switched between movements without rebuilding its species.
EcoSISTEM.NoRealWorldPosition — Type
NoRealWorldPosition <: AbstractDecisionSource - a synthetic area, with no real-world position for a CRS to describe.EcoSISTEM.OffsetBy — Type
OffsetBy(shape)Declare that shape's values are offsets from the layer's values as they stand when the change is attached - an interval, so K rather than °C on a temperature layer.
Arguments
shape: asReplaceWith, something that differs from step to step. A bare constant is rejected: a fixed offset applied every step is idempotent after the first, so it too is a one-off operation rather than a change.
EcoSISTEM.Overlaps — Type
Overlaps(x)Regions that share real ground with x.
Answers "which regions does my data reach into?". Sharing only a boundary does not count, which is the whole difference from a bare intersection test: a region touching your data along an edge contains none of it, and boundingbox(..., round = ...) snaps boxes onto a lattice, so that case is reachable rather than theoretical.
Arguments
x: asEncloses, but not a point - a point has no area to share.
EcoSISTEM.ParamRole — Type
ParamRoleAbstract supertype for the conversion role a distribution's parameter plays, which decides how a unit is attached to it.
The distinction is Unitful's affine one, and getting it wrong is silent. A location is a position on the axis, so LocationRole converts 12 °C to 285.15 K; a scale or a rate is an interval, so ScaleRole and RateRole leave a width of 12 °C as a width of 12 K rather than 285.15. A ShapeRole parameter is dimensionless and takes no unit at all.
EcoSISTEM.PatternedChange — Type
PatternedChange(amplitude, timescale; shape = sinusoidal)A shape of elapsed simulation time: amplitude * shape(elapsed / timescale).
Arguments
amplitude: whatshape's output is scaled by, and where the unit comes from.timescale: the elapsed time that maps to one unit ofshape's argument. The phase is not wrapped, so this is a period for a periodic shape and a transition width for a monotone one.shape: any function of a dimensionless phase - a sigmoid, a ramp, a step. Defaults tosinusoidal, one full cycle pertimescale.
Like SeriesChange this is a shape rather than a change in itself: the recipe wrapping it says whether its values are absolute, an offset or a rate.
EcoSISTEM.PatternedLayerChange — Type
PatternedLayerChange{M <: AbstractChangeMode, F, V, B} <: AbstractLayerChange{M}A change following an arbitrary shape of elapsed simulation time: the layer gets amplitude * shape(elapsed / timescale), read according to M. shape defaults to sinusoidal, one full cycle per timescale; a sigmoid, ramp or step function is equally valid.
The phase handed to shape is deliberately not wrapped into [0, 1). A sinusoid is periodic by itself so wrapping would gain nothing, while a sigmoid is not periodic at all and wrapping would destroy it. timescale is therefore the elapsed time mapping to one unit of shape's argument - a period for a sinusoid, a transition width for a sigmoid.
Under RelativeChange the pattern is added to baseline, captured from the layer when the change was attached so that the result stays a pure function of elapsed time rather than compounding on what the previous step wrote. The other modes leave baseline as nothing.
EcoSISTEM.PeakedSpec — Type
PeakedSpec{A <: NicheAxis, V}A layer whose value peaks - or dips - in the middle of the grid: inside at the centre, falling off to outside at each end.
As GradientSpec, the pattern is fixed in space; wrap the spec in Varying to give it a change in time.
Arguments
outside,inside: the values at the ends and at the centre. They must differ, or there is no peak.axis: the niche axis this layer is on. Required.orientation: which way the peak runs, with the same meaning and the same angle-Quantityrequirement asGradientSpec's.
EcoSISTEM.PerCellAccumulationPeriod — Type
PerCellAccumulationPeriod(code)The period is another layer, varying by cell - gsp (growing-season precipitation) accumulates over gsl (growing-season length). Written percell=gsl.
A trait cannot be converted without reading that layer, so a stock and a rate reading of such a value are genuinely different hypotheses rather than two spellings of one.
Fields
code: theCODE_TYPEof the layer holding the period -:gslforgsp. It names a layer of the same dataset, which is what makes the second read resolvable from the first.
EcoSISTEM.PerSliceAccumulationPeriod — Type
PerSliceAccumulationPeriod()Each time slice accumulated over its own calendar month, so slice 1 is January's 31 days and slice 2 February's. Written perslice=calendar_month in the shipped tables.
This is the case a single unit cannot express, and the reason the column is not simply a unit: a 12-slice monthly read has twelve different divisors, not one.
EcoSISTEM.Periodic — Type
Periodic <: AbstractBoundaryCondition - this axis wraps: its two edges join.EcoSISTEM.PopGrowth — Type
PopGrowth{U <: Unitful.Units} <: AbstractParamsDemographic rates given per species: the general form, and what the hot loop reads.
Fields
birth,death: one rate per species, per unit time.longevity,survival: the two exponents described inAbstractParams.boost: the ceiling on the birth multiplier where resources are abundant.
EcoSISTEM.Precipitation — Type
Precipitation <: PrecipitationAxis - a precipitation amount over a month, quarter or year (BioClim 12-19, Climate prec/pr; mm/day). Carries the unit and provides a water supply/demand.EcoSISTEM.PrecipitationAxis — Type
PrecipitationAxis <: WaterAxis - precipitation niche axes. A topical group; the unit and the water supply/demand live on the [`Precipitation`](@ref) leaf.EcoSISTEM.PrecipitationSeasonality — Type
PrecipitationSeasonality <: PrecipitationAxis - precipitation seasonality, the coefficient of variation of the monthly precipitation totals (BioClim 15; dimensionless).EcoSISTEM.Problem — Type
ProblemOne thing worth telling the user about a study area.
Fields
severity: aProblemNoticeor aProblemWarning.code: names the kind of problem, so that it can be tested for and filtered on without matching against the prose.message: the prose itself.
EcoSISTEM.ProblemNotice — Type
ProblemNotice <: AbstractProblemSeverity - something was guessed, or is lossy but expected.EcoSISTEM.ProblemWarning — Type
ProblemWarning <: AbstractProblemSeverity - it will work, but is probably not what you want.EcoSISTEM.RainTolerance — Type
RainToleranceA rainfall preference: a NicheTolerance on Precipitation, read in the mm/day frame, with a Uniform response.
The frame is a rate rather than a depth: every shipped precipitation layer is read per unit time.
An alias rather than a type of its own, so it has the fields NicheTolerance has. RainTolerance(matrix) is a shorthand for NicheTolerance(Precipitation, Uniform, matrix).
EcoSISTEM.RandomCells — Type
RandomCells(count::CELLCOUNT)count cells drawn at random, without replacement, from the currently active ones.
Arguments
count: how many cells, either exactly (RandomCells(20)) or as a per-time rate (RandomCells(0.05/year)). A rate is applied to each candidate cell independently over the step, so the number taken is a binomial draw and varies from one firing to the next.
EcoSISTEM.RasterDataAcceptableCode — Type
RasterDataAcceptableCode{S, C}Trait holding when C is a shape in which a layer of source S may be named - a scalar code, a vector of them, or Nothing.
This admits a spelling; it does not confirm a layer exists. Rejecting :not_a_layer needs the catalogue and happens there. C records the canonical type a code resolves to, never the shape the caller wrote - see CODE_TYPE.
EcoSISTEM.RateChange — Type
RateChange <: AbstractChangeMode - an interval per unit time, accumulated each step.EcoSISTEM.Reactivate — Type
Reactivate() <: AbstractOperationMark the region's cells active again.
A deactivated cell keeps its supply - _zerogaps zeroes data gaps only - so a reactivated cell has resource waiting. That matters: a cell whose supply had been zeroed would be lethal rather than merely barren, since the death term is E/K and K = 0 gives a death probability of exactly one.
It does not restock the cell, and that asymmetry with Deactivate is deliberate: the habitat becomes available again and dispersal recolonises it from the surviving neighbours, which is how a site actually recovers. Actively replanting is a different act - combine AddAbundance with this over the same region - and is a restoration scenario rather than a release of constraint.
EcoSISTEM.RegimeCollection2 — Type
RegimeCollection2{M1, M2} - two positional regimes over one grid. Deprecated plumbing: use [`LayerCollection`](@ref).EcoSISTEM.RegimeCollection3 — Type
RegimeCollection3{M1, M2, M3} - three positional regimes over one grid. Deprecated plumbing: use [`LayerCollection`](@ref).EcoSISTEM.RegionMatch — Type
RegionMatchOne named region a query found, and enough of it to act on without looking anything else up.
Fields
level: which kind of region it is, asNaturalEarthLevel.name: the source's own spelling of the name.extent: its bounding box, in degrees.area: the total area of the region, inkm^2.parts: how many separate components it has.share: what fraction of the region's area its largest component holds. This is the number that says whetherLargestLandmassis a sensible answer for the region at all: New Zealand's is 0.56, so asking for its principal landmass silently returns South Island alone, and the Solomon Islands' is 0.20.overlap: the area of the box it shares with whatever was asked about, inkm^2, which is what anOverlapsreport orders by.nothingfor a listing, which asked about nothing.
EcoSISTEM.RegionReport — Type
RegionReportWhat investigate_regions found: the matching regions, in order, and the question asked.
A report is a container - it iterates, indexes and has a length - so only(report) asserts that the answer was unique, first(report) takes the best one and report[i] takes a chosen one. Any of those gives a RegionMatch, which is what NaturalEarthSpec accepts.
Fields
relation: the question that was asked, including what it was asked about.matches: the regions that answered it, ordered as described ininvestigate_regions.exact: whether the answer was checked against the regions' real outlines rather than their bounding boxes.refined: how many candidates had their geometry fetched to answer it. Zero unlessexact.
EcoSISTEM.RelativeChange — Type
RelativeChange <: AbstractChangeMode - an interval from the layer's captured values, so `K` rather than `°C`.EcoSISTEM.RelativeHumidity — Type
RelativeHumidity <: RelativeHumidityAxis - near-surface relative humidity (Climate hurs, BioClimPlus hurs_max/mean/min; dimensionless).EcoSISTEM.RelativeHumidityAxis — Type
RelativeHumidityAxis <: HumidityAxis - relative-humidity niche axes (level and range).EcoSISTEM.RelativeHumidityRange — Type
RelativeHumidityRange <: RelativeHumidityAxis - annual range of the monthly relative humidity (BioClimPlus hurs_range; dimensionless).EcoSISTEM.RemoveAbundance — Type
RemoveAbundance(species, count)Remove individuals from each cell of the region, never taking a cell below zero - a cull, or a harvest.
Arguments
species: which species, by name or by index.count: at most how many per cell. AnIntegeris an exact number; a quantity per unit time is a mean rate, drawn afresh each step.
EcoSISTEM.RepeatAtEnd — Type
RepeatAtEnd <: AbstractSeriesEnd - the series cycles, by a true modulus of its own period.EcoSISTEM.ReplaceWith — Type
ReplaceWith(shape)Declare that shape's values are absolute: the layer's value is shape, in the layer's own unit.
Arguments
shape: something that genuinely differs from step to step - aSeriesChange, or aPatternedChangewhose shape returns the full value. A bare constant is rejected, because writing the same value every step is a one-off operation on the ecosystem rather than a change of the layer.
EcoSISTEM.Resource — Type
Resource <: RoleWhat a cell provides - solar radiation, available water, land.
A resource is a shared pool that species compete for, and it is what regulates abundance. Each species states how much it needs as an AbstractDemand; the demands of everything present are summed, and births fall and deaths rise as that total approaches what the cell supplies. Species therefore interact only through this total. Carrying capacity is not a parameter anywhere in the model - it emerges from supply divided by demand.
EcoSISTEM.RevertToLayer — Type
RevertToLayer <: AbstractSeriesEndPast its last slice the series stops driving the layer, which returns to the values it held before the series was attached - its own spec's, for a ReplaceWith series.
This is the not-yet-started rule of AbstractSeriesEnd applied at the far end, where the alternatives are genuine. It is also the only end policy for which the layer's own values are still needed: the other three keep the series in charge.
EcoSISTEM.Role — Type
RoleThe two ways a cell of the world bears on the species living in it: as a Condition it must tolerate, or as a Resource it competes for.
This distinction is the axis the whole model is built along, and it applies to both sides at once. The environment states each role as a layer (AbstractLayer) - a regime and a supply - and each species brings a matching requirement (AbstractSpeciesRequirement) - a tolerance and a demand. A role therefore names a relationship, not a kind of data: the same temperature grid is a condition because of how species meet it, not because of what it contains.
The two roles behave quite differently, which is why they are distinguished rather than merged: a condition is experienced identically by everything in the cell, while a resource is finite and shared, so what one species takes bears on the rest.
EcoSISTEM.RoundedFromMeasurement — Type
RoundedFromMeasurement <: AbstractDecisionSource - a [`MeasuredAcrossProjection`](@ref) cell size, floored to whole units.EcoSISTEM.SavedLandscape — Type
SavedLandscapeA GridLandscape reduced to what has to survive a round trip through disk: the bare abundance matrix, without its dimensions, and a snapshot of the per-species random number streams.
The streams are what make a resumed run reproducible - a run draws from one generator per species rather than from a shared one, so restoring the abundances alone would restart every stream from wherever the loading process happened to be. The dimensions are not saved because the ecosystem being restored into already has them.
Fields
matrix: the abundances, species by flat grid cell.rngs: one generator state per species, copied at the moment of saving.
EcoSISTEM.SavedLandscape — Method
SavedLandscape(gl::GridLandscape, rngs::Vector{Random.Xoshiro})Reduce a GridLandscape to its serialisable form.
Arguments
gl: the landscape whose abundances are to be kept.rngs: the ecosystem's per-species generators, copied rather than aliased so that continuing the run does not alter what was saved.
EcoSISTEM.SeriesChange — Type
SeriesChange(source; times = nothing, origin = nothing, atend = ErrorAtEnd(),
calendar = nothing)A stack of stored slices to be indexed by elapsed simulation time - a read climate series, or any (Y, X, Ti) array of values.
Arguments
source: the slices. Anything indexable by a time dimension.times: one time per slice. Taken fromsource's ownTilookup by default, or assumed monthly for an array carrying no lookup at all.origin: the point in the series' own coordinate that elapsed time zero corresponds to. Defaults to the first stored time, so a series starts at its own beginning whatever its axis is anchored to.atend: what happens past the last slice - anAbstractSeriesEnd, one ofErrorAtEnd(the default),HoldAtEndorRepeatAtEnd.calendar: what the coordinates mean - anAbstractSeriesCalendar. A source whose lookup holds real dates is inferred to be aDatedSeriesand anything else anUndatedSeries. A monthly climatology has to saycalendar = MonthOfYearSeries()for a run's epoch to start it in the right month, because month-of-year coordinates cannot be told from plain offsets by their values alone.
origin = 0 is not the same as leaving origin out, and the difference is a real one rather than a technicality. Omitting it means start at the first slice; zero means the coordinate zero, which on an ordinary monthly climatology - slices at 1 to 12 months - is a month before the first slice, and a series before its first slice says nothing, so the layer holds its own values for that month. Write the lead-in when you want one; leave origin out when you mean "from the beginning".
origin is accepted only for an UndatedSeries, the one case where nothing else can set the zero point: for the other two the epoch fixes the phase, and a second knob for the same thing could only contradict it. To say that an undated series really begins at a particular date, give it real times rather than an origin - that states what every slice is, rather than only where zero sits.
Like PatternedChange this is a shape, so the mode is named by the recipe wrapping it: ReplaceWith for stored values the layer takes on, OffsetBy for a stored deviation from the layer's own values, IncrementBy for a stored rate.
EcoSISTEM.SeriesLayerChange — Type
SeriesLayerChange{M <: AbstractChangeMode, E <: AbstractSeriesEnd, C <: AbstractSeriesCalendar, D, B} <: AbstractLayerChange{M}A stack of stored slices, indexed by elapsed simulation time: a slice is current from its own stored time until the next slice's, so at elapsed the layer takes the last slice at or before origin + elapsed, read according to M. Under AbsoluteChange the layer is that slice (a read climate series); under RelativeChange the slice is added to the layer's captured values.
times holds one time per slice in the same order, and origin is the point in that coordinate which elapsed time is measured from - the first stored time unless the caller says otherwise, so that a series starts at its own beginning whatever its axis is anchored to.
calendar records what the coordinates mean - see AbstractSeriesCalendar. It is what build_ecosystem reads when it resolves a run's epoch, and what it re-points the series against: resolving an epoch rewrites origin, leaving the stored slices and the hot path untouched.
Outside its own span a series contributes nothing, and the layer is whatever it would be without it: before the first slice always, and past the last under RevertToLayer. baseline is what that costs - the layer's values as they stood when the change was attached, kept for the modes that need something to fall back to.
Indexing by time rather than by a step counter is the substance of this type: it makes the result independent of the timestep (one twelve-month step and twelve one-month steps land on the same slice), which a cursor advanced once per call can never be. atend decides what happens past the last slice - see AbstractSeriesEnd.
EcoSISTEM.SetChange — Type
SetChange(target, spec)Install a new change rule on one layer, part-way through a run:
SetChange(:rainfall, IncrementBy(-0.1mm / day / year))Region-independent by nature - a layer's change applies to the whole layer - so an intervention carrying it should use AllCells. Any other region is accepted but ignored, and says so.
Arguments
target: which layer, by name. This addresses a member of a collection, so a multi-variable environment can say which variable is the one that changes.spec: the new change, as anAbstractChangeSpec.
EcoSISTEM.SetLandCover — Type
SetLandCover(class)Set the region's cells to a land-cover class.
The only operation permitted to write a layer's matrix directly, and only a categorical one. A continuous layer's values are owned by its change rule, which is a pure function of elapsed time; writing them from outside would break that and desynchronise MPI ranks. A categorical layer has no such rule, so land cover is the one thing an intervention may set.
Arguments
class: the class to set the cells to, by name (:open_water) or by its code.
EcoSISTEM.ShapeBuffer — Type
ShapeBuffer(distance)Grow the shape outwards by distance, or shrink it inwards where distance is negative.
This is how a study area becomes "within 50 km of this coastline", which no set operation can express. It takes one member: a buffer transforms a shape rather than combining several.
⚠️ The distance is applied in the shape's own coordinates, which for Natural Earth are degrees of latitude and longitude - so a buffer given as a length is converted at the equator and is narrower in east-west terms the further from it the shape lies. Give an angle to say exactly what is meant.
Arguments
distance: how far to grow, as a length (50km) or an angle (0.5°).
EcoSISTEM.ShapeConvexHull — Type
ShapeConvexHull() <: AbstractShapeOperationThe smallest convex outline containing the shape, as a rubber band round it.
Takes one member. Useful for turning a scattered archipelago into the single area it occupies, and for smoothing away a coastline's detail without choosing a tolerance.
EcoSISTEM.ShapeDifference — Type
ShapeDifference() <: AbstractShapeOperationThe first member's ground with every later member's removed.
EcoSISTEM.ShapeIntersection — Type
ShapeIntersection() <: AbstractShapeOperation - only ground common to every member.EcoSISTEM.ShapeSimplify — Type
ShapeSimplify(tolerance)Replace the outline with a coarser one no further than tolerance from it.
Only 1:10m polygons ship, that being the one scale at which a name's box and its shape can agree, so this is how a coarser outline is had when a fine one is not wanted - a continent's coastline carries tens of thousands of vertices that no continental-resolution grid can use. It takes one member.
Arguments
tolerance: how far the simplified outline may depart from the original, as a length or an angle, in the same coordinatesShapeBufferuses.
EcoSISTEM.ShapeSpec — Type
ShapeSpec(path::AbstractString; layer = 0)Name an active-area mask taken from the polygons of a vector file, without reading it. It holds no geometry: the read, any download, the per-feature reprojection into the target grid's own CRS and the cell-membership test all happen when it is materialised onto a decided grid, as for SourceSpec.
Arguments
path: a shapefile, GeoJSON, GeoPackage, or any format GDAL reads. A path ending in.zipis read directly, with no need to unzip first, and a URL is downloaded intoEcoSISTEM.assetdir(owner = ShapeSpec)as anEcoSISTEM.CachedAssetthe first time it is needed.layer: which layer of the file, 0-indexed. Every polygon feature in it is used.
EcoSISTEM.ShapeUnion — Type
ShapeUnion() <: AbstractShapeOperation - every member's ground, merged.EcoSISTEM.SimpleCategoricalTolerance — Type
SimpleCategoricalTolerance{A <: NicheAxis, V} <: AbstractCategoricalTolerance{A, V}
SimpleCategoricalTolerance(vals; axis, penalty = 0.0)The categories each species tolerates on niche axis A - one set of acceptable class values per species - together with the weight a species gets outside its set.
Fields
vals:vals[i]lists the class values speciesitolerates. A species with a single preferred class simply has a one-element set, so pass a plain vector of classes (one per species) and each is wrapped for you.penalty: the suitability weight outside the set, in[0, 1]. Inside it the weight is always1.
penalty is the whole soft-versus-hard distinction, and it is a number rather than a type. 0.0, the default, is hard exclusion: the species cannot persist outside its classes at all, because a zero suitability makes its death rate infinite. 0.5 is soft - it does worse there but survives. Anything between is available and means what it says.
penalty interacts with params.survival. Suitability enters the demographics as suitability^±survival, so at survival = 0 every penalty is ignored and the tolerance does nothing at all. That is a property of the model rather than of this type, and invisible from here, so it is worth stating: a categorical tolerance needs a non-zero survival to have any effect.
EcoSISTEM.SiteWaterBalance — Type
SiteWaterBalance <: WaterAxis - cumulative site water balance over the year, capped by soil water-holding capacity (BioClimPlus swb; L*m^-2).EcoSISTEM.SnowWaterEquivalent — Type
SnowWaterEquivalent <: WaterAxis - snow water equivalent, the liquid-water amount of the snowpack (BioClimPlus swe; L*m^-2).EcoSISTEM.SolarRadiation — Type
SolarRadiation <: SolarRadiationAxis - surface downwelling shortwave (solar) radiation flux (Climate srad/rsds, BioClimPlus rsds_max/mean/min). Provides a solar supply/demand.EcoSISTEM.SolarRadiationAxis — Type
SolarRadiationAxis <: NicheAxis - solar-radiation niche axes (level and range).EcoSISTEM.SolarRadiationRange — Type
SolarRadiationRange <: SolarRadiationAxis - annual range of the monthly solar radiation flux (BioClimPlus rsds_range).EcoSISTEM.SourceSpec — Type
SourceSpec{A <: NicheAxis, U, K <: NamedTuple}Name a layer of a catalogued data source, without reading it. It holds no grid array: the read, the cut and the resample happen only when it is materialised onto a decided grid.
Passing no code describes the whole dataset - every layer read into one multi-band raster, which is the form ConstructedRasterSpec uses for a bare dataset, such as all the land-cover class bands for compress_landcover.
Arguments
source: the dataset type to read from,WorldClim{BioClim}and the like.code: which layer of it, as oneCODE_TYPEor a vector of them. Omit it for the whole dataset.unit: the physical unit to attach on read. Defaults to the layer's own, from the shipped table.axis: the niche axis, which is what matches the layer to species niches. Defaults from the shipped table, and toNicheAxiswhere the table names none.any other keyword: kept as a pass-through argument for the eventual
read, soSourceSpec(WorldClim{Climate}, :wind, month = 1:12)reads the twelve monthly layers andmonth = 1just the one. ASourceSpecnested inside aConstructedRasterSpeccan therefore carry its own read options.Two of those keywords decide how much is read, and are worth knowing about together.
cutwindows the read, so only the cells inside a bounding box come off disk.scalecoarsens by an integer factor, and on its own it coarsens the whole source file however small a result is wanted, because the aggregated form is memoised per file rather than per window: for a global dataset that first read can need many gigabytes. Give ascaleacutas well where the whole world is not needed, and the memo is skipped along with the cost.
Fields
source,code,unit,readkw: as above.codeis nevernothing- a whole-dataset spec resolves the dataset's own code list at construction, so every layer's identity is known before anything is read and each can keep its own unit.unitfalls back toNoUnitsas a neutral placeholder where a multi-layer spec's layers disagree.
Type parameters
A: the niche axis. A type parameter rather than a field because it is dispatched on, which is what lets a layer's meaning be checked at compile time rather than looked up.U,K: the types ofunitandreadkw.
EcoSISTEM.SpaceAxis — Type
SpaceAxis <: NicheAxis - the physical space niche axes: ground surface now, canopy and soil later.EcoSISTEM.Spatial2D — Type
Spatial2D{Kind, T}A two-dimensional quantity in (y, x) order, with Kind saying whether it is a place or a separation and T the type of each component.
Write SpatialLocation or SpatialSize rather than this; both are aliases that pin Kind, so a method annotated with either refuses the other.
The order is y then x – north-south before east-west – matching every other pair in the package, and the field names are always y/x whatever the units. A degree quantity makes a geographic pair and a length quantity a projected one, so the units say which frame a value is in without a second type having to.
Fields
y: the north-south component – a latitude for a geographic position, a northing otherwise.x: the east-west component – a longitude for a geographic position, an easting otherwise.
EcoSISTEM.SpatialKind — Type
SpatialKindSupertype of the tags that say what kind of two-dimensional quantity a Spatial2D is.
The two are AbsolutePosition (a place) and RelativeOffset (a separation between places). Both are internal: a caller names SpatialLocation or SpatialSize instead, and the tag appears only inside the type.
EcoSISTEM.SpatialLocation — Type
SpatialLocation(y, x)A place, in (y, x) order: SpatialLocation(50.0°, -3.0°) geographically, or SpatialLocation(5000.0m, 3000.0m) on a projected grid.
Degrees are checked against the valid geographic range on construction; other units are not, because what counts as in range is a property of the coordinate reference system and is not known here.
EcoSISTEM.SpatialSize — Type
SpatialSize(y, x)A separation in (y, x) order – the extent of a cell, the size of a grid, the step between two coordinates: SpatialSize(1.0km, 1.0km).
Never range-checked, and signed: a displacement may run either way, and an angular separation may exceed the range a latitude is confined to.
EcoSISTEM.SpeciesList — Type
SpeciesList{TL <: AbstractTolerance, DM <: AbstractDemand,
MO <: AbstractMovement, T <: AbstractTypes,
P <: AbstractParams} <: AbstractTypesEverything the simulation knows about the species themselves - the species-side counterpart of a GridHabitat, and one of the two halves build_ecosystem checks against each other name for name.
It is itself a Diversity.AbstractTypes, but it holds the real types in types rather than being them, so every AbstractTypes question is forwarded there; see src/DiversityInterface.jl.
Fields
names: one name per species.tolerance: the niche of each species, anAbstractTolerancematching the habitat's regime axis for axis.demand: what each species takes from the shared pool, anAbstractDemandmatching the habitat's supply the same way.abun: the abundances a run starts from, beforepopulate!scatters them.types: the similarity structure - aUniqueTypeswhere species are maximally distinct, or aPhyloBranchesderived from a phylogeny.movement: which individuals disperse and how far, anAbstractMovement.params: the demographic rates, anAbstractParams.native: whether each species is native, one flag each.susceptible: optional per-species disease susceptibility,missingwhere unset.
Type parameters
TL,DM,MO,T,P: the types oftolerance,demand,movement,typesandparams.Tis what a method keys on to require a phylogeny, sinceDiversity's ownSimslot cannot carry that constraint.
EcoSISTEM.SpeciesList — Method
SpeciesList(numspecies::Int64, numtraits::Int64, abun::Vector{Int64},
demand::DM, movement::MO, params::P, native::Vector{Bool})
SpeciesList(numspecies::Int64, numtraits::Int64, abun::Vector{Int64},
demand::DM, movement::MO, params::P, native::Vector{Bool},
switch::Vector{Float64})
SpeciesList(numspecies::Int64, numtraits::Int64, abun::Vector{Int64},
demand::DM, movement::MO, phy::T, params::P, native::Vector{Bool})Create a SpeciesList whose categorical niche tolerances are evolved along a random ultrametric phylogeny, with a PhyloBranches similarity structure computed from that tree.
The third form takes a similarity structure explicitly instead of computing one from the tree; the tolerances are still evolved along a random ultrametric tree.
All three forms need Phylo - each builds the tree, or forwards to one that does - so using Phylo is required and without it the call is a MethodError. The implementation is in EcoSISTEMPhyloExt.
Arguments
numspecies: how many species.numtraits: how many categorical niche classes the tolerances are drawn from.abun: the starting abundances.demand: what each species takes from the shared pool.movement: which individuals disperse and how far.params: the demographic rates.native: whether each species is native.switch: the rate of trait change along branches. Defaults to[0.5].phy: a similarity structure to use in place of the one the tree would give.
EcoSISTEM.SpeciesList — Method
SpeciesList(numspecies::Int64, tolerance::TL, abun::Vector{Int64}, demand::DM,
movement::MO, params::P, native::Vector{Bool})Create a SpeciesList from tolerances supplied directly, rather than evolved along a phylogeny. Species are treated as maximally distinct, with a UniqueTypes similarity structure.
Arguments
numspecies: how many species.tolerance: their niches, as anAbstractTolerance.abun: the starting abundances. Padded with zeros if shorter thannumspecies.demand: what each species takes from the shared pool.movement: which individuals disperse and how far.params: the demographic rates.native: whether each species is native.
EcoSISTEM.SpeciesRequirementCollection — Type
SpeciesRequirementCollection{R <: Role, A, C <: NamedTuple}Several species requirements of the same role R - tolerances over several regime layers, or demands over several supplies - over the axis structure A, held by name in a NamedTuple, (Temperature = ..., Precipitation = ...). The species side's counterpart to LayerCollection: its members must line up, name for name and in the same order, with the layer collection they are matched against.
Members are named by their axis, so a Tuple of them is accepted and named for you. Two members on the same axis cannot be told apart that way, and are refused rather than silently numbered.
The role is read off the members rather than chosen, as LayerCollection does, so R cannot be got wrong and a collection mixing a tolerance with a demand is refused instead of being tagged with whichever role came first.
Members are reached through the standard container interface - sr.Precipitation, sr[1], sr[:Precipitation], keys, values, pairs, iterate, length, merge and NamedTuple(sr). A single requirement answers identically, as a one-member container.
Fields
nt: the members, by name. Reach them through the interface above rather than directly, so that no member name is reserved.
EcoSISTEM.SpreadingCells — Type
SpreadingCells(count::CELLCOUNT)count cells forming a contiguous cluster: a random active seed cell, then repeatedly a random active neighbour of the cells already chosen. Falls back to a fresh seed if the cluster is boxed in, so it always returns count cells where that many are available.
Arguments
count: how many cells, exactly or as a per-time rate, asRandomCells.
EcoSISTEM.SteadyLayerChange — Type
SteadyLayerChange{V} <: AbstractLayerChange{RateChange}A constant rate of change: the layer gains value * timestep every step. value is a scalar or a per-cell matrix, already converted to the layer's changeunit when the change was attached.
The mode is fixed to RateChange because only a rate accumulates. A constant value - absolute or relative - writes the same thing every step and is idempotent after the first, which makes it a one-off operation on the ecosystem rather than a per-timestep change of the layer.
EcoSISTEM.StudyArea — Type
StudyArea(base = missing; regime::Union{LayerInput, Missing, Nothing} = missing,
supply::Union{LayerInput, Missing, Nothing} = missing, within = missing,
crs = missing, cellsize = missing, extent = missing, align = missing,
simulate_safely = missing, verbosity = :normal)Decide the grid a simulation will run on, before anything is built on it.
Nothing is compulsory: the grid is decided from whatever is given, so naming only regime means only the regime shapes it. A layer that is not named here can never move or resize the grid - when GridHabitat later samples it, it can only mark cells inactive (and says so). Name a layer to let it shape the grid; omit it and it can only subtract.
The optional positional base refines an existing area - StudyArea(area, cellsize = 1km) - keeping everything not overridden, including its cache of reads, so trying several grids does not re-read the data. A StudyAreaReport or a GridHabitat may be given in its place.
A habitat's grid is copied rather than re-derived. A habitat can end up narrower than the area it was built on, because a layer named only to GridHabitat can cost cells the area listed as active - and nothing but the habitat's own report records that. So a base whose report is AsBuilt, with no other keyword given, is taken verbatim: StudyArea(habitat) is the grid the habitat is actually on, not the one originally investigated. Naming any grid keyword alongside re-derives instead, which loses the narrowing; that is deliberate, and not warned about, because overriding is an explicit act.
What is copied is the report, not the built grid. StudyArea(habitat) describes the habitat's grid but is itself a fresh area with nothing built on it, so its builtgrid is nothing while its report stays AsBuilt. The two say different things - the report's stage describes what the report is, builtgrid what has been done to this area - which is why neither can be derived from the other.
Keywords are tri-state: missing (the default) means "not specified - derive it, or take it from base", nothing means "explicitly cleared, ignore any inherited value", and any other value is used as given.
Arguments
regime,supply: the layers the simulation will use. Naming one here lets it shape the grid - its extent, its CRS and its resolution all become candidates. A layer not named here can still be used later, but can only mark cells inactive, never move or resize the grid.within: what positions the area - aShapeSpec, aCircleMaskSpec, aLatLongbox, orEcoSISTEM.boundingbox("Scotland"). It both restricts which cells are active and, where it can state an extent, sets the grid's. This is the argument to reach for when a global dataset would otherwise give you the globe.crs: the coordinate reference system to work in. A projected CRS is required to simulate: dispersal is expressed against one cell size, which only a projected grid has. Omitted, it is adopted from the layers, and a geographic result is warned about.cellsize: the length of a cell's side. Omitted, it is taken from thealignlayer's own step.extent: a size, not a bounding box - how big the area is, never where it is, given as a(y, x)tuple of lengths: north-south first, then east-west, the dimension order used throughout the package. It is therefore only meaningful for a synthetic area, and combining it with data layers is an error: those already carry their own extent, and a second unanchored size cannot be reconciled with it. Usewithinto position and limit an area built from data.align: names the layer whose own grid is preserved exactly. By default whichever layer is already in the target CRS (finest first), since that one needs no reprojection.simulate_safely: whether a cell must be wholly inside every layer's data to be simulated.true(the default) is the safe reading - a cell the data only partly describes is dropped, and the grid crops inwards rather than carrying it - since nothing can put data where a file has none.falserestores the older rule, under which a cell survives if its centre has a value (i.e. if it is more than half covered) and is then given a whole cell's worth of supply over ground that is partly missing; that is announced, with a count. The same rule applies to layers named only later, atGridHabitat.verbosity: see below.
With no layers that can shape a grid, extent and cellsize build a synthetic one with no CRS - which is also what a synthetic layer (UniformSpec, GradientSpec, ...) needs, since it is generated at whatever shape it is handed and so has no CRS, extent or resolution to contribute. Naming one here is harmless but decides nothing.
verbosity is :silent (errors only), :normal (announce every guessed value and every lossy step, and warn about grids that will work but are probably not what you want) or :verbose (aliases :full/:debug; show the whole investigate_study_area report).
Fields
report: theStudyAreaReportrecording how this grid was decided - the CRS, cell size and extent it settled on, which layer decided each, and everyProblemraised on the way.builtgrid: theStudyGridaGridHabitatwas built on here, ornothinguntil one has been.nothingdoes not mean the grid is undecided - an investigated area has decided one; that is what investigation is. It means nothing has been built on it yet, so the cells it lists are a prediction: a layer named only toGridHabitatcan still narrow them.
EcoSISTEM.StudyAreaReport — Type
StudyAreaReportEverything decided about a study area, and what it costs.
Returned by investigate_study_area and held by every StudyArea. The two share one analysis, so a report can never describe a grid other than the one that would be built.
Fields
crs,cellsize,align: the grid that was chosen.crssource,cellsizesource: where each of those decisions came from - anAbstractDecisionSource,GivenByUserif you supplied it, otherwise how it was derived. This is what lets the constructor announce everything it guessed.active: one array answering two questions. Its coordinates say where the cells are - units, CRS, span, locus - and its values say which of them are simulated.simulate_safely: the resolved ruleactivewas decided by.layers: aLayerPlaneach, saying what the chosen grid costs that layer.footprint: how much memory a run on this grid needs.problems: theProblems found on the way.specs,constraints: enough to use this report as the base of another - the specs it was decided from, and the constraints as given rather than as resolved.cache: theLayerCacheof reads, ornothingon an as-built report, where it has been discarded.stage: which of the two kinds of report this is - seeAbstractReportStage.
EcoSISTEM.StudyGrid — Type
StudyGrid{C, YD, XD} <: EcoBase.AbstractGridThe geometry of the grid a GridHabitat was built on: where its cells are, how big they are and what coordinate reference system they are stated in.
This is the package's EcoBase location data, so anything that speaks that interface - EcoBase, SpatialEcology, the plot recipes - can ask a habitat where its cells are. Every answer is unitful, in the grid's own units: a projected grid answers in km (or whatever it was built in) and a geographic one in degrees, neither converted into the other.
It is never constructed by hand and never carries its own copy of the coordinates: it holds the very Y and X dimensions the habitat's active mask is indexed by, so the two cannot drift apart. Reach it through the habitat's StudyArea.
Fields
crs: the coordinate reference system the coordinates are stated in, ornothingfor a synthetic grid, which has none.y: the grid'sYdimension - the first array dimension throughout this package.x: the grid'sXdimension.
EcoSISTEM.SumOfLayerChanges — Type
SumOfLayerChanges{M <: AbstractChangeMode, P <: Tuple, B} <: AbstractLayerChange{M}Several changes driving one layer, added together - a stored monthly series plus a multi-year warming trend, say, where the trend offsets the whole seasonal pattern rather than contradicting it.
Composition is a sum of values as functions of elapsed time, evaluated once per step, never a sequence of mutations. Chaining the applications instead would silently fail: an absolute write each step erases whatever a rate had accumulated by then.
M follows from the parts. A part that is a position (a read series) makes the whole an AbsoluteChange - there can be at most one, since two positions cannot be added - and parts keeps it first so the fold adds intervals to it in an order affine units accept. With no such part the whole is a RelativeChange over the layer's captured baseline. A RateChange part contributes its integral, so it must have one in closed form: a steady rate does (value × elapsed), a patterned one would need the integral of its own shape and is refused rather than approximated.
EcoSISTEM.Supply — Type
Supply{A}A supply of the resource measured on niche axis A - a Resource-role ContinuousLayer over a (Y, X) grid: Supply{SolarRadiation} (kJ/day per cell), Supply{Precipitation} (L/day), Supply{CarbonFlux} (g/day).
The axis is the only declaration of what a supply measures: its unit comes from canonicalunit(Resource, A), and an axis that declares no resource cannot be built as a supply at all. Construct one from a matrix of per-cell rates, Supply{SolarRadiation}(fill(200.0kJ/day, 10, 10)), or let GridHabitat do it from a spec that names the axis.
A supply that varies in time is the same type, carrying a SeriesLayerChange.
EcoSISTEM.SupplyCollection2 — Type
SupplyCollection2{M1, M2} - two positional supplies over one grid. Deprecated plumbing: use [`LayerCollection`](@ref).EcoSISTEM.SurfaceArea — Type
SurfaceArea <: SpaceAxis - ground surface, as a fraction of a cell (EarthEnv LandCover 1-12, or a `SurfaceSpec`).EcoSISTEM.SyntheticData — Type
SyntheticDataSource of a raster that was generated, not read: a synthetic supply or regime field built from a spec. It has no dataset, no layer codes and no catalogue row, and says so rather than borrowing a real dataset's name.
EcoSISTEM.TakenFromAlignedLayer — Type
TakenFromAlignedLayer <: AbstractDecisionSource - a cell size taken from the layer being aligned to.EcoSISTEM.TempTolerance — Type
TempToleranceA temperature preference: a NicheTolerance on Temperature, read in the kelvin frame, with a Trapezoid response.
An alias rather than a type of its own, so it has the fields NicheTolerance has. TempTolerance(matrix) is a shorthand for NicheTolerance(Temperature, Trapezoid, matrix).
EcoSISTEM.Temperature — Type
Temperature <: TemperatureAxis - an absolute temperature (annual/monthly/quarter mean, min, max, or growing-season mean; BioClim 1/5/6/8-11, Climate tavg/tmin/tmax/tas/tasmin/tasmax, BioClimPlus gst; K).EcoSISTEM.TemperatureAxis — Type
TemperatureAxis <: NicheAxis - temperature-related niche axes. A pure grouping node: each leaf states its own unit, because they do not share one.EcoSISTEM.TemperatureRange — Type
TemperatureRange <: TemperatureAxis - a temperature range (max - min): mean diurnal range or annual range (BioClim 2 and 7; K interval).EcoSISTEM.TemperatureSeasonality — Type
TemperatureSeasonality <: TemperatureAxis - temperature seasonality, the standard deviation of the monthly mean temperatures (BioClim 4; K).EcoSISTEM.ToleranceCollection2 — Type
ToleranceCollection2{M1, M2} - two positional tolerances. Deprecated plumbing: use [`SpeciesRequirementCollection`](@ref).EcoSISTEM.ToleranceCollection3 — Type
ToleranceCollection3{M1, M2, M3} - three positional tolerances. Deprecated plumbing: use [`SpeciesRequirementCollection`](@ref).EcoSISTEM.Torus — Type
Torus = EdgeTopology{Periodic, Periodic}A toroidal grid: both pairs of edges join, so nothing ever leaves.
True of a synthetic grid. On one with a real-world position it asserts something false - a study area is a window on a globe, not a world that wraps - so it is accepted with a warning.
EcoSISTEM.Trapeze — Type
Trapeze{A, V} <: AbstractNicheFit{A, V}Trapeze is deprecated and will be removed; use NicheSuitability instead (it pairs with a Trapezoid NicheTolerance).
EcoSISTEM.Trapezoid — Type
Trapezoid{T<:Real} <: ContinuousUnivariateDistributionTrapezoidal distribution as described at https://en.wikipedia.org/wiki/Trapezoidal_distribution.
EcoSISTEM.TypologyAxis — Type
TypologyAxis <: NicheAxis - categorical classification niche axes (class labels; dimensionless, used with a `CategoricalRegime`).EcoSISTEM.UndatedSeries — Type
UndatedSeries()No calendar identity at all - a synthetic stack, or any series whose coordinates are simply offsets. There is nothing for an epoch to bind to, so elapsed zero is the first slice unless the series' origin says otherwise. This is the only calendar for which origin is meaningful, and the default for any source that does not carry real dates.
EcoSISTEM.Unif — Type
Unif{A, V} <: AbstractNicheFit{A, V}Unif is deprecated and will be removed; use NicheSuitability instead (it pairs with a Uniform NicheTolerance).
EcoSISTEM.UniformSpec — Type
UniformSpec{A <: NicheAxis, V}A layer with a single constant value in every cell.
Arguments
value: what every cell holds - aUnitfulquantity, or a bare number.axis: the niche axis this layer is on. Required: it is what makes the layer matchable against a species' tolerances, and no default could be right for every model. PassNicheAxisitself for data whose meaning is genuinely not being claimed, such as a mask.
EcoSISTEM.VapourPressure — Type
VapourPressure <: HumidityAxis - near-surface water-vapour partial pressure (Climate vapr; kPa).EcoSISTEM.VapourPressureDeficit — Type
VapourPressureDeficit <: VapourPressureDeficitAxis - near-surface vapour pressure deficit (Climate vpd, BioClimPlus vpd_max/mean/min; Pa).EcoSISTEM.VapourPressureDeficitAxis — Type
VapourPressureDeficitAxis <: HumidityAxis - vapour-pressure-deficit niche axes (level and range).EcoSISTEM.VapourPressureDeficitRange — Type
VapourPressureDeficitRange <: VapourPressureDeficitAxis - annual range of the monthly vapour pressure deficit (BioClimPlus vpd_range; Pa).EcoSISTEM.Varying — Type
Varying(spec, change)Declare that the layer built from spec carries change. change is a change recipe (ReplaceWith, OffsetBy, IncrementBy) or an already materialised AbstractLayerChange.
Pass it to GridHabitat's regime or supply keyword. A StudyArea ignores the wrapper entirely - a change has no meaning until there is a grid to apply it to, so the area is decided from the spec alone.
GridHabitat(regime = Varying(SourceSpec(WorldClim{BioClim}, :bio1),
IncrementBy(0.02K/yr)),
supply = GradientSpec(...), area = area)Each layer names its own change, so a multi-variable regime wraps its elements, never the tuple: (Varying(temp, ...), rain), not Varying((temp, rain), ...).
EcoSISTEM.WaterAxis — Type
WaterAxis <: NicheAxis - umbrella for all water-measuring niche axes (precipitation, humidity, evapotranspiration, moisture, water stocks). A pure grouping node with no unit or resource of its own.EcoSISTEM.WindSpeed — Type
WindSpeed <: WindSpeedAxis - near-surface (10 m) wind speed (Climate wind/sfcWind, BioClimPlus sfcWind_max/mean/min; m*s^-1).EcoSISTEM.WindSpeedAxis — Type
WindSpeedAxis <: NicheAxis - wind-speed niche axes (level and range).EcoSISTEM.WindSpeedRange — Type
WindSpeedRange <: WindSpeedAxis - annual range of the monthly near-surface wind speed (BioClimPlus sfcWind_range; m*s^-1).EcoSISTEM.Within — Type
Within(x)Regions that lie completely inside x.
Answers "which regions can I simulate in full with the data I have?" - the converse of Encloses, and what walks down a hierarchy where that walks up.
Arguments
x: asEncloses, but not a point - no region fits inside a point.
Base.append! — Method
append!(diversityset::DiversitySet, dat::DataFrame)Append a DataFrame of diversity results to the data a DiversitySet already holds.
Arguments
diversityset: the set to append to.dat: the results, one row per subcommunity per timepoint.
Base.read — Method
read(::Type{CERA}, dir::String, file::String, param::String; cut = nothing)Read one variable out of the CERA-20C netCDF files in a directory - the archive is one file per decade - concatenate them along time, and return a ClimateRaster{CERA}.
Unlike the ERA readers this needs no dim: the monthly time coordinate for each decade is generated here, because the archive's layout is known. Longitudes are wrapped onto (-180°, 180°] as for ERA.
Arguments
dir: the directory to search.file: matched against each filename.param: the name of the variable to take out of each.cut: an optional region to crop to.
Base.read — Method
read(::Type{ERA}, dir::String, file::String, param::String,
dim::Vector{<:AbstractVector{<:Unitful.Time}}; cut = nothing)Read one variable out of every matching ERA netCDF file in a directory, concatenating them along time, and return a ClimateRaster{ERA}. The multi-file wrapper over the three-argument method above.
Arguments
dir: the directory to search.file: matched against each filename; every file containing it is read, inreaddirorder.param: the name of the variable to take out of each.dim: the time coordinate per file - a vector of time vectors, one per matched file.cut: an optional region to crop to.
Base.read — Method
read(::Type{ERA}, file::String, param::String, dim::Vector{<:Unitful.Time}; cut = nothing)As the two-argument method, but with the file's own time coordinate overridden. Returns a ClimateRaster{ERA}.
Arguments
file,param: as above.dim: one time per layer, replacing what the file says. For files whose CF time metadata is missing or wrong, or which are to be labelled in elapsed time rather than calendar dates.cut: an optional region to crop to.
Base.read — Method
read(::Type{ERA}, file::String, param::String; cut = nothing)Read one variable out of a single ERA netCDF file, returning a ClimateRaster{ERA} - ERA names the source, and the raster carries the data.
The file's own time coordinate is used as it stands - a genuine Dates.DateTime per layer, decoded from its CF metadata - and its longitudes are wrapped onto (-180°, 180°] to match every other reader. Use the three-argument method to override the time coordinate instead of trusting it, and the four-argument one to read and concatenate a whole directory.
Arguments
file: the netCDF file to read.param: the name of the variable to take out of it.cut: an optional region to crop to.
EcoSISTEM.GaussTrait — Method
GaussTrait(mean, sd)
GaussTrait(::Type{A}, mean, sd)GaussTrait is deprecated and will be removed. A Gaussian preference is just the Normal case of a NicheTolerance, so use one directly - NicheTolerance(A, Normal, mean, sd) (one unitful vector per parameter, support imputed). This shim forwards to that. GaussTrait(::Type{A}, mean, sd) names the niche axis A explicitly; the axis-less GaussTrait(mean, sd) form takes dimensionless (bare) data as NicheAxis, and - for back-compatibility only - infers the axis from a unitful vector's unit (temperature -> Temperature, precipitation rate -> Precipitation) with an extra warning, because a NicheTolerance's unit must come from its axis, not its data.
EcoSISTEM.HabitatLoss — Method
HabitatLoss(eco::AbstractEcosystem, regime::AbstractRegime, timestep::Unitful.Time)Destroy regime for one timestep of the ecosystem. The regime's change carries a loss rate (per unit time); over timestep it gives the per-cell probability that an active cell is lost. That many active cells are drawn at random and have their supply and abundances zeroed.
Deprecated: habitat loss changes the ecosystem, not a layer - it never marks the lost cells inactive, so they stay dispersal targets and can be lost again, and it draws from the global RNG, so it neither replays reproducibly nor agrees across MPI ranks. It is superseded by an explicit cell-deactivating intervention.
EcoSISTEM.LayerUpdate — Method
LayerUpdate(changefun, rate)
LayerUpdate(changefun, rate, ::Type{<:Unitful.Dimensions})Construct the AbstractLayerChange that replaces the v0.4.0 change function changefun. The third argument, a dimension to check rate against, is accepted and ignored - a change is now checked against the layer it is attached to instead.
EcoSISTEM.RainfallChange — Method
RainfallChange(eco::AbstractEcosystem, layer::AbstractLayer, timestep::Unitful.Time)Apply one timestep of layer's own change. Deprecated: a rainfall change is now declared as IncrementBy(rate), in the layer's unit per unit time, rather than named as a change function that hard-codes mm - which stopped being precipitation's unit when it became the rate mm/d.
EcoSISTEM.SurfaceSpec — Function
SurfaceSpec(fraction = 1.0; axis = SurfaceArea)A uniform space layer: the fraction of each cell that is available, from 0.0 to all of it (1.0, the default).
A thin convenience over UniformSpec: it fixes the axis to a space one and checks the fraction is not negative, and nothing more. SurfaceSpec() is the whole-cell case, which is what makes a space supply easy to ask for without its being automatic.
Not capped at 1.0. A cover fraction cannot exceed a whole cell, but a canopy legitimately can, since crowns overlap, so the ceiling belongs to the axis's own bounds rather than here.
Arguments
fraction: the share of each cell that is available,1.0by default.axis: which stratum, for when more than one is declared.SurfaceAreais the onlySpaceAxisleaf today.
EcoSISTEM.TempChange — Method
TempChange(eco::AbstractEcosystem, layer::AbstractLayer, timestep::Unitful.Time)Apply one timestep of layer's own change. Deprecated: a temperature increase is now declared as IncrementBy(rate), in the layer's unit per unit time, rather than named as a change function that hard-codes K.
EcoSISTEM.TempFluct — Method
TempFluct(eco::AbstractEcosystem, layer::AbstractLayer, timestep::Unitful.Time)Apply one timestep of layer's own change. Deprecated: an oscillation is now declared as IncrementBy(PatternedChange(amplitude, timescale)).
EcoSISTEM.abundances — Method
abundances(cache::CachedEcosystem, tm::Unitful.Time)Extract abundances for an ecosystem, cache, at a certain point in time, tm. If the abundances for that time are missing from the ecosystem, then the function checks on disk for the last saved version and simulates forward.
EcoSISTEM.applyinterventions! — Method
applyinterventions!(eco::AbstractEcosystem, intervention, elapsed, timestep, step)Apply every scheduled Intervention for the step that has just reached elapsed. Called by update! - after the population dynamics and before the layer update, so that a SetChange takes effect in the same step rather than one step late.
This is also the supported imperative route: it is the way to act on a running ecosystem without having declared anything in advance, and it takes any operation, not just some privileged subset. To add a species mid-run, having passed no intervention to simulate!:
simulate!(eco, 1year, 1month_mean_duration)
applyinterventions!(eco,
Intervention(EveryStep(), AllCells(),
AddSpecies(tolerance = Normal(298.0, 2.0),
abundance = 500)),
simulationtime(eco), 1month_mean_duration, 12)
simulate!(eco, 1year, 1month_mean_duration) # carries on with the new speciesPrefer declaring an intervention and passing it to simulate!. Calling this yourself gives up the two guarantees the declarative form provides, and step is where both bite:
- Reproducibility. A selection's random stream is
hash((seed, :intervention, k, step)), so astepyou have already used reuses that stream - aRandomCellsregion would draw the very same cells again - and a wrongstepmeans the run no longer follows from its seed. Pass the step number the simulation has actually reached. - Determinism across MPI ranks. An intervention mutates the ecosystem, so it must be applied once and identically everywhere.
update!guarantees that; a hand call does not.
For a conditional intervention - one whose firing depends on the state of the run, which no schedule can express - prefer simulate_action!: its callback closes over the ecosystem and runs at a known step, so it can decide and then apply without you tracking step by hand.
EcoSISTEM.arenoderecordsempty — Function
arenoderecordsempty(tree::AbstractTree, nodes::Vector{String})Check whether the node data records are empty for each node in nodes. Returns a vector of Bool values, one per node.
EcoSISTEM.assetdir — Function
EcoSISTEM.assetdir(mod::Module = EcoSISTEM; owner::Union{Type, Nothing} = nothing)Path to a subdirectory of EcoSISTEM's Scratch.jl space, for storing downloaded data outside the repository. Creating the directory is part of answering.
One EcoSISTEM-owned space with a subdirectory per package, rather than a space each, keeps the whole cache under one lifecycle: created on first use, and reclaimed by Pkg.gc() when EcoSISTEM is removed. RasterDataSources is put under it the same way, by the extension's __init__ setting RASTERDATASOURCES_PATH.
Arguments
mod: whose subdirectory to return, defaulting to EcoSISTEM's own.owner: a type to nest a further subdirectory under, so each owner's downloads are separate - seeCachedAsset.
EcoSISTEM.assetpath — Method
assetpath(asset::CachedAsset)
assetpath(relative_path::AbstractString)Return a local path in EcoSISTEM's asset cache, downloading the file first if it is not there yet.
Arguments
asset: aCachedAsset, fetched from itsurlinto its owner's subdirectory if the cache does not already hold it.relative_path: a path resolved underassetdirdirectly, for a cached file whose name is already known and which needs no descriptor.
EcoSISTEM.assigntraits! — Function
assigntraits!(tree::AbstractTree, switch_rate::Vector{Float64}, traits::DataFrame)
assigntraits!(tree::AbstractTree, switch_rate::Float64, traits::DataFrame)
assigntraits!(tree::AbstractTree, traits::DataFrame)Evolve functional traits through a phylogenetic tree, writing the result onto the tree's node records.
The first two forms evolve categorical traits, switching between the values in each column of traits at switch_rate - one rate per trait, or a single rate shared by all of them. The third evolves continuous traits by Brownian motion, and takes a traits with a start column of initial values and a σ² column of rates, one row per trait.
Arguments
tree: the phylogeny to evolve the traits along.switch_rate: the rate of categorical trait change along a branch, per trait or shared by all of them. Omitted for the Brownian form.traits: the traits to evolve - the categorical values per trait, or thestart/σ²pairs the Brownian form needs.
EcoSISTEM.bioclimhabitat — Function
erahabitat(era, maxsupply, area[, active]; axis = NicheAxis)
erahabitat(era, supply[, active]; axis = NicheAxis)
worldclimhabitat(worldclim, maxsupply, area[, active]; axis = NicheAxis)
worldclimhabitat(worldclim, supply[, active]; axis = NicheAxis)
bioclimhabitat(bioclim, maxsupply, area[, active]; axis = NicheAxis)
bioclimhabitat(bioclim, supply[, active]; axis = NicheAxis)
landcoverhabitat(landcover, maxsupply, area[, active]; axis = NicheAxis)
landcoverhabitat(landcover, supply[, active]; axis = NicheAxis)All four are deprecated and will be removed; use GridHabitat(regime = SourceSpec(source, code), supply = ..., area = ...), with a StudyArea deciding the grid from the data's own CRS, extent and resolution. A ConstructedRasterSpec wraps an already-read ClimateRaster where one is in hand. Unlike these builders, that route reports what the grid costs each layer, masks and reprojects, and can be inspected with investigate_study_area before anything is built.
EcoSISTEM.boundingbox — Method
boundingbox(region::AbstractString; level = nothing, coverage = AllTerritories(),
round = false)Return a named region's geographic bounding box, as an Extents.Extent of ° intervals ready to pass as the cut keyword to read and the other raster readers.
The answer costs no download: it is read from a table generated from Natural Earth's own polygons at 1:10m, so the box agrees with the shape the same name gives. Rounding onto a source's own lattice is what lets a layer be aggregated exactly rather than resampled: WorldClim's cells are 10 arcminutes, EarthEnv's and CHELSA's 30 arcseconds.
Arguments
region: the region's name, matched case-insensitively.level: which kind of region the name means -"ADMIN"for a country,"SUBUNIT"for a constituent country,"Physical Island"for a landmass, and so on;EcoSISTEM.naturalearth_levels()lists them all. Optional, and only needed where a name means genuinely different ground at different levels: "Scotland" is the same box whether asked for as a map unit or a map subunit, while "Africa" as a continent stops 54 degrees west of "Africa" as a UN region, and naming a level is then required rather than guessed at.coverage: how much of what the name covers to take -AllTerritories, the default, for everything the name covers however scattered, orLargestLandmassfor the principal landmass alone. The default follows the source: Natural Earth's "France" is the one that includes Guadeloupe, and taking less than that is a choice the caller should make rather than one made for them.round: an angular step to snap the box outwards onto, so the result fully contains the exact box. Any angular unit will do:round = 5°,round = 10arcminute,round = 30arcsecond. The result is in degrees whichever was used.false, the default, leaves it unrounded.
EcoSISTEM.bounds — Method
bounds(axis::Type{<:NicheAxis})Return the physical range axis' values must stay within, as a (floor, ceiling) tuple in the axis' canonical unit. Either end is nothing where no bound applies, and (nothing, nothing) - the default - means the axis is unbounded in both directions.
Stated in canonical units, and that is load-bearing: a temperature is ≥ 0 in kelvin but not in degrees Celsius, so a bound compared against a layer still holding °C would be nonsense. Every caller converts first.
The floor is the same fact the catalogue records as Category = balance. An axis with a balance row is sign-indefinite - a difference of two quantities, which may fall either side of zero - and is therefore not supply-eligible either. The two are one fact, and a testset asserts that the catalogue and these methods agree. Declared as methods rather than looked up per call, so that no bound check costs a catalogue search.
Ceilings are declared here and cannot be read from the catalogue: its OfficialUnit column says °C for Isothermality, TemperatureSeasonality and PrecipitationSeasonality, which are a ratio, a standard deviation and a coefficient of variation respectively. That column is wrong for them, so it is no evidence either way.
EcoSISTEM.brownian_motion — Function
brownian_motion(T::Real, σ²::Float64, start::Float64, lab::String = "")Evolve a Real value through Brownian motion, with a starting value, start, and rate, σ².
EcoSISTEM.build_ecosystem — Method
build_ecosystem(species::SpeciesList, environment::GridHabitat;
nichefit = nothing, seed = nothing, distributed = :auto, epoch = nothing)Assemble an ecosystem from a species list and an environment. When nichefit is not given it is inferred from the trait type (NicheTolerance -> NicheSuitability, any AbstractCategoricalTolerance -> CategoricalSuitability). Checks that the species' resource demand matches the environment's supply before building, and passes seed through for reproducibility.
distributed selects the ecosystem type: :auto (the default) builds a distributed MPIEcosystem when the MPI extension is loaded and the process is running with more than one rank (MPI.Init() already called), and a serial Ecosystem otherwise; true forces an MPIEcosystem (erroring if the MPI extension is not loaded); false forces a serial Ecosystem. Note that auto-selection only covers construction and simulate! - under MPI the abundances are partitioned across ranks, so collecting results still needs gatherabundance/gatherdiversity.
epoch is the real date the run begins - the date elapsed time zero means. It fixes the run's calendar for output (see simulationdate) and, more importantly, phases every series the environment carries: a DatedSeries starts at the slice covering the epoch, and a MonthOfYearSeries climatology at the slice for the epoch's own month, so a run beginning in July starts in July rather than in January.
It is resolved the way StudyArea resolves a CRS - adopt if unambiguous, ask if not. An explicit epoch always wins; otherwise the environment's own series supply it, and if exactly one real start date is found it is used and everything else is phased to it. Series that disagree are an error naming the candidates, and an environment with no dated series has no epoch at all, which is the behaviour of a run that never mentions dates.
EcoSISTEM.build_habitat — Function
build_habitat(source = DefaultEcosystem(); regime, supply, area, topology,
verbosity = :normal)Create a GridHabitat, filling anything not named from source.
GridHabitat itself is strict: omitting a required input is an error, because no default could be right for every model. This fills those omissions from somewhere explicit instead, and announces every value it chose.
source: where an unnamed input comes from.DefaultEcosystemgives a small synthetic toy grid; an existingGridHabitatgives its own layers, grid and topology, sobuild_habitat(habitat, supply = ...)is a rebuild with one thing changed.regime: the Condition layer(s) - seeGridHabitatfor what is accepted.supply: the Resource layer(s).area: theStudyAreathat decides the grid. From a habitat this is the grid it was actually built on, narrowing included - not the one originally investigated.topology: how the grid's edges join - seeEdgeTopology.verbosity::silentannounces nothing; anything else announces each filled-in value.
toy = build_habitat() # every input defaulted, and said so
wetter = build_habitat(toy, supply = rainier) # same grid, same regime, new supplyEcoSISTEM.build_species — Method
build_species(numspecies::Integer; tolerance, toleranceaxis, demand, demandaxis, dispersal = 10.0km,
pthresh = 1.0e-9, movement = BirthOnlyMovement, disperse_safely = true, birth = 0.6/year,
death = 0.6/year, longevity = 1.0, survival = 0.2, boost = 1.0,
abundance = 1000 * numspecies, native = true, seed = nothing)Build a SpeciesList of numspecies species. tolerance (the environmental Condition a species is matched to) and demand (the Resource it consumes) are required, and so is the NicheAxis each is measured on - toleranceaxis and demandaxis. Omitting any of the four errors (use build_species(DefaultEcosystem(); ...) to fill omissions with announced defaults). Every per-species keyword accepts either a scalar (applied to all species) or a length-numspecies vector (validated, with a clear error naming the argument on a length mismatch):
tolerance = (mean, width)- Gaussian niche tolerance (aNicheTolerancewith aNormalresponse). A tuple of(mean, width)pairs, e.g.((298.0K, 2.0K), (50.0mm, 10.0mm)), gives one tolerance per regime (aSpeciesRequirementCollection), to match a multi-variable environment.toleranceaxis- theNicheAxisthe tolerance is on. ANicheTolerance's unit comes from its axis, so the axis is what says which environmental variable the species responds to and in what unit its(mean, width)are read. For a per-regime tolerance tuple, pass a matching tuple of axes.demand- per-species resource demand rate, in the axis's own unit (Demand{SolarRadiation}iskJ/day,Demand{Precipitation}L/day,Demand{CarbonFlux}g/day); any scale of the right dimension is converted. A tuple of two demands (e.g.(10.0kJ/day, 5.0L/day)) gives aSpeciesRequirementCollectionto match a two-resource supply.demandaxis- theNicheAxisthe demand is on, matchingdemand's arity astoleranceaxismatchestolerance's.
Both axes used to be guessable: axis defaulted to Temperature, and a demand's type was chosen from its unit (kJ/day -> solar, and so on). Neither is true now. A unit cannot say what a value means - m/s and mm/day share a dimension, which is how a wind-speed layer once became a water supply - so the axis is the single declaration, on both sides, and it is required.
dispersal- mean Gaussian dispersal distance, cut off belowpthresh.movement- the movement type:BirthOnlyMovement(default),AlwaysMovementorNoMovement.disperse_safely- per species, what becomes of an individual whose dispersal is aimed at a dead cell (off the grid, or an inactive one):true(the default) redistributes it among the reachable destinations,falseloses it. A property of the disperser, so it may differ between species - a wind-dispersed seed blown out to sea is gone, an animal-dispersed one is not. The grid's topology (whether the world wraps) is a different question, answered byGridHabitat(..., topology = ...).birth,death,longevity,survival,boost- demographic rates (scalar rates give anEqualPop, vectors aPopGrowth).
abundance is either a total number of individuals split at random across species (seedable via seed) or an explicit per-species vector. native marks species as native (default all true).
EcoSISTEM.calc_lookup_moves! — Method
calc_lookup_moves!(topology::EdgeTopology, y, x, sp, eco, abun)Calculate the number of moves taken by a species, sp, from a specific grid square location (y, x). topology says how the grid's edges join - one AbstractBoundaryCondition per axis - and the total abundance of individuals to move is abun, which may be the number of births in the timestep or the total individuals.
One method for all four topologies. They differ only in whether each axis wraps, which is the two coordinate rules in _stepto, so the fourth combination - Y wrapping, X bounded - comes free rather than as a fourth copy.
EcoSISTEM.canonicalunit — Method
canonicalunit(::Type{<:NicheAxis})
canonicalunit(::Type{<:Role}, ::Type{<:NicheAxis})The unit a layer on this axis is normalised to when materialised (e.g. temperature -> K), or nothing to leave values as-is. The 2-argument form is role-aware: a Condition (a niche tolerance - a descriptive climatological normal) and a Resource (a literal consumable pool, replenished over time) can legitimately want a different canonical unit for the same axis - e.g. Precipitation stays a bare depth (mm) as a Condition, but is a genuine volumetric flow (L/day) as a Resource. It defaults to the 1-argument form for any role/axis combination without a specific override, so existing (implicitly Condition-role) call sites are unaffected.
EcoSISTEM.cellregime — Method
cellregime(eco::AbstractEcosystem, y::Int64, x::Int64)
cellregime(habitat::AbstractHabitat, y::Int64, x::Int64)Return what the environment is like at cell (y, x) - a NamedTuple keyed by keys, with one entry per regime layer.
The Condition half of the cell side of the 2×2 this vocabulary is built on; see speciestolerance for what a species brings to it.
EcoSISTEM.cellsupply — Method
cellsupply(eco::AbstractEcosystem, y::Int64, x::Int64)
cellsupply(habitat::AbstractHabitat, y::Int64, x::Int64)Return what the environment provides at cell (y, x) - a NamedTuple keyed by keys, with one entry per supply layer.
The Resource half of the cell side; see speciesdemand for what a species asks of it. These are the supply's own values, not what is available: an inactive cell's resource is included here, whereas totalsupply totals only the active ones.
EcoSISTEM.changeunit — Method
changeunit(mode::AbstractChangeMode, layer::AbstractLayer)Return the unit a change's values must be in to be applied to layer under mode, or nothing for a NoChange change, which carries no values in the layer's unit at all.
The three value-carrying modes are exactly the three answers to "what kind of quantity is this?":
| mode | the value is | unit on a °C layer |
|---|---|---|
AbsoluteChange | a position - the layer's value is this | °C |
RelativeChange | an interval from the layer's captured values | K |
RateChange | an interval per unit time | K/s |
The absolutising in the latter two is load-bearing, not cosmetic: a temperature is a position but a change in temperature is a width, and Unitful rejects adding two affine positions outright (10.0°C + 1.0°C throws AffineError). Reading a relative change in °C would therefore not be merely imprecise, it would not run.
EcoSISTEM.check_bounds — Method
check_bounds(eco::AbstractEcosystem, duration::Unitful.Time, timestep::Unitful.Time)Check that no change will drive a condition layer outside its axis' physical range (EcoSISTEM.bounds) during a run of duration in steps of timestep, erroring before the first timestep if one would. Called by simulate!.
Only changes whose reach can be computed exactly are checked; anything else is caught at the moment it happens instead.
EcoSISTEM.checkcoverage — Method
checkcoverage(eco::AbstractEcosystem, duration::Unitful.Time, timestep::Unitful.Time)Check that every stored series in eco's environment covers a run of duration in steps of timestep, erroring or warning as each series' own AbstractSeriesEnd policy dictates. Called by simulate! before the first timestep.
EcoSISTEM.checkfile — Method
checkfile(file::String, idx::Int)Check whether a JLD2 checkpoint file exists in the folder file for checkpoint index idx. Returns true if <idx>.jld2 is present.
EcoSISTEM.checkfile — Method
checkfile(::String, ::Missing)Check whether a cache file exists for a given timepoint. Always returns false when the timepoint is missing.
EcoSISTEM.clearcache! — Method
clearcache!(cache::CachedEcosystem)Delete all JLD2 cache files from the output folder of a CachedEcosystem. Returns a string reporting how many files were removed.
The trailing ! is not decoration: this destroys the recorded abundances on disk, and a CachedEcosystem that has been cleared can no longer answer for the timepoints it held.
Arguments
cache: theCachedEcosystemwhose output folder to empty.
EcoSISTEM.compress_landcover — Function
compress_landcover(landcover::ClimateRaster{<:EarthEnv{<:LandCover}})Collapse EarthEnv's twelve per-class cover fractions into a single layer of class codes, taking each cell's dominant class.
Arguments
landcover: the twelve bands as one multi-bandClimateRaster, which is whatSourceSpec(EarthEnv{LandCover})(no code) reads. The class code is the band's position, so all twelve must be present and in order; look one up by name withlandcoverclassrather than counting.
The result holds land-cover types (1-12, addressable by name with landcoverclass), which is a different quantity from its inputs: each input band is a fraction of the cell covered by one class - a SurfaceArea - while the output names which class won. Declaring the spec's axis = LandCoverTypology is what says so - a TypologyAxis holds class labels - and it is why nothing downstream averages between class codes: resampling takes the nearest class rather than interpolating, and a regime built from it is a CategoricalRegime.
Its niche axis is declared where it is used, not here. A raster carries no axis of its own - only a layer code the shipped catalogue can resolve - and no EarthEnv code means "typology", so say so on the spec:
ConstructedRasterSpec(EarthEnv{LandCover}, axis = LandCoverTypology) do lc
compress_landcover(lc)
endPrefer to let the combine run after the layers are sampled, which is the default: interpolating the percentages and taking the argmax afterwards keeps each cell's sub-cell mix and cannot fabricate a class, whereas collapsing first and resampling the codes invents classes that occur nowhere in the data.
EcoSISTEM.continuous_evolve — Function
continuous_evolve(val::Union{Float64, Unitful.Quantity{Float64}}, var::Union{Float64, Unitful.Quantity{Float64}}, tree::BinaryTree)Evolve a continuous trait along a BinaryTree, tree via Brownian motion. Takes in a starting value, val and a variance, var.
EcoSISTEM.convert_coords — Function
convert_coords(eco, sc::Int64, height::Int64)
convert_coords(eco, y::Int64, x::Int64, height::Int64)Convert coordinates from two-dimensional (y,x) format to one dimension (sc), or vice versa, using the height (dimension 1) of the grid. This function can also be applied to arrays of coordinates.
EcoSISTEM.cyclic_change — Method
cyclic_change(eco::AbstractEcosystem, layer::AbstractLayer, timestep::Unitful.Time)Apply one timestep of layer's own change. Deprecated: walking a stored time series is now the layer's declared change rather than a named change function. eraChange/worldclimChange are aliases of this - the logic never differed by source or role.
EcoSISTEM.demandtype — Method
demandtype(::Type{<:NicheAxis})The AbstractDemand concrete type a species uses to consume this axis' resource, or nothing if the axis is not a resource.
EcoSISTEM.densitywidth — Method
densitywidth(::Type{<:NicheAxis})The fixed physical width a continuous suitability density is multiplied by to make it a dimensionless weight, or nothing for an axis that declares none (no scaling is applied).
This is what stops an axis's canonicalunit being a model parameter in disguise. A probability density carries 1/x, so a stripped pdf is really "probability mass in a window one canonical unit wide" - re-declaring an axis from mm/d to cm/d would widen that window tenfold, multiply every suitability by ten and move every equilibrium. Multiplying by a width that is a fixed physical quantity cancels exactly that, because the width shrinks in the new frame by the same factor the density grows.
It must be written as a literal, never derived from canonicalunit. A width defined as "one canonical unit" changes when the canonical unit changes, which is the bug it exists to fix. Each declaration therefore states its quantity outright, and today's values are exactly one of each axis's current canonical unit - so behaviour is unchanged and test/canonical/reference.toml does not move.
It preserves the required specialist advantage, because the width is the same for every species: a narrower niche still peaks higher. That is what separates it from peak-normalising by σ, which would leave the specialist strictly dominated.
EcoSISTEM.discrete_evolve — Function
discrete_evolve(numTraits::Int64, tree::BinaryTree)Evolve a discrete switching trait along a BinaryTree, tree. Takes in a number of traits, numTraits to be switched between and rate to switch between traits, switch_rate with default value of 0.5.
EcoSISTEM.dispersesafely — Method
dispersesafely(m::AbstractMovement, sp::Integer)Return whether species sp is redistributed (true) or lost (false) when its dispersal is aimed at a dead cell. NoMovement answers true, since nothing disperses and so nothing can be lost.
EcoSISTEM.empty_landscape — Method
empty_landscape(habitat::GridHabitat, spplist::SpeciesList)
empty_landscape(habitat::GridHabitat, spplist::SpeciesList,
sppcounts::Vector{Int32}, sccounts::Vector{Int32})Create a landscape of the right shape with every abundance zero, taking the species names from spplist and the grid from habitat.
The partition is what distinguishes the two. Given only the habitat and species list this builds a GridLandscape; given sppcounts and sccounts as well - how many species and how many cells each rank owns - the MPI extension builds an MPIGridLandscape instead. The extra arguments are what "distributed" means, so the signature says it rather than the name.
Both take the habitat and species list rather than values derived from them, so that the derivation happens in one place and cannot drift between the two.
EcoSISTEM.emptypopulate! — Method
emptypopulate!(ml::GridLandscape, spplist::SpeciesList, habitat::AB, nichefit::NF,
rngs::Vector{Random.Xoshiro}) where {AB <: EcoSISTEM.AbstractHabitat, NF <: EcoSISTEM.AbstractNicheFit}Placeholder population function that leaves the landscape empty and warns.
EcoSISTEM.equalpop — Method
equalpop(params::AbstractParams, numspp)Expand EqualPop's single pair of rates into the numspp per-species rates of a PopGrowth. Parameters that are already per species are returned unchanged, so a caller can apply this without first asking which form it holds.
EcoSISTEM.erahabitat — Function
erahabitat(era, maxsupply, area[, active]; axis = NicheAxis)
erahabitat(era, supply[, active]; axis = NicheAxis)
worldclimhabitat(worldclim, maxsupply, area[, active]; axis = NicheAxis)
worldclimhabitat(worldclim, supply[, active]; axis = NicheAxis)
bioclimhabitat(bioclim, maxsupply, area[, active]; axis = NicheAxis)
bioclimhabitat(bioclim, supply[, active]; axis = NicheAxis)
landcoverhabitat(landcover, maxsupply, area[, active]; axis = NicheAxis)
landcoverhabitat(landcover, supply[, active]; axis = NicheAxis)All four are deprecated and will be removed; use GridHabitat(regime = SourceSpec(source, code), supply = ..., area = ...), with a StudyArea deciding the grid from the data's own CRS, extent and resolution. A ConstructedRasterSpec wraps an already-read ClimateRaster where one is in hand. Unlike these builders, that route reports what the grid costs each layer, masks and reprojects, and can be inspected with investigate_study_area before anything is built.
EcoSISTEM.extract_values — Method
extract_values(dat::AbstractClimate; lat, long, date = :, month = :, offset = :, code = :)Extract the value(s) of a climate dataset at the grid cell(s) containing given place(s).
The dataset is the only positional argument - everything else is a keyword, so a bare value is never left to be interpreted by its position. lat and long are required; every other keyword defaults to taking its whole dimension.
Each keyword becomes a selector on its own named dimension, so a 2-D grid, a monthly stack and a multi-layer read are one code path rather than three. The result's shape follows the request: a single place and a single slice give a scalar, and every dimension asked for by a vector is kept. Precisely: a dimension is dropped only when every keyword addressing it named exactly one thing, so a span, a vector, or a filter such as month on a dated axis all keep it, even where just one slice comes back.
Vectors cross, they do not zip. lat = [a, b], long = [c, d] samples all four combinations rather than the two pairs. Pairing a coordinate list with a per-record date belongs to sampling occurrence records, which this deliberately does not do.
Arguments
dat: the dataset to sample - anyAbstractClimate, including aClimateRasterstraight fromread.lat,long: required - where to sample, as a scalar for one place or a vector for several. The containing cell is returned, so a coordinate anywhere inside a cell gives that cell's value, and a coordinate off the grid is an error rather than the nearest cell.date: for a dataset on a calendar time axis - oneDateorDateTime, a vector of them, or a closed interval,Date(2000, 1, 1) .. Date(2000, 12, 31).month: a month number (March), several ([June, July]) or a range (March:May). On a monthly climatology this names the slice; on a dated axis it is a filter meaning every March across all the years present, so it keeps the time dimension even for a single month, since how many slices match is not fixed by the request. Refused on a time axis that is not monthly, namingoffsetinstead.offset: for a time axis of plain elapsed-time offsets rather than calendar dates - one value, a vector, or an interval, in the axis's own units.code: which layer of a multi-layer dataset, by its code (:bio2, or the number the catalogue names it by). A code is a label, so an unknown one is refused rather than read as a position.
Naming a keyword the dataset has no dimension for is an error that says what the dataset does have and which keyword addresses it.
EcoSISTEM.fitbrownian — Function
fitbrownian(tree::AbstractTree, traits::Vector{F}) where F <: AbstractFloatFit a Brownian motion model of trait evolution to traits measured at the tips of tree, returning a Brownian.
Arguments
tree: the phylogeny relating the taxa. Itsvarcovarmatrix is what carries the relatedness into the likelihood.traits: one measured value per tip, in the tree's own leaf order. The two are matched by position and not by name, so a mismatch is silent rather than an error.
EcoSISTEM.gatherabundance — Function
gatherabundance(eco::MPIEcosystem)Gather the full abundances matrix onto the root node.
EcoSISTEM.gatherdiversity — Function
gatherdiversity(eco::MPIEcosystem, divmeasure::F, q) where F <: FunctionAssemble the subcommunity diversity measured by divmeasure at order(s) q across every rank of a distributed ecosystem, returning the whole metacommunity's answer on all ranks.
Each rank computes the measure for the cells it owns. Those values are already final – a cell's diversity is a reduction over the species in that cell, and every one of them lives on the rank that owns the cell – so this assembles them rather than combining them, and the result matches a serial run whatever the rank count.
Arguments
eco: the distributed ecosystem.divmeasure: a subcommunity diversity function from Diversity, such asnorm_sub_alpha.q: a single order or a vector of orders.
Returns
- A
DataFrameof one row per subcommunity per order, as the serial measure returns.
EcoSISTEM.generate_storage — Method
generate_storage(eco::Ecosystem, qs::Int64, times::Int64, reps::Int64)Allocate a float array of shape (gridSize, qs, times, reps) for recording diversity values across the ecosystem eco for qs diversity orders over multiple timesteps and replicate runs.
EcoSISTEM.generate_storage — Method
generate_storage(eco::Ecosystem, times::Int64, reps::Int64;
maxspecies = length(eco.spplist.abun))Allocate an integer array of shape (maxspecies, gridSize, times, reps) for recording species abundances across the ecosystem eco over multiple timesteps and replicate runs.
maxspecies defaults to the number of species eco starts with, which is what a run that never gains one needs. Raise it to make room for species that arrive during the run - an AddSpecies intervention, an invasion - and the recorder then has somewhere to put them:
storage = generate_storage(eco, times, reps, maxspecies = 12)The array is sized once, before the run, and cannot grow afterwards: it is a dense array indexed by species number, so growing it mid-run would mean reallocating and copying every recorded step. A run that gains more species than maxspecies allows for says so when it tries to record them, rather than silently dropping them.
EcoSISTEM.genlookups — Method
genlookups(regime::AbstractRegime, kernel::GaussianMovement)Generate lookup tables, which hold information on the probability of moving to neighbouring squares.
EcoSISTEM.getcellarea — Method
getcellarea([units,] x, place)Return the area of the single cell of x's grid containing place.
The plural getcellareas answers for every cell; this answers for one, and is exactly getcellareas(units, x)[getcellat(x, place)].
units- asgetcellareas.x,place- asgetcellat.
There is no force here: a place has to be stated in the grid's own frame, so a caller who holds one already knows the grid. Force the read through getcellareas if that is what is wanted.
EcoSISTEM.getcellareas — Method
getcellareas([units,] x)Return the area of every cell of x's grid, one value per cell.
The result is always grid-shaped, so it can be indexed, reduced or broadcast without asking whether the grid happens to be uniform. Where every cell has the same area the answer is a Fill, which costs the same however large the grid; where areas vary – as they do with latitude on a geographic grid – it is materialised.
units- the unit to answer in, and optional: a length-squared unit (km^2) asks for a physical area,°^2orsrfor a true solid angle, and omitting it gives the grid's own.x- anything that knows the grid: aStudyArea, its report, aClimateRaster, a raster, a layer or collection, a habitat, or an ecosystem. Something with no grid answersnothing.force- whether to read the data to find out. A data-backed spec has a grid, but only reading it would say what, so it answersmissingrather thannothing: the value exists and is unknown here.force = trueperforms that read, which may involve a download. Only aSourceSpecnames data that can be read on its own; any other lazy spec describes a computation whose grid comes from the area it is built on, and refuses.
Reduce with Base: mean(getcellareas(x)), extrema(...), sum(...).
See also getcellsizes and getgridarea.
EcoSISTEM.getcellat — Method
getcellat(x, place)Return the CartesianIndex of the cell of x's grid that contains place, or nothing where x has no grid.
x- anything that knows the grid, asgetcellareas.place- aSpatialLocation(or aLatLong) in the grid's own frame.
This is the one function that turns a position into a grid position; everything else is then indexing, which is why no other accessor takes a location as a keyword.
Selection is by the lookup's own Contains, so it respects where in each cell the coordinate sits rather than re-deriving it. A place outside the grid throws: it is a caller mistake rather than a missing value.
EcoSISTEM.getcellcount — Method
getcellcount(x; active = false)Return how many cells x's grid has, or how many are active when active = true.
x,force- asgetcellareas.active- count only the cells the study area decided to simulate.
EcoSISTEM.getcellsize — Method
getcellsize([units,] x, place)Return the extent of the single cell of x's grid containing place, as a SpatialSize of scalars.
The plural getcellsizes answers for every cell; this answers for one.
units- asgetcellsizes.x,place- asgetcellat.
There is no force here, for the reason given on getcellarea.
EcoSISTEM.getcellsizes — Method
getcellsizes([units,] x)Return the extent of every cell of x's grid as a SpatialSize, one value per cell.
Each component is grid-shaped on the same terms as getcellareas: a Fill where the extent is uniform, materialised where it is not.
units- the unit to answer in, and optional: a length (km,m) asks for a metric answer, an angle (°) for an angular one, and omitting it gives the grid's own. The unit chooses the frame, not merely a conversion.x,force- asgetcellareas.
This is not the square root of getcellareas. On a geographic grid a cell's extent is angular and constant while its area is physical and shrinks towards the poles.
EcoSISTEM.getdemand — Method
getdemand(eco::Ecosystem)
getdemand(sppl::SpeciesList)Return the species' demands - their Resource-role requirements, pairing member for member with the supply. The species-side mirror of getsupply.
Returns the demand itself rather than a total, which would make it the only member of this family answering with a number rather than with the thing asked for.
Arguments:
eco/sppl: the ecosystem to read the demands from, or the species list directly.
Returns:
- the demand or collection of them.
EcoSISTEM.getdispersaldist — Method
getdispersaldist(eco, sp)Deprecated. Use EcoSISTEM.speciesdispersal, which returns the dispersal kernel itself rather than one of its parameters - more honest (the distance distribution is Rayleigh, not Normal) and directly reusable as AddSpecies' dispersal keyword.
EcoSISTEM.getdispersalvar — Method
getdispersalvar(eco, sp)Deprecated. Use EcoSISTEM.speciesdispersal.
Its formula did not match the kernel it claimed to describe - see the deferred item on dispersal parameterisation in the master plan - which is part of why the replacement returns the kernel and lets the caller read whatever it actually holds.
EcoSISTEM.getdist — Method
getdist(tolerance::NicheTolerance, sp::Int64)Return the pre-built response distribution for species sp. This is what the hot loop reads: a plain vector fetch, with no per-call construction and no allocation.
EcoSISTEM.getgridarea — Method
getgridarea([units,] x; active = false)Return the total area of x's grid, or of its active cells only when active = true.
This is sum(getcellareas(x)), and is correct on every projection because it adds each cell's own area rather than multiplying one cell by a count - which would be wrong wherever cells differ.
units,x,force- asgetcellareas.active- count only the cells the study area decided to simulate.
EcoSISTEM.getgridshape — Method
getgridshape(x)Return the size of x's grid in cells, as (ny, nx), or nothing where x has no grid.
This is how big the grid is - how many rows and how many columns - and is what the dispersal and intervention code needs to turn a flat location index into a (y, x) position.
x- anything that knows the grid, asgetcellareas: aStudyArea, its report, aClimateRaster, a raster, a layer or collection, a habitat, or an ecosystem.force- asgetcellareas: read a data-backed spec's data rather than answeringmissing.
shape rather than size is doing real work in the name. getcellareas and getgridarea are the same quantity at two scales and read as a pair, but a cell's size is a length while a grid's is a count, so those two should not. getgridsize keeps its released meaning - one cell's side length - and is deprecated onto it.
Deliberately a plain Tuple rather than a SpatialSize: these are counts, with no units and no frame, so nothing about them is spatial in the way a distance is.
One method covers everything, because getcellareas and the rest route through the same _gridyx dispatch table - so a habitat answers directly and no caller needs to reach inside it for a regime.
See also getcellcount, which is prod of this and can exclude inactive cells.
EcoSISTEM.getkernels — Method
getkernels(m::AbstractMovement)Return the vector of dispersal kernels a movement holds, one per species.
EcoSISTEM.getlat — Method
getlat(p)
getlong(p)Return the latitude or longitude of a geographic point.
Arguments
p: the point to read, which must be aLatLong.
Defined only for a LatLong, so asking a projected location for its latitude is a MethodError rather than a plausible-looking northing: a projected y is not a latitude, and the type system is where that should be caught.
EcoSISTEM.getlong — Method
getlat(p)
getlong(p)Return the latitude or longitude of a geographic point.
Arguments
p: the point to read, which must be aLatLong.
Defined only for a LatLong, so asking a projected location for its latitude is a MethodError rather than a plausible-looking northing: a projected y is not a latitude, and the type system is where that should be caught.
EcoSISTEM.getlookup — Method
getlookup(eco::Ecosystem)Extract movement lookup table of species from Ecosystem object.
EcoSISTEM.getlookup — Method
getlookup(eco::Ecosystem)Extract movement lookup table of species from Ecosystem object.
EcoSISTEM.getnichefit — Method
getnichefit(eco::Ecosystem)Extract niche fits.
EcoSISTEM.getpref — Method
getpref(tolerance::AbstractCategoricalTolerance, sp::Int64)Return the class values species sp tolerates. Always a collection, with one element for a species that has a single preferred class.
EcoSISTEM.getpref — Method
getpref(tolerance::NicheTolerance, sp::Int64)Return the parameters of species sp's response distribution, read off the distribution itself. Use getdist to reach the distribution rather than its parameters.
EcoSISTEM.getpref — Method
getpref(tolerance::AbstractTolerance, name::Symbol)EcoSISTEM.getregime — Method
getregime(eco::Ecosystem)
getregime(habitat::GridHabitat)Return the regime - what each cell is like - as the AbstractRegime layer (or collection of them) the environment holds.
Arguments:
eco/habitat: the ecosystem to read the regime from, or the habitat directly.
Returns:
- the regime layer or collection. Not its values: reach those through
.matrix.
EcoSISTEM.getregime — Method
getregime(regime::AbstractRegime, pos::Int64)Deprecated. Use EcoSISTEM.cellregime(eco, y, x), which is indexed by cell coordinates rather than by a linear position and returns a NamedTuple naming each regime layer.
EcoSISTEM.getregime — Method
getregime(regime::AbstractRegime, name::Symbol)EcoSISTEM.getrng — Method
getrng(eco::AbstractEcosystem, sp::Int64)Return the per-species random number generator for global species index sp. Because each species has its own stream and is processed by exactly one task per timestep, random draws are both thread-safe and reproducible independent of the number of threads or MPI processes (see makerngs).
EcoSISTEM.getspeciesstorage — Method
getspeciesstorage(x)Return the bytes one species' abundances occupy on x's grid, or nothing where x has no grid to answer for.
x- anything that knows the grid: aStudyArea, itsStudyAreaReport, aGridHabitat, anEcosystem, a layer, aClimateRasteror a raster. A spec that is a rule rather than data has no grid and answersnothing.
Multiply by a species count to size a run before building it - which is the point, since it can be asked of a StudyAreaReport from investigate_study_area before anything is constructed.
It counts the whole grid, not the active cells: GridLandscape's matrix is allocated over all of it, so an inactive cell costs exactly as much as an active one. And it is one array - a run holds several (abundances and net migration serially, more when distributed), so this is a per-array figure to be multiplied, not a total.
See also getcellsizes and getcellareas, which ask the same grid other questions.
EcoSISTEM.getsupply — Method
getsupply(eco::Ecosystem)
getsupply(habitat::GridHabitat)Return the supply - what each cell provides - as the AbstractSupply layer (or collection of them) the environment holds. The mirror of getregime.
Returns the layer, not its values; a caller who wants the numbers writes getsupply(eco).matrix. A layer's array type is an implementation detail, and the package does not put one across its public boundary.
Arguments:
eco/habitat: the ecosystem to read the supply from, or the habitat directly.
Returns:
- the supply layer or collection. For the total resource instead, see
totalsupply.
EcoSISTEM.gettimes — Method
gettimes(diversityset::DiversitySet)Return the timepoints in a DiversitySet for which diversity has not yet been calculated. Where a previously saved Feather file of results is found, only times beyond the latest it records are returned, so a run can be resumed rather than repeated.
Arguments
diversityset: the set to ask, whosefolderis searched for saved results.
EcoSISTEM.gettolerance — Method
gettolerance(eco::Ecosystem)
gettolerance(sppl::SpeciesList)Return the species' tolerances - their Condition-role requirements, pairing member for member with the regime. The species-side mirror of getregime.
Arguments:
eco/sppl: the ecosystem to read the tolerances from, or the species list directly.
Returns:
- the tolerance or collection of them.
EcoSISTEM.gettraits — Function
gettraits(tree::AbstractTree, tips::Bool=true)Retrieve functional traits assigned to a phylogenetic tree, either just tips or all nodes.
EcoSISTEM.hasdata — Method
hasdata(layer)A ConstructedRasterSpec combine returning a Bool mask of the cells of layer that hold data (are not missing/NaN) - the canonical combine-rule example. Pass it a data source to mask that source's coverage: ConstructedRasterSpec(hasdata, WorldClim{BioClim}, 1).
This is about data coverage, not about whether a cell is active: it takes a raw ClimateRaster, so it runs before any active mask exists - it is one of the rules that produces one.
Two limits worth knowing. It tests NaN only, so a source's own nodata sentinel counts as data unless reading has already converted it (which it does). And on a multi-band raster it reports the first band alone, so a twelve-class land-cover stack is masked by class 1's coverage rather than the stack's.
EcoSISTEM.in_memory_raster — Method
in_memory_raster(raster::ClimateRaster; axis)Wrap a raster you already hold as a layer spec, declaring what its values mean.
Prefer naming the source. A SourceSpec lets the package read only the window the study area needs, cache the result between layers, and take the layer's unit, axis, accumulation period and value type from the shipped catalogue. An in-memory raster gives all of that up: it is read in full by whoever built it, cached nowhere, and describes itself only by the axis given here. Reach for this when the data genuinely did not come from a catalogued source - something computed elsewhere, or read by hand - not as the ordinary way to build a layer.
It exists because a raster is refused as a spec, and rightly so: a raster carries values and possibly a layer code, but no niche axis, so nothing about it says whether those numbers are a temperature, a rainfall rate or a cover fraction. The spec is where that is declared, which is exactly what a raster cannot do - so this is the pathway, and axis is the whole of what it adds.
Arguments
raster: theClimateRasterto wrap. It is returned by the spec's combine verbatim, so it is neither re-read nor re-projected before the study area samples it.axis: theNicheAxisthe values are on - what makes them matchable against a species' tolerances. Required: passNicheAxisitself for data whose meaning is not being claimed, but a layer meant to pair with a tolerance needs a real one.
EcoSISTEM.investigate_regions — Method
investigate_regions(x; level = nothing, kind = nothing, limit = 20)
investigate_regions(relation::AbstractSpatialRelation; ...)Find the named regions that relate to x, as investigate_study_area reports on a grid before one is built.
Given anything with a position - a study area, a raster, a layer, a habitat, an ecosystem, an Extents.Extent, a LatLong or an earlier match - this asks which of the 2 444 shipped regions Encloses it. Name a relation instead to ask a different question: Overlaps for regions your data reaches into, Within for regions your data covers entirely.
Every region is compared by its bounding box, because that is what costs no download. A box can be far larger than the ground it names: Chile's spans 43 degrees of longitude because of Easter Island, so a query "overlapping" Chile may share no Chilean land at all. Pass exact = true to check against the real outlines instead, or build the shape with NaturalEarthSpec.
Arguments
x: what to ask about, or a relation carrying it.level: restrict to one level, by name.EcoSISTEM.naturalearth_levels()lists them.kind: restrict to levels of one sort -:political,:statistical,:physicalor:code.limit: how many matches to keep. A continental query can match hundreds, and the ordering puts the useful ones first.exact: check the surviving candidates against the regions' real outlines instead of their boxes, which needs the geometry and so downloads. It removes the false positives a box tier cannot avoid - Norway's box encloses Edinburgh, its coastline does not - and reaches the 54 regions that cross the antimeridian, which have no box a query can compare at all.Refinement is lazy and in box order, stopping as soon as the answer cannot change: refining only ever removes a match or shrinks its overlap, so a confirmed
limitcannot be displaced by anything later. The report says how many regions it had to fetch.
EcoSISTEM.investigate_study_area — Function
investigate_study_area(base = missing; regime::Union{LayerInput, Missing, Nothing} = missing,
supply::Union{LayerInput, Missing, Nothing} = missing,
within = missing, crs = missing, cellsize = missing,
extent = missing, align = missing, simulate_safely = missing)Report what a StudyArea built from these arguments would be, without building it.
Takes exactly the arguments StudyArea does - see there for what each one decides - so you can investigate, adjust, and then commit to the result. In brief: regime/supply are the layers allowed to shape the grid, within positions it, crs and cellsize fix the projection and resolution, align names the layer kept exactly, extent sizes a synthetic area only, and simulate_safely says whether a partly covered cell may be simulated.
Returns a StudyAreaReport, which displays as a readable summary and can equally be inspected programmatically (report.problems, report.layers, report.footprint).
The report can itself be handed back as the base of a StudyArea, which reuses its cache, so committing to an investigated grid re-reads nothing:
report = investigate_study_area(; regime, supply, within = ShapeSpec("scotland.shp"))
area = StudyArea(report) # same grid, no re-readingEcoSISTEM.iscategorical — Method
iscategorical(axis::Type{<:NicheAxis})Return whether axis' values are class labels rather than measurements.
This is a property of the axis, and nothing else needs to declare it. An axis holding Koppen climate classes or land-cover classes holds codes whose arithmetic mean is meaningless, so anything resampling such a layer must take the nearest class rather than interpolate. Every other axis holds numbers that may be averaged.
A day-count is deliberately not modelled as a third case. The catalogue distinguishes one from a continuous measurement, but nothing in the package acts on the distinction: every consumer asks only whether a layer is categorical, because that is the only answer that changes what resampling may do. A count is an ordinary number that may be averaged, exactly as a temperature is.
An axis whose values are class labels says so in its @nicheaxis declaration, with categorical = true; every other axis declares nothing and inherits from its parent, ending at NicheAxis itself, which is not categorical. This is the same declared-or-delegated shape as canonicalunit and densitywidth, and the macro is the only route - writing a method by hand covers the exact type named and not its subtypes, so a hand-declared group would silently fail to pass the property to its own leaves.
The fallback is false rather than an error, which is where this differs from canonicalunit. Very few axes are categorical, so false is a real majority answer that an axis can be assumed into; nearly every axis has a different canonical unit, so there is no answer to fall back on and not declaring one has to be refused. The same question decides how any future axis property should behave when undeclared: ask whether a majority answer exists.
EcoSISTEM.landcoverclass — Function
landcoverclass(name::Symbol)The raw numeric code of the shipped EarthEnv land-cover class name, looked up by name in the shipped table (never a hardcoded number). A building block for land-cover masks - e.g. an argmax of all class bands, excluding open water:
ConstructedRasterSpec(EarthEnv{LandCover}) do lc
compress_landcover(lc) .!= landcoverclass(:open_water)
endA raster broadcasts and yields a raster, so a combine names no array type: neither .array on the way in nor a wrapper on the way out.
EcoSISTEM.landcoverhabitat — Function
erahabitat(era, maxsupply, area[, active]; axis = NicheAxis)
erahabitat(era, supply[, active]; axis = NicheAxis)
worldclimhabitat(worldclim, maxsupply, area[, active]; axis = NicheAxis)
worldclimhabitat(worldclim, supply[, active]; axis = NicheAxis)
bioclimhabitat(bioclim, maxsupply, area[, active]; axis = NicheAxis)
bioclimhabitat(bioclim, supply[, active]; axis = NicheAxis)
landcoverhabitat(landcover, maxsupply, area[, active]; axis = NicheAxis)
landcoverhabitat(landcover, supply[, active]; axis = NicheAxis)All four are deprecated and will be removed; use GridHabitat(regime = SourceSpec(source, code), supply = ..., area = ...), with a StudyArea deciding the grid from the data's own CRS, extent and resolution. A ConstructedRasterSpec wraps an already-read ClimateRaster where one is in hand. Unlike these builders, that route reports what the grid costs each layer, masks and reprojects, and can be inspected with investigate_study_area before anything is built.
EcoSISTEM.layeraxes — Function
layeraxes(A::Type{<:NicheAxis} = NicheAxis)Return the niche-axis hierarchy at and below A (the whole tree by default) as a nested AxisNode: each node carries the shipped layer names that use its axis directly (only a concrete leaf ever has any - an abstract grouping node's own names is always empty) plus its child axis nodes, recursively down to the concrete leaves. Use it to discover which axes exist and what shipped layers use them, then drill into a group with layersbyaxis.
Arguments
A: the axis to root the tree at. Defaults toNicheAxis, the whole hierarchy; pass a group such asTemperatureAxisto see only that branch.
EcoSISTEM.layeraxis — Method
layeraxis(T::Type, code)Return the NicheAxis type declared for layer code of dataset T in its shipped data/ table, or nothing if the Axis cell is blank (or absent). A blank axis is an unclassified layer - documented and unit-bearing, but not modelled as a niche axis; to use it, pass an explicit axis when building the layer.
Arguments
T: theRasterDataSourcesdataset type.code: which layer of it, in any of the formslayerunitaccepts.
EcoSISTEM.layerinfo — Method
layerinfo(T::Type, code)
layerinfo(code)Return the catalogue LayerRecord for a layer, with its name, definition, unit, niche axis and sources. The two-argument form looks up code in dataset T's table (mirrors layerunit(T, code)) and returns one record. The single-argument form (an Integer/Symbol/String code) searches EVERY shipped table and returns a Vector of all matches - the same code can appear in several datasets (e.g. bio1 is in both BioClim and BioClimPlus).
Arguments
T: the dataset to look in. Omit it to search every shipped table instead, which is what turns one record into a vector of them.code: which layer - anInteger/Symbol/String, as forlayerunit.
The two forms differ in return type, not just in scope: name the dataset when you want the record, and omit it when you want to see where a code appears.
EcoSISTEM.layerrate — Method
layerrate(unit, period, axis)Return the unit a layer's values actually carry once its accumulation period has been applied - the declared amount, or that amount per day where the layer's canonical reading is a rate.
Arguments
unit: the layer's declared unit, aslayerunitreturns it.period: what each value accumulated over - anAbstractAccumulationPeriod, ornothingfor a layer that accumulates nothing.axis: the layer'sNicheAxis, which is what decides whether the canonical reading is a rate at all. Not the period - see below.
Two different questions, kept apart: layerunit answers what the shipped table declares, this answers what materialising it yields. Monthly precipitation is catalogued as L*m^-2, an amount, and read as L*m^-2*d^-1, a rate.
Having a period does NOT mean a layer is read as a rate - the axis decides that, not the period. gdd0 accumulates over a year, but CumulativeHeat's canonical unit is d*K: the heat sum is the reading that means something, since heat is a condition rather than a consumable resource. Dividing it would produce a mean daily temperature excess nobody asked for. So the period says what interval this accumulated over, and the axis says which reading is canonical; both are needed and they answer different questions.
Per day when it does divide, uniformly, whatever the period - that is what makes twelve slices divided by twelve different month durations share one unit, and it matches the canonical units the axes already declare (mm/day, kJ/day). The per-slice divisor changes the value, never the unit.
A PerCellAccumulationPeriod is deliberately never divided here: its stock-and-rate readings are role-dependent and the role is unknown at this point, so it keeps the declared amount.
An axis may be resource-only - CarbonFlux (npp) declares no Condition unit at all, deliberately, because potential productivity is a resource species compete for and not a condition they are matched against. Its Resource-role unit stands in as the canonical reading, so npp is divided like any other rate layer rather than left as an annual total.
EcoSISTEM.layersbyaxis — Method
layersbyaxis(A::Type{<:NicheAxis})
layersbyaxis(::Nothing)
layersbyaxis()Return a Vector of LayerRecords for every layer (across all shipped tables) whose axis is A or a concrete leaf beneath it. Passing an abstract group spans all its axes - layersbyaxis(TemperatureAxis) returns every temperature layer, layersbyaxis(Temperature) just that one axis. Printed as a compact list of codes with short summaries.
layersbyaxis(nothing) returns the unclassified layers instead - those whose Axis cell is blank, which layeraxis also reports as nothing. They are documented and unit-bearing but not modelled as a niche axis, so no axis type can reach them.
layersbyaxis() returns every layer, classified or not: the whole catalogue.
layersbyaxis() exists because layersbyaxis(NicheAxis) looks complete and is not - it spans every axis, but an unclassified layer has none, so it would be silently omitted. No shipped layer is unclassified today, which is exactly what makes that trap easy to fall into. Iterate the catalogue with the no-argument form.
Arguments
A: the axis to search under - a concrete leaf for that axis alone, or an abstract⋯Axisgroup to span every axis beneath it. Passnothingfor the unclassified layers, or omit it entirely for the whole catalogue.
EcoSISTEM.layerunit — Method
layerunit(T::Type, code)Return the physical unit of layer code in raster dataset T (e.g. layerunit(WorldClim{BioClim}, 1) is K, layerunit(WorldClim{Climate}, :srad) is kJ m^-2 day^-1). Looked up in the dataset's shipped data/ table and parsed with Unitful.uparse; a blank Units cell means dimensionless (NoUnits). code is matched by its string form, so integer layer numbers and Symbol/String keys both work.
Arguments
T: theRasterDataSourcesdataset type, e.g.WorldClim{BioClim}.code: which layer of it - anIntegerlayer number, or aSymbol/Stringalias (:bio1,"bio1",1all reach the same row).
EcoSISTEM.loadfile — Method
loadfile(cache::CachedEcosystem, file::String, idx::Int, names::Vector{String},
yx::Tuple{<:Y, <:X})Load a cached GridLandscape from the folder file for checkpoint index idx, reshaping the abundance matrix onto names/yx (the ecosystem's own species names and (Y, X) grid). The saved per-species RNG streams are restored into cache.rngs so the resumed run continues a reproducible random stream.
EcoSISTEM.makerngs — Method
makerngs(seed::Integer, n::Integer)Build a vector of n independent, deterministically-seeded random number generators, one per species. Species j is seeded as Xoshiro(hash((seed, j))) so its random stream is a pure function of (seed, j) - independent of how species are distributed across threads or MPI processes. This is what makes simulation results reproducible across different thread and process counts (each species is always processed by exactly one task on one rank, drawing in a fixed cell order). See getrng.
Note: this per-species scheme is sufficient only because no single species' draws are ever split across ranks/tasks. If a species' cells were ever partitioned across ranks, a per-(species, cell) counter-based generator would be needed instead.
EcoSISTEM.makeunique — Method
makeunique(eco::Ecosystem)Convert type of similarity in SpeciesList to UniqueTypes, i.e. an identity matrix.
The species keep their names: only the similarity structure is dropped.
EcoSISTEM.materialise — Method
materialise(spec::AbstractSpec, area::StudyArea; role = missing)
materialise(specs::Union{Tuple, NamedTuple}, area::StudyArea; role = missing)Put spec - or a tuple/named tuple of specs - onto area's grid and hand back the layer it becomes, so it can be plotted or checked before a simulation is built from it.
Works the same way for every kind of spec - a data source, a ConstructedRasterSpec, or a synthetic gradient - so layers can be compared cell for cell on the grid they will actually share. Data-backed specs are sampled onto the grid and synthetic ones generated at its shape, and the members of a tuple may be mixed. The result is an AbstractLayer whose matrix is a (Y, X) array carrying the area's real coordinates; several specs give a LayerCollection keeping the caller's names, exactly as the builder produces.
This runs the same code the builder does, so what you see is what the simulation gets. It is also the way to check a synthetic layer's layout, which is otherwise invisible: a gradient's direction follows real-world north (not array row order), and its endpoints span the grid's bounding rectangle, so on a non-rectangular study area the extremes may fall on inactive cells.
Arguments
spec: any layer spec - aSourceSpec, aConstructedRasterSpec, or a synthetic one (UniformSpec,GradientSpec,PeakedSpec,NicheSpec) - or a tuple/named tuple of them for a multi-layer regime, which is materialised member by member and keeps its names. The members may be mixed: data-backed specs are sampled onto the grid and synthetic ones generated at its shape, so both can share one grid.area: theStudyAreawhose grid to put it on.role:missing(the default) gives a regime layer holding the values as they are - its spatial pattern. A spec does not know its own role:UniformSpec(298K)is a regime andUniformSpec(1kJ/km^2/day)a supply only by virtue of which keyword it is passed to. Passrole = Conditionto canonicalise to the axis's unit, orrole = Resourcefor aSupplywhose per-area rate has become an absolute per-cell one - giving exactly the layer the simulation uses.
EcoSISTEM.move! — Method
move!(eco::Ecosystem, ::AbstractMovement, sc::Int64, sp::Int64, grd::Matrix{Int64}, births::Int64)Calculate the movement of species sp from a given position in the landscape sc, using the lookup table found in the Ecosystem and updating the movement patterns on a cached grid, grd. The number of births are passed in as births so that the movement can be restricted to only the newly born individuals, if desired. The movement type is specified by the second argument, which can be one of AlwaysMovement, NoMovement, or BirthOnlyMovement. Only in the last case is the births argument used.
EcoSISTEM.naturalearth_levels — Method
naturalearth_levels()Return every kind of named region there is, as a vector of NaturalEarthLevels.
A name means nothing without its level - "Africa" is a continent of 55 countries and a UN region of 62 - so this is where to look before naming one. Each entry says which file defines it, which attribute carries the name, what sort of division it is, and where it is likely to surprise.
EcoSISTEM.naturalearth_regions — Method
naturalearth_regions(level)Return every region defined at level, sorted by name, with the extent and area of each.
Reads the shipped table, so it costs no download. What comes back is a RegionReport, the same thing investigate_regions returns: it displays as a table, it iterates and indexes, and any row of it converts straight into a NaturalEarthSpec. The names alone are [m.name for m in naturalearth_regions(level)].
Names are matched case-insensitively wherever they are used, so the spelling here is for display rather than something to reproduce exactly.
Arguments
level: the level to list, as a name ("ADMIN") or aNaturalEarthLevel. An unknown one is an error suggesting the closest matches.
EcoSISTEM.nichefitcombine — Method
nichefitcombine(nichefit::AbstractNicheFit)Return the function that combines a nichefit's per-layer suitabilities into one number. It takes the whole NamedTuple of per-layer results - see CombiningFit - so a single fit "combines" by taking the only result, and _suitability needs no separate leaf path.
EcoSISTEM.pair — Function
pair(vec)Split a vector into consecutive overlapping pairs, returning a matrix with one pair per row. Used to traverse root-to-tip paths branch by branch.
EcoSISTEM.paramunits — Method
paramunits(D, support_units; probes = _defaultprobes(D))The absolute unit of each parameter of distribution D given a support of support_units, inferred by parameter role (see param_roles_resolved): a location or scale parameter carries the absolute support unit (K for °C), a rate carries its inverse, and a shape parameter is dimensionless - so a shape-only family (Beta, LogNormal, ...) is all-NoUnits. This is the introspection companion to read_distribution, which performs the actual, affine-aware value conversion when a distribution is read from bare parameters.
Arguments
D: the distribution type to describe.support_units: the unit its support is measured in.probes: the values used to discover each parameter's role, asread_distribution; defaults perD.
EcoSISTEM.peakedgradhabitat — Function
tempgradhabitat(minT, maxT, dimension, maxsupply, area, rate[, active]; axis = Temperature)
peakedgradhabitat(minT, maxT, dimension, maxsupply, area, rate[, active]; axis = Temperature)Both are deprecated and will be removed; use GridHabitat(regime = GradientSpec(minT, maxT, axis = Temperature), supply = ..., area = ...) - or PeakedSpec in place of GradientSpec for the peaked form. Declare the rate with Varying(spec, IncrementBy(rate)). These shims preserve the old behaviour rather than forwarding.
EcoSISTEM.populate! — Method
populate!(ml::GridLandscape, spplist::SpeciesList, habitat::AbstractHabitat,
nichefit::AbstractNicheFit, rngs::Vector{Random.Xoshiro})
populate!(ml::GridLandscape, spplist::SpeciesList,
habitat::GridHabitat{H, <:LayerCollection{Resource}}, nichefit, rngs)Populate the grid landscape ml by randomly scattering each species' total abundance (taken from spplist.abun) across the grid cells, choosing each cell with probability proportional to its available resource supply. Inactive cells are given zero probability, so no individuals are placed outside the habitable region. Each species is drawn from its own generator in rngs, so the result is reproducible and independent of the number of threads or MPI processes.
nichefit is unused by these resource-based methods; it is accepted only so that they share a signature with populate_by_tolerance! and can be passed interchangeably as the population function when constructing an Ecosystem. For a multi-supply environment (a LayerCollection) the sampling weight of a cell is the product of its two separately normalised supplies.
EcoSISTEM.populate_by_tolerance! — Method
populate_by_tolerance!(ml::GridLandscape, spplist::SpeciesList, habitat::AbstractHabitat,
nichefit::AbstractNicheFit, rngs::Vector{Random.Xoshiro})Populate the grid landscape ml by scattering each species' total abundance (taken from spplist.abun) across the grid cells with probability proportional to how well the species tolerances match each cell's environment, as scored by the trait nichefit nichefit applied to spplist.tolerance and habitat.regime. Where a species matches no cell the distribution falls back to uniform. Only native species (those flagged in spplist.native) are placed; non-native species are left empty.
This is the trait-based counterpart of populate!, which instead weights cells by their available resource supply.
EcoSISTEM.raingrad — Method
raingrad(minR, maxR, size, dim, rate)raingrad is deprecated and will be removed. Build the gradient as a layer recipe instead - GridHabitat(regime = GradientSpec(minR, maxR, axis = Precipitation), ...) - which does the same job on any niche axis, with Varying(spec, IncrementBy(rate)) for the rate. This shim keeps the old behaviour rather than forwarding, because a StudyArea would put the layer on a different grid.
EcoSISTEM.raingradhabitat — Function
raingradhabitat(minR, maxR, dimension[, maxsupply], area, rate[, active]; axis = Precipitation)raingradhabitat is deprecated and will be removed; use GridHabitat(regime = GradientSpec(minR, maxR, axis = Precipitation), supply = ..., area = ...) instead. minR/maxR are Condition values on the Precipitation axis, whose canonical unit is the rate mm/d - an accumulated depth (mm) is rejected. Note declare the rate with Varying(spec, IncrementBy(rate)). This shim preserves the old behaviour rather than forwarding.
EcoSISTEM.randomniches — Method
randomniches(dimension, types, clumpiness, weights, gridsquaresize)EcoSISTEM.read_distribution — Method
read_distribution(D, us, bare; canonical = absoluteunit(us), offset = nothing,
scale = nothing, probes = _defaultprobes(D), roles = ...)Build one species' response distribution of type D in the canonical (absolute) frame.
Arguments
D: the distribution type, e.g.Normal,Trapezoid,Beta.us: the support unit - the framebare's magnitudes are read in.bare: the distribution's parameters as bare numbers, in that frame.canonical: the frame to build in, absolute by default. Absolute matters, because a location converts affinely - 12 °C becomes 285.15 K - while a width does not.offset,scale: required only for a shape-only distribution (no location/scale/rate role -Beta,LogNormal), which is placed on the dimensioned axis viaLocationScaleasdist * scale + offset.offsetis a reference position,scalea reference width.probes: the values used to discover each parameter's role; defaults perD.roles: the roles themselves, one per parameter, where they are already known. Defaults toparam_roles_resolved(D, probes = probes), so a caller building many distributions of the same type can resolve them once and pass them in rather than paying for the discovery each time.
The roles drive the per-parameter conversion - see ParamRole for why a location and a width convert differently.
EcoSISTEM.readfile — Method
readfile(file::String; cut = nothing)Import a raster file from a path string into a DimArray.
Arguments
file: path to the raster, in any format GDAL reads.cut: a region to restrict the read to as anExtents.Extentof°intervals - fromboundingbox, say - ornothingfor the whole file. Applied lazily, before the pixels are fetched, so cutting a global layer to one country costs the country rather than the globe.xmin,xmax,ymin,ymax: deprecated, and warn when used. All four together meancut = Extent(Y = (ymin, ymax), X = (xmin, xmax)); passing some of them, or passing them alongsidecut, is an error. Passcutinstead.
EcoSISTEM.regimeupdate! — Method
regimeupdate!(eco::AbstractEcosystem, timestep::Unitful.Time)Update the regime of an ecosystem for one timestep.
EcoSISTEM.repopulate! — Method
repopulate!(eco::Ecosystem)
repopulate!(eco::Ecosystem, abun::Int64)Repopulate an ecosystem eco by redistributing abundances according to resource availability. If an abun parameter is given, that number of individuals of the final species is added at randomly sampled locations instead.
EcoSISTEM.repopulate_by_tolerance! — Method
repopulate_by_tolerance!(eco::Ecosystem)Repopulate an ecosystem eco according to how well species tolerances match their environment, redistributing the total abundance across species at random.
EcoSISTEM.reroot! — Function
reroot!(tree::AbstractTree, node::String)Reroot a phylogenetic tree by removing and recreating node, then attaching a new root node "NewRoot" above the original root.
EcoSISTEM.resettime! — Method
resettime!(eco::AbstractEcosystem)Reset the simulation clock to zero, so that the next timestep is the first.
Layers that vary in time are indexed by elapsed time, so this is what puts a stored series back to its first slice.
EcoSISTEM.resettraits! — Function
resettraits!(tree::AbstractTree)Clear all node data records in the tree, resetting every node to an empty DataFrame.
EcoSISTEM.resource_adjustment — Method
resource_adjustment(eco::Ecosystem, supply::AbstractSupply, sc::Int64, sp::Int64)Calculate how much birth and death rates should be adjusted by, according to how much resource is available, supply, in the grid square, sc, and how much resource the species, sp, requires.
EcoSISTEM.retrieve_era5 — Function
retrieve_era5(args...; kwargs...)Download ERA5 reanalysis data from the Copernicus Climate Data Store.
The download goes through the CDS Python client, so the method appears only once PyCall is loaded.
Arguments
args...,kwargs...: forwarded unchanged to the extension's method, which documents them - loadPyCalland consultretrieve_era5again to see the live signature.
The result is an ERA5 netCDF that readfile/ERA read like any other raster.
EcoSISTEM.root_to_tips — Function
root_to_tips(tree)Return all root-to-tip paths in a phylogenetic tree as a vector of node-name vectors, one per tip.
EcoSISTEM.setchange! — Method
setchange!(layer::AbstractLayer, spec)Install spec as layer's per-timestep change, converting and validating its values against the layer exactly once. spec is a change recipe (e.g. IncrementBy(0.02K/yr)) or an already materialised AbstractLayerChange.
EcoSISTEM.simplehabitat — Function
simplehabitat(val, dimension, maxsupply, area[, active]; axis = NicheAxis)
simplenichehabitat(numniches, dimension, maxsupply, area[, active]; axis = TypologyAxis)Both are deprecated and will be removed; use GridHabitat(regime = UniformSpec(val; axis), supply = ..., area = ...) - or NicheSpec in place of UniformSpec for the random-niche form - with a StudyArea deciding the grid. maxsupply has no direct equivalent: a supply spec gives the resource per cell, rather than a total spread across the grid.
EcoSISTEM.simplenichehabitat — Function
simplehabitat(val, dimension, maxsupply, area[, active]; axis = NicheAxis)
simplenichehabitat(numniches, dimension, maxsupply, area[, active]; axis = TypologyAxis)Both are deprecated and will be removed; use GridHabitat(regime = UniformSpec(val; axis), supply = ..., area = ...) - or NicheSpec in place of UniformSpec for the random-niche form - with a StudyArea deciding the grid. maxsupply has no direct equivalent: a supply spec gives the resource per cell, rather than a total spread across the grid.
EcoSISTEM.simpleregime — Method
simpleregime(val::Float64, size::Unitful.Length, dim::Tuple{Int64, Int64},
axis::Type{<:NicheAxis})Create a dimensionless ContinuousRegime filled with val.
EcoSISTEM.simpleregime — Method
simpleregime(val::Unitful.Quantity, size::Unitful.Length,
dim::Tuple{Int64, Int64}, axis::Type{<:NicheAxis})Create a ContinuousRegime regime of dimension dim, with cell size and filled value, val, on niche axis axis.
EcoSISTEM.simulate! — Method
simulate!(cache::CachedEcosystem, srt::Unitful.Time, timestep::Unitful.Time)Run a cached ecosystem, cache at a specified timepoint, srt, for a particular timestep, timestep.
EcoSISTEM.simulate! — Method
simulate!(eco::AbstractEcosystem, times::Unitful.Time, timestep::Unitful.Time)Run an ecosystem, eco for a specified length of time, times, for a particular timestep, timestep.
EcoSISTEM.simulate! — Method
simulate!(eco::Ecosystem, times::Unitful.Time, timestep::Unitful.Time,
cacheInterval::Unitful.Time, cacheFolder::String,
scenario_name::String)Run an ecosystem, eco for specified length of times, duration, for a particular timestep, 'timestep'. A cache interval and folder/file name are specified for saving output.
EcoSISTEM.simulate_action! — Method
simulate_action!(action!::Function, eco::AbstractEcosystem, times::Unitful.Time,
interval::Unitful.Time, timestep::Unitful.Time;
intervention = nothing, offset = false)Run an ecosystem eco up to time times in steps of timestep, calling the user-supplied action! at regular intervals so that any periodic task can be performed as the simulation proceeds - recording a quantity, logging progress, applying a management intervention, checking a stopping condition, and so on. This is the general engine behind the simulate_record! and simulate_record_diversity! recorders; use it directly when you want to do something they do not.
At each step the ecosystem is advanced with update!, which applies any Intervention passed as intervention. Whenever the elapsed time falls on a multiple of interval, action!(counting) is called, where counting is the 1-based index of that occurrence (handy as a storage slot when the action is recording); interval must be a whole multiple of timestep. Anything the action needs to read or update - the ecosystem, an output array, an external counter - is captured by the closure, typically written as a do block:
totals = zeros(Int, length((0s):interval:times))
simulate_action!(eco, times, interval, timestep) do counting
totals[counting] = sum(eco.abundances.matrix)
endoffset shifts the action grid to start at timestep rather than 0, which drops the first occurrence (one fewer action in total). Use it to make the number of actions match a pre-allocated array (such as one from generate_storage); the built-in diversity recorders pass offset = iseven(size(storage, 3)).
Returns the ecosystem eco, now advanced to times.
EcoSISTEM.simulate_record! — Method
simulate_record!(storage::AbstractArray, eco::Ecosystem, times::Unitful.Time,
interval::Unitful.Time, timestep::Unitful.Time)Run an ecosystem, eco for a specified length of time, times, for a particular timestep, timestep, recording abundances into storage at each time interval interval.
Pre-allocate storage with generate_storage(eco, ntimes, reps), where ntimes = length((0s):interval:times) is the number of recordings.
An intervention keyword takes an Intervention or InterventionSet. If it can add species (AddSpecies), size storage for them with generate_storage(eco, ntimes, reps, maxspecies = ...): the array is allocated before the run and cannot grow.
To record diversity rather than raw abundances, see simulate_record_diversity!; to perform an arbitrary action at regular intervals via a callback, see simulate_action!.
EcoSISTEM.simulate_record_diversity! — Method
simulate_record_diversity!(storage, eco, times, interval, timestep,
divfun, qs::Vector{Float64})
simulate_record_diversity!(substorage, metastorage, eco, times, interval, timestep,
qs::Vector{Float64})
simulate_record_diversity!(storage, eco, times, interval, timestep,
divfuns::Array{Function}, q::Float64)Run an ecosystem eco up to times in steps of timestep, recording diversity into storage (and, for the alpha/beta/gamma form, substorage/metastorage) every interval, which must be a whole multiple of timestep. These are all thin wrappers over simulate_action! - see it for the recording mechanics - and differ only in what diversity they record:
divfun, qs- a single diversity functiondivfun(which returns aDataFramewith a:diversitycolumn) evaluated over the diversity ordersqs, reshaped intostorage;substorage, metastorage, ..., qs- normalised alpha, normalised beta and gamma diversity overqs; subcommunity-level values are written tosubstorage(gridSize × 3 × timepoints × qs) and metacommunity-level values tometastorage(3 × timepoints × qs). This form returns both, as the named tuple(subcommunity = substorage, metacommunity = metastorage), so a caller need not remember which of the two came first;divfuns, q- several diversity functions at a single diversity orderq, one per column ofstorage.
For the divfun/divfuns forms, pre-allocate storage with generate_storage(eco, ncols, ntimes, reps), where ncols is length(qs) (or length(divfuns)) and ntimes = length((0s):interval:times).
EcoSISTEM.simulationdate — Method
simulationdate(eco::AbstractEcosystem)Return the real date the simulation has reached, or nothing for a run with no epoch.
The epoch is the date simulationtime counts from - resolved at build_ecosystem from the environment's dated series, or given there explicitly. A run whose environment mentions no dates has no epoch, and so no date: elapsed time is all there is to say about when it is.
EcoSISTEM.simulationtime — Method
simulationtime(eco::AbstractEcosystem)Return the simulation time elapsed since the ecosystem was built - zero at construction, advanced by one timestep per update!.
EcoSISTEM.sinusoidal — Method
sinusoidal(phase)Return one full sine cycle over a unit of dimensionless phase, the default shape of a PatternedChange or PatternedLayerChange.
phase is elapsed time divided by the change's timescale, so a whole number of timescales returns to zero. Any function of a dimensionless phase may be used instead - a sigmoid, a ramp, a step.
Arguments
phase: the dimensionless phase, elapsed time overtimescale.
EcoSISTEM.sourcecrs — Function
sourcecrs(T::Type{<:RasterDataSource}, layers = RasterDataSources.layers(T); kw...)Return the coordinate reference system of a source's files without reading any of their data.
The file is opened lazily, so only its header is touched - which is what lets a StudyArea settle its target CRS before deciding how much of each layer to read, rather than reading every layer whole just to discover where it is. Returns nothing for a file that declares no CRS.
cut/scale/fn are accepted and ignored, so a SourceSpec's stored read keywords can be splatted in unchanged; the aggregation scale in particular cannot affect a CRS.
Arguments
T: theRasterDataSourcesdataset type.layers: which layers to inspect, defaulting to all of the dataset's. Only the first file that declares a CRS is needed, so this is rarely worth narrowing.kw...: read keywords, all ignored - see above.
EcoSISTEM.species_blocksize — Method
species_blocksize()Number of species iterated together as a contiguous inner block in update!, chosen so one block spans a CPU cache line (cachelinesize ÷ sizeof(Int)).
EcoSISTEM.speciesdemand — Method
speciesdemand(eco::AbstractEcosystem, sp::Int64)
speciesdemand(spplist::SpeciesList, sp::Int64)Return what species sp requires - a NamedTuple keyed by demand_names, with one entry per resource: (sunlight = 2.0kJ/day, water = 5.0L/day).
The Resource half of the species side; pairs with cellsupply, and the values are directly comparable with it.
These are the raw unitful rates, never resource[sp] * exchange_rate. The exchange rate is arithmetic machinery - it defaults to 1/mean(resource), so the product is a dimensionless number on a community-relative scale that shifts when a species is added or removed. 2.0 kJ/day is what a species actually needs; 0.5 is only "half the mean of whoever happens to be here".
EcoSISTEM.speciesdispersal — Method
speciesdispersal(eco::AbstractEcosystem, sp)
speciesdispersal(spplist::SpeciesList, sp)Return species sp's dispersal kernel - a GaussianKernel or LongTailKernel. sp may be an index or a name.
The exception to the NamedTuple shape of the other four: a species has one dispersal kernel, not one per layer or per resource, so there is nothing to key a tuple by.
It returns the kernel itself rather than a parameterisation, which is both more honest - the distance distribution is Rayleigh rather than Normal, and a LongTailKernel is a 2Dt with a shape a Normal cannot express - and directly reusable: it is exactly what AddSpecies's dispersal keyword takes, so an arrival can be given an existing species' dispersal.
AddSpecies(dispersal = speciesdispersal(eco, 3), abundance = 500)EcoSISTEM.speciestolerance — Method
speciestolerance(eco::AbstractEcosystem, sp::Int64)
speciestolerance(spplist::SpeciesList, sp::Int64)Return what species sp can tolerate - a NamedTuple keyed by tolerance_names, with one entry per tolerance. Each value is whatever that tolerance kind holds: a response distribution for a NicheTolerance, a value for a categorical one, a vector of codes for land cover.
The Condition half of the species side; pairs with cellregime.
EcoSISTEM.suitability — Method
suitability(eco::AbstractEcosystem, pos::Int64, sp::Int64)
suitability(eco::AbstractEcosystem, y::Int64, x::Int64, sp::Int64)Return how well species sp suits a grid square - by linear position pos, or by cell coordinates (y, x).
Both forms exist because each has a caller that already holds what it takes: populate_by_tolerance! works in linear indices, while the hot loop already has (y, x) for the supply. They are distinguished by arity, so neither shadows the other.
EcoSISTEM.supplytype — Method
supplytype(::Type{<:NicheAxis})The AbstractSupply concrete type for this axis when used as a Resource resource, or nothing if the axis is not a consumable resource (so it errors clearly rather than silently guessing one if a supply is nonetheless requested).
EcoSISTEM.supplyupdate! — Method
supplyupdate!(eco::AbstractEcosystem, timestep::Unitful.Time)Update the supply of an ecosystem for one timestep.
EcoSISTEM.synchronise_from_cols! — Function
synchronise_from_cols!(mpigrid)Copy the abundance matrix from its cell-partitioned view back into the species-partitioned one - the mirror of synchronise_from_rows!.
EcoSISTEM.synchronise_from_rows! — Function
synchronise_from_rows!(mpigrid)Copy the abundance matrix from its species-partitioned view into its cell-partitioned one, so the next phase of the timestep sees the data in the split it needs.
An MPIGridLandscape holds one matrix in two layouts because the simulation needs different splits at different moments: demographics is per species, dispersal is per cell. This is one half of moving between them.
EcoSISTEM.tempgrad — Method
tempgrad(minT, maxT, size, dim, rate)tempgrad is deprecated and will be removed. Build the gradient as a layer recipe instead - GridHabitat(regime = GradientSpec(minT, maxT, axis = Temperature), ...) - which does the same job on any niche axis, with Varying(spec, IncrementBy(rate)) for the rate. This shim keeps the old behaviour rather than forwarding, because a StudyArea would put the layer on a different grid.
EcoSISTEM.tempgradhabitat — Function
tempgradhabitat(minT, maxT, dimension, maxsupply, area, rate[, active]; axis = Temperature)
peakedgradhabitat(minT, maxT, dimension, maxsupply, area, rate[, active]; axis = Temperature)Both are deprecated and will be removed; use GridHabitat(regime = GradientSpec(minT, maxT, axis = Temperature), supply = ..., area = ...) - or PeakedSpec in place of GradientSpec for the peaked form. Declare the rate with Varying(spec, IncrementBy(rate)). These shims preserve the old behaviour rather than forwarding.
EcoSISTEM.totalsupply — Method
totalsupply(habitat::GridHabitat)Return the total resource of a GridHabitat - one number per resource, not a per-cell grid - as a NamedTuple, one entry per resource, keyed by the supply's own axis names - (SolarRadiation = ..., Precipitation = ...) for a multi-resource habitat, and (SolarRadiation = ...,) for a single one. Each total is over the habitat's active cells only: an inactive cell's resource cannot be used by anything, so counting it would overstate what the landscape can support.
EcoSISTEM.unziptemp — Function
EcoSISTEM.unziptemp(path::String)Helper function for the FAIR Data Pipeline to unzip files that are stored as zips to a temporary folder.
EcoSISTEM.update! — Method
update!(eco::AbstractEcosystem, timestep::Unitful.Time)Update an ecosystem's abundances and environment for one timestep, with no intervention scheduled.
eco is the ecosystem to advance and timestep how far to advance it. Equivalent to update!(eco, timestep, nothing): the three-argument method is where the work happens, and each concrete ecosystem supplies its own, so this one covers every kind - serial, distributed, and any later addition.
EcoSISTEM.update! — Method
update!(eco::Ecosystem, timestep::Unitful.Time, intervention)Update an ecosystem for one timestep, applying any scheduled Intervention.
The ordering is the point. Interventions run after the population dynamics and before the layer update, with the clock advanced between - so a SetChange installed this step takes effect this step rather than one step late.
EcoSISTEM.update_resource_usage! — Method
update_resource_usage!(eco::Ecosystem)Calculate how much resource has been used up by the current species in each grid square in the ecosystem, eco. This function is parameterised on whether the species have one type of resource demand or two.
EcoSISTEM.updatesimulation! — Method
updatesimulation!(cache::CachedEcosystem, tm::Unitful.Time)Trigger the computation and caching of ecosystem abundances at timepoint tm in a CachedEcosystem.
EcoSISTEM.varcovar — Function
varcovar(tree::AbstractTree)Compute the phylogenetic variance-covariance matrix from the branch lengths of tree. The diagonal entries are the root-to-tip distances and the off-diagonal entries are the shared root-to-ancestor distances between pairs of tips.
Arguments
tree: the phylogeny, whose leaves are the taxa the matrix is over. Its order fixes the row/column order, so a trait vector passed tofitbrownianmust be in that same order.
Two tips sharing a longer ancestry share more of their history, so the matrix is what turns "related species resemble each other" into a covariance a model can be fitted against.
EcoSISTEM.worldclimhabitat — Function
erahabitat(era, maxsupply, area[, active]; axis = NicheAxis)
erahabitat(era, supply[, active]; axis = NicheAxis)
worldclimhabitat(worldclim, maxsupply, area[, active]; axis = NicheAxis)
worldclimhabitat(worldclim, supply[, active]; axis = NicheAxis)
bioclimhabitat(bioclim, maxsupply, area[, active]; axis = NicheAxis)
bioclimhabitat(bioclim, supply[, active]; axis = NicheAxis)
landcoverhabitat(landcover, maxsupply, area[, active]; axis = NicheAxis)
landcoverhabitat(landcover, supply[, active]; axis = NicheAxis)All four are deprecated and will be removed; use GridHabitat(regime = SourceSpec(source, code), supply = ..., area = ...), with a StudyArea deciding the grid from the data's own CRS, extent and resolution. A ConstructedRasterSpec wraps an already-read ClimateRaster where one is in hand. Unlike these builders, that route reports what the grid costs each layer, masks and reprojects, and can be inspected with investigate_study_area before anything is built.
EcoSISTEM.@nicheaxis — Macro
@nicheaxis Name <: Parent [condition = U] [resource = U supply = S demand = D] [reference]
[bounds = (lo, hi)] [densitywidth = W] [categorical = true]Declare a niche axis: its type, and what it means. This is the supported way to add one - the underlying canonicalunit/supplytype/demandtype/bounds/densitywidth/iscategorical methods are internal, and are emitted here so that they cannot disagree.
Every axis is an abstract type - an axis is only dispatched on, never constructed - so there is no group/leaf distinction to declare. An axis that declares nothing inherits its parent, which is the common case and quite different from reference, which states that it has no canonical unit.
condition and resource are the two roles, and each names a role and gives that role's canonical unit - so an axis is a condition, a resource, both, or neither, and says which.
| what you write | what it means |
|---|---|
condition = U | a condition: layers are canonicalised to U, and a tolerance is built in it |
resource = U supply = S demand = D | a resource: species consume it. All three, or none |
| both | a condition and a resource, as Precipitation is |
condition = nothing | not a condition - use with resource for a supply-only axis, as CarbonFlux is |
reference | neither - buildable, materialisable and composable, but never simulated |
categorical = true | values are class labels, so a layer on this axis is resampled by nearest class rather than interpolated |
| nothing at all | inherit the group's declarations |
Omitting condition and writing condition = nothing are different: the first inherits whatever the group declares, the second states that this axis has no condition reading and overrides the group. Declaring a resource implies neither - an axis can be both, and SolarRadiation is.
bounds = (lo, hi) gives the physical range in the axis's own canonical unit, either end nothing.
categorical is independent of the roles, and combines with reference: a layer of class codes carried only as ground truth is still put on a grid, and still must not be interpolated between its classes. Declaring it on one axis covers that axis' descendants, which is why TypologyAxis is the only declaration in this package - LandCoverTypology and ClimateTypology inherit it.
@nicheaxis(TemperatureAxis <: NicheAxis, condition = K, bounds = (0.0K, nothing), densitywidth=1.0K)
@nicheaxis(Temperature <: TemperatureAxis) # inherits both
@nicheaxis(CumulativeHeat <: TemperatureAxis, condition = K * Unitful.d, densitywidth=1.0K * Unitful.d)Both call forms work - @nicheaxis Name <: Parent condition = U parses identically. The parenthesised, comma-separated one is used throughout this package because JuliaFormatter keeps it readable, while it reflows the space-separated form into wrapped fragments.
EcoSISTEM.ClimatePref.downresolution — Function
downresolution(data::Union{ERA, ClimateRaster{WorldClim{BioClim}, <: DimensionalData.AbstractDimArray}}, rescale::Int64; fn)Function to decrease the resolution of a climate dataset, by a factor, rescale, and aggregation function, fn. The aggregation function has a default setting of taking the mean value.
Arguments
data: the dataset to coarsen - anERAor aClimateRaster.rescale: how many input cells are combined along each axis, so2combines blocks of four.fn: how to combine them,meanby default. A mean is meaningless for class codes - use a nearest-class rule there, which is what the resampling path does for a layer on a aTypologyAxis.
EcoSISTEM.ClimatePref.downresolution! — Function
downresolution!(resized_array::Matrix{T}, array::Matrix{T}, rescale::Int64, fn)
downresolution!(resized_array::Array{T, 3}, array::Matrix{T}, dim::Int64, rescale::Int64, fn)Function to decrease the resolution of a climate dataset in place, by a factor, rescale, and aggregation function, fn. The aggregation function has a default setting of taking the mean value.
Arguments
resized_array: the destination, written in place - its size is what fixes the output grid.array: the source values, one 2-D slice.dim: which slice of a 3-D destination to write, for the second form only.rescale: how many input cells are combined along each axis.fn: how to combine them, applied to the non-NaNvalues of each block.
EcoSISTEM.ClimatePref.extractvalues — Method
extractvalues(args...; kwargs...)Deprecated - use extract_values, which takes the dataset positionally and everything else by keyword.
EcoSISTEM.ClimatePref.readCERA — Method
readCERA(dir::String, file::String, param::String; cut = nothing)Deprecated - use read(CERA, dir, file, param; cut) instead.
EcoSISTEM.ClimatePref.readCHELSA_monthly — Function
readCHELSA_monthly(dir::String, var_name::String; scale = 1, fn = mean, cut = nothing)Deprecated - use read(CHELSA{Climate}, dir, var_name; scale, fn, cut) instead.
EcoSISTEM.ClimatePref.readCRUTS — Method
readCRUTS(dir::String, var_name::String; cut = nothing)Deprecated - use read(CRUTS, dir, var_name; cut) instead.
EcoSISTEM.ClimatePref.readERA — Method
readERA(dir::String, file::String, param::String,
dim::Vector{<:AbstractVector{<:Unitful.Time}}; cut = nothing)Deprecated - use read(ERA, dir, file, param, dim; cut) instead.
EcoSISTEM.ClimatePref.readERA — Method
readERA(file::String, param::String, dim::Vector{<:Unitful.Time}; cut = nothing)Deprecated - use read(ERA, file, param, dim; cut) instead.
EcoSISTEM.ClimatePref.readERA — Method
readERA(file::String, param::String; cut = nothing)Deprecated - use read(ERA, file, param; cut) instead.
EcoSISTEM.ClimatePref.readworldclim — Function
readworldclim(T::Type{WorldClim{Climate}}, files; cut = nothing)Deprecated - use read(WorldClim{Climate}, layers; ...) instead, which downloads via getraster and reads through the same machinery. Retained to read an already-resolved set of monthly climate raster file paths.
EcoSISTEM.ClimatePref.upresolution — Function
upresolution(data::Union{ERA, ClimateRaster}, rescale::Int64; fn)Function to increase the resolution of a climate dataset, by a factor, rescale.
Arguments
data: the dataset to refine - anERAor aClimateRaster.rescale: how many output cells each input cell becomes along each axis, so2gives four times as many cells.fn: how to fill them. Splitting a cell invents no information: the values are repeated, so this is a change of grid, not of detail.
EcoSISTEM.Units.month_duration — Method
month_duration(n::Integer)Return the duration of a calendar month named by its number, using February's mean length, since a bare month number carries no year.
Arguments
n: the month, fromJanuary(1) toDecember(12).
EcoSISTEM.Units.month_duration — Method
month_duration(date::Union{Dates.Date, Dates.DateTime})Return the duration of the calendar month a date falls in, using February's real length - 29 days in a leap year and 28 otherwise.
This is the form to use whenever the year is known, and the only one that can be right for a dated series: dividing February 2016's monthly total by February's mean 28.25 days rather than its actual 29 overstates that month's rate by 2.7%, every leap year. The Integer method cannot do better, because a bare month number carries no year, which is why both forms exist.
Typed on the two Gregorian date types rather than on Dates.TimeType, because every duration it can return is a Gregorian month length. A date on another calendar is refused rather than answered.
Arguments
date: anyDateorDateTime.
Base.read — Function
read(T::Type{<:RasterDataSource}, layers = RasterDataSources.layers(T);
cut = nothing, scale, fn, kw...)Download (via getraster) and read a RasterDataSources layer set into a ClimateRaster. layers chooses which layers/variables to read (default: all of them); a vector of distinct same-unit layers (e.g. [:tmin, :tavg, :tmax]) is read into one Dim{:layer}-stacked array rather than being conflated with a time axis. cut, if given, restricts the result to a Extents.Extent(Y = (a, b), X = (c, d)) of ° bounds. scale/fn coarsen each raster by an integer block-aggregation factor with reducer fn (source-specific defaults - e.g. EarthEnv{LandCover} is aggregated 10×). Any remaining keywords (e.g. month) pass through to getraster.
Base.read — Method
read(::Type{CRUTS}, dir::String, var_name::String; cut = nothing)Read every .tif in dir as a monthly time series of variable var_name, returning a ClimateRaster{CRUTS} - CRUTS names the source, and the raster carries the data. var_name uses the same short codes as WorldClim{Climate}'s shipped layer table (tavg, wind, prec, ...), which is where the attached unit comes from - CRU TS has no layer table of its own.
EcoSISTEM.NATURALEARTH_LEVELSEcoSISTEM.AbsoluteChangeEcoSISTEM.AbstractAccumulationPeriodEcoSISTEM.AbstractBoundaryConditionEcoSISTEM.AbstractCategoricalToleranceEcoSISTEM.AbstractChangeModeEcoSISTEM.AbstractChangeSpecEcoSISTEM.AbstractClimateEcoSISTEM.AbstractCombineStageEcoSISTEM.AbstractCoverageEcoSISTEM.AbstractDecisionSourceEcoSISTEM.AbstractDemandEcoSISTEM.AbstractEcosystemEcoSISTEM.AbstractHabitatEcoSISTEM.AbstractKernelEcoSISTEM.AbstractLayerEcoSISTEM.AbstractLayerChangeEcoSISTEM.AbstractLayerFateEcoSISTEM.AbstractLazySpecEcoSISTEM.AbstractMovementEcoSISTEM.AbstractNicheFitEcoSISTEM.AbstractOperationEcoSISTEM.AbstractParamsEcoSISTEM.AbstractProblemSeverityEcoSISTEM.AbstractRegimeEcoSISTEM.AbstractRegionEcoSISTEM.AbstractReportStageEcoSISTEM.AbstractScheduleEcoSISTEM.AbstractSeriesCalendarEcoSISTEM.AbstractSeriesEndEcoSISTEM.AbstractShapeOperationEcoSISTEM.AbstractShapeSpecEcoSISTEM.AbstractSpatialRelationEcoSISTEM.AbstractSpecEcoSISTEM.AbstractSpeciesEcoSISTEM.AbstractSpeciesRequirementEcoSISTEM.AbstractSupplyEcoSISTEM.AbstractSyntheticLayerSpecEcoSISTEM.AbstractSyntheticMaskSpecEcoSISTEM.AbstractSyntheticSpecEcoSISTEM.AbstractToleranceEcoSISTEM.AbstractTopologyEcoSISTEM.ActiveCellsEcoSISTEM.AddAbundanceEcoSISTEM.AddSpeciesEcoSISTEM.AdditiveFitEcoSISTEM.AdditiveFit2EcoSISTEM.AdditiveFit3EcoSISTEM.AdoptedFromLayersEcoSISTEM.AgreedByAllLayersEcoSISTEM.AllCellsEcoSISTEM.AllTerritoriesEcoSISTEM.AltitudeEcoSISTEM.AlwaysMovementEcoSISTEM.AsBuiltEcoSISTEM.AsInvestigatedEcoSISTEM.AtTimeEcoSISTEM.AtTimesEcoSISTEM.AxisNodeEcoSISTEM.BetweenTimesEcoSISTEM.BirthOnlyMovementEcoSISTEM.BoundedEcoSISTEM.BrownianEcoSISTEM.CERAEcoSISTEM.CODE_TYPEEcoSISTEM.CRUTSEcoSISTEM.CacheEcoSISTEM.CachedAssetEcoSISTEM.CachedEcosystemEcoSISTEM.CachedEcosystemEcoSISTEM.CachedGridLandscapeEcoSISTEM.CachedGridLandscapeEcoSISTEM.CarbonAxisEcoSISTEM.CarbonFluxEcoSISTEM.CategoricalLayerEcoSISTEM.CategoricalRegimeEcoSISTEM.CategoricalSuitabilityEcoSISTEM.CellMaskEcoSISTEM.CellNamesEcoSISTEM.CircleMaskSpecEcoSISTEM.ClimateMoistureEcoSISTEM.ClimateMoistureAxisEcoSISTEM.ClimateMoistureRangeEcoSISTEM.ClimateRasterEcoSISTEM.ClimateTypologyEcoSISTEM.CloudCoverEcoSISTEM.CloudCoverAxisEcoSISTEM.CloudCoverRangeEcoSISTEM.CombineOnSourceGridEcoSISTEM.CombineOnTargetGridEcoSISTEM.CombinedChangeEcoSISTEM.CombiningFitEcoSISTEM.ConditionEcoSISTEM.ConstantAccumulationPeriodEcoSISTEM.ConstructedRasterSpecEcoSISTEM.ConstructedShapeSpecEcoSISTEM.ContinuousLayerEcoSISTEM.ContinuousRegimeEcoSISTEM.ContinuousToleranceEcoSISTEM.CumulativeHeatEcoSISTEM.CylinderEcoSISTEM.DatedSeriesEcoSISTEM.DayAxisEcoSISTEM.DayCountEcoSISTEM.DayOfYearEcoSISTEM.DeactivateEcoSISTEM.DefaultEcosystemEcoSISTEM.DemandEcoSISTEM.DemandCollection2EcoSISTEM.DerivedDataEcoSISTEM.DiversitySetEcoSISTEM.DiversitySetEcoSISTEM.ERAEcoSISTEM.EcoSISTEMSourceEcoSISTEM.EcosystemEcoSISTEM.EcosystemEcoSISTEM.EcosystemEcoSISTEM.EdgeTopologyEcoSISTEM.EnclosesEcoSISTEM.EqualPopEcoSISTEM.ErrorAtEndEcoSISTEM.EvapotranspirationEcoSISTEM.EvapotranspirationAxisEcoSISTEM.EvapotranspirationRangeEcoSISTEM.EveryStepEcoSISTEM.FrostChangeFrequencyEcoSISTEM.GaussEcoSISTEM.GaussianKernelEcoSISTEM.GivenByUserEcoSISTEM.GradientSpecEcoSISTEM.GridHabitatEcoSISTEM.GridLandscapeEcoSISTEM.GridLandscapeEcoSISTEM.GrowingSeasonPrecipitationEcoSISTEM.HeterogeneityEcoSISTEM.HoldAtEndEcoSISTEM.HumidityAxisEcoSISTEM.IncrementByEcoSISTEM.InterventionEcoSISTEM.InterventionSetEcoSISTEM.IsRasterDataEcoSISTEM.IslandEcoSISTEM.IsothermalityEcoSISTEM.LandCoverTypologyEcoSISTEM.LandmassesAboveEcoSISTEM.LargestLandmassEcoSISTEM.LatLongEcoSISTEM.LayerAggregatedEcoSISTEM.LayerCacheEcoSISTEM.LayerCollectionEcoSISTEM.LayerInputEcoSISTEM.LayerKeptExactlyEcoSISTEM.LayerPlanEcoSISTEM.LayerRecordEcoSISTEM.LayerResampledEcoSISTEM.LayerSpecEcoSISTEM.LegacyLossEcoSISTEM.LongTailKernelEcoSISTEM.LookupEcoSISTEM.MPIEcosystemEcoSISTEM.MPIGridLandscapeEcoSISTEM.MaskSpecEcoSISTEM.MeasuredAcrossProjectionEcoSISTEM.MonthOfYearSeriesEcoSISTEM.MultiplicativeFitEcoSISTEM.MultiplicativeFit2EcoSISTEM.MultiplicativeFit3EcoSISTEM.NaturalEarthLevelEcoSISTEM.NaturalEarthSpecEcoSISTEM.NaturalEarthSpecEcoSISTEM.NeverScheduledEcoSISTEM.NicheAxisEcoSISTEM.NicheSpecEcoSISTEM.NicheSuitabilityEcoSISTEM.NicheToleranceEcoSISTEM.NicheToleranceEcoSISTEM.NicheToleranceEcoSISTEM.NoChangeEcoSISTEM.NoFitCategoricalEcoSISTEM.NoFitContinuousEcoSISTEM.NoGrowthEcoSISTEM.NoLayerChangeEcoSISTEM.NoMovementEcoSISTEM.NoMovementEcoSISTEM.NoRealWorldPositionEcoSISTEM.OffsetByEcoSISTEM.OverlapsEcoSISTEM.ParamRoleEcoSISTEM.PatternedChangeEcoSISTEM.PatternedLayerChangeEcoSISTEM.PeakedSpecEcoSISTEM.PerCellAccumulationPeriodEcoSISTEM.PerSliceAccumulationPeriodEcoSISTEM.PeriodicEcoSISTEM.PopGrowthEcoSISTEM.PrecipitationEcoSISTEM.PrecipitationAxisEcoSISTEM.PrecipitationSeasonalityEcoSISTEM.ProblemEcoSISTEM.ProblemNoticeEcoSISTEM.ProblemWarningEcoSISTEM.RainToleranceEcoSISTEM.RandomCellsEcoSISTEM.RasterDataAcceptableCodeEcoSISTEM.RateChangeEcoSISTEM.ReactivateEcoSISTEM.RegimeCollection2EcoSISTEM.RegimeCollection3EcoSISTEM.RegionMatchEcoSISTEM.RegionReportEcoSISTEM.RelativeChangeEcoSISTEM.RelativeHumidityEcoSISTEM.RelativeHumidityAxisEcoSISTEM.RelativeHumidityRangeEcoSISTEM.RemoveAbundanceEcoSISTEM.RepeatAtEndEcoSISTEM.ReplaceWithEcoSISTEM.ResourceEcoSISTEM.RevertToLayerEcoSISTEM.RoleEcoSISTEM.RoundedFromMeasurementEcoSISTEM.SavedLandscapeEcoSISTEM.SavedLandscapeEcoSISTEM.SeriesChangeEcoSISTEM.SeriesLayerChangeEcoSISTEM.SetChangeEcoSISTEM.SetLandCoverEcoSISTEM.ShapeBufferEcoSISTEM.ShapeConvexHullEcoSISTEM.ShapeDifferenceEcoSISTEM.ShapeIntersectionEcoSISTEM.ShapeSimplifyEcoSISTEM.ShapeSpecEcoSISTEM.ShapeUnionEcoSISTEM.SimpleCategoricalToleranceEcoSISTEM.SiteWaterBalanceEcoSISTEM.SnowWaterEquivalentEcoSISTEM.SolarRadiationEcoSISTEM.SolarRadiationAxisEcoSISTEM.SolarRadiationRangeEcoSISTEM.SourceSpecEcoSISTEM.SpaceAxisEcoSISTEM.Spatial2DEcoSISTEM.SpatialKindEcoSISTEM.SpatialLocationEcoSISTEM.SpatialSizeEcoSISTEM.SpeciesListEcoSISTEM.SpeciesListEcoSISTEM.SpeciesListEcoSISTEM.SpeciesRequirementCollectionEcoSISTEM.SpreadingCellsEcoSISTEM.SteadyLayerChangeEcoSISTEM.StudyAreaEcoSISTEM.StudyAreaReportEcoSISTEM.StudyGridEcoSISTEM.SumOfLayerChangesEcoSISTEM.SupplyEcoSISTEM.SupplyCollection2EcoSISTEM.SurfaceAreaEcoSISTEM.SyntheticDataEcoSISTEM.TakenFromAlignedLayerEcoSISTEM.TempToleranceEcoSISTEM.TemperatureEcoSISTEM.TemperatureAxisEcoSISTEM.TemperatureRangeEcoSISTEM.TemperatureSeasonalityEcoSISTEM.ToleranceCollection2EcoSISTEM.ToleranceCollection3EcoSISTEM.TorusEcoSISTEM.TrapezeEcoSISTEM.TrapezoidEcoSISTEM.TypologyAxisEcoSISTEM.UndatedSeriesEcoSISTEM.UnifEcoSISTEM.UniformSpecEcoSISTEM.VapourPressureEcoSISTEM.VapourPressureDeficitEcoSISTEM.VapourPressureDeficitAxisEcoSISTEM.VapourPressureDeficitRangeEcoSISTEM.VaryingEcoSISTEM.WaterAxisEcoSISTEM.WindSpeedEcoSISTEM.WindSpeedAxisEcoSISTEM.WindSpeedRangeEcoSISTEM.WithinBase.append!Base.readBase.readBase.readBase.readBase.readBase.readBase.readEcoSISTEM.ClimatePref.downresolutionEcoSISTEM.ClimatePref.downresolution!EcoSISTEM.ClimatePref.extractvaluesEcoSISTEM.ClimatePref.readCERAEcoSISTEM.ClimatePref.readCHELSA_monthlyEcoSISTEM.ClimatePref.readCRUTSEcoSISTEM.ClimatePref.readERAEcoSISTEM.ClimatePref.readERAEcoSISTEM.ClimatePref.readERAEcoSISTEM.ClimatePref.readworldclimEcoSISTEM.ClimatePref.upresolutionEcoSISTEM.GaussTraitEcoSISTEM.HabitatLossEcoSISTEM.LayerUpdateEcoSISTEM.RainfallChangeEcoSISTEM.SurfaceSpecEcoSISTEM.TempChangeEcoSISTEM.TempFluctEcoSISTEM.Units.month_durationEcoSISTEM.Units.month_durationEcoSISTEM.abundancesEcoSISTEM.applyinterventions!EcoSISTEM.arenoderecordsemptyEcoSISTEM.assetdirEcoSISTEM.assetpathEcoSISTEM.assigntraits!EcoSISTEM.bioclimhabitatEcoSISTEM.boundingboxEcoSISTEM.boundsEcoSISTEM.brownian_motionEcoSISTEM.build_ecosystemEcoSISTEM.build_habitatEcoSISTEM.build_speciesEcoSISTEM.calc_lookup_moves!EcoSISTEM.canonicalunitEcoSISTEM.cellregimeEcoSISTEM.cellsupplyEcoSISTEM.changeunitEcoSISTEM.check_boundsEcoSISTEM.checkcoverageEcoSISTEM.checkfileEcoSISTEM.checkfileEcoSISTEM.clearcache!EcoSISTEM.compress_landcoverEcoSISTEM.continuous_evolveEcoSISTEM.convert_coordsEcoSISTEM.cyclic_changeEcoSISTEM.demandtypeEcoSISTEM.densitywidthEcoSISTEM.discrete_evolveEcoSISTEM.dispersesafelyEcoSISTEM.empty_landscapeEcoSISTEM.emptypopulate!EcoSISTEM.equalpopEcoSISTEM.erahabitatEcoSISTEM.extract_valuesEcoSISTEM.fitbrownianEcoSISTEM.gatherabundanceEcoSISTEM.gatherdiversityEcoSISTEM.generate_storageEcoSISTEM.generate_storageEcoSISTEM.genlookupsEcoSISTEM.getcellareaEcoSISTEM.getcellareasEcoSISTEM.getcellatEcoSISTEM.getcellcountEcoSISTEM.getcellsizeEcoSISTEM.getcellsizesEcoSISTEM.getdemandEcoSISTEM.getdispersaldistEcoSISTEM.getdispersalvarEcoSISTEM.getdistEcoSISTEM.getgridareaEcoSISTEM.getgridshapeEcoSISTEM.getkernelsEcoSISTEM.getlatEcoSISTEM.getlongEcoSISTEM.getlookupEcoSISTEM.getlookupEcoSISTEM.getnichefitEcoSISTEM.getprefEcoSISTEM.getprefEcoSISTEM.getprefEcoSISTEM.getregimeEcoSISTEM.getregimeEcoSISTEM.getregimeEcoSISTEM.getrngEcoSISTEM.getspeciesstorageEcoSISTEM.getsupplyEcoSISTEM.gettimesEcoSISTEM.gettoleranceEcoSISTEM.gettraitsEcoSISTEM.hasdataEcoSISTEM.in_memory_rasterEcoSISTEM.investigate_regionsEcoSISTEM.investigate_study_areaEcoSISTEM.iscategoricalEcoSISTEM.landcoverclassEcoSISTEM.landcoverhabitatEcoSISTEM.layeraxesEcoSISTEM.layeraxisEcoSISTEM.layerinfoEcoSISTEM.layerrateEcoSISTEM.layersbyaxisEcoSISTEM.layerunitEcoSISTEM.loadfileEcoSISTEM.makerngsEcoSISTEM.makeuniqueEcoSISTEM.materialiseEcoSISTEM.move!EcoSISTEM.naturalearth_levelsEcoSISTEM.naturalearth_regionsEcoSISTEM.nichefitcombineEcoSISTEM.pairEcoSISTEM.paramunitsEcoSISTEM.peakedgradhabitatEcoSISTEM.populate!EcoSISTEM.populate_by_tolerance!EcoSISTEM.raingradEcoSISTEM.raingradhabitatEcoSISTEM.randomnichesEcoSISTEM.read_distributionEcoSISTEM.readfileEcoSISTEM.regimeupdate!EcoSISTEM.repopulate!EcoSISTEM.repopulate_by_tolerance!EcoSISTEM.reroot!EcoSISTEM.resettime!EcoSISTEM.resettraits!EcoSISTEM.resource_adjustmentEcoSISTEM.retrieve_era5EcoSISTEM.root_to_tipsEcoSISTEM.setchange!EcoSISTEM.simplehabitatEcoSISTEM.simplenichehabitatEcoSISTEM.simpleregimeEcoSISTEM.simpleregimeEcoSISTEM.simulate!EcoSISTEM.simulate!EcoSISTEM.simulate!EcoSISTEM.simulate_action!EcoSISTEM.simulate_record!EcoSISTEM.simulate_record_diversity!EcoSISTEM.simulationdateEcoSISTEM.simulationtimeEcoSISTEM.sinusoidalEcoSISTEM.sourcecrsEcoSISTEM.species_blocksizeEcoSISTEM.speciesdemandEcoSISTEM.speciesdispersalEcoSISTEM.speciestoleranceEcoSISTEM.suitabilityEcoSISTEM.supplytypeEcoSISTEM.supplyupdate!EcoSISTEM.synchronise_from_cols!EcoSISTEM.synchronise_from_rows!EcoSISTEM.tempgradEcoSISTEM.tempgradhabitatEcoSISTEM.totalsupplyEcoSISTEM.unziptempEcoSISTEM.update!EcoSISTEM.update!EcoSISTEM.update_resource_usage!EcoSISTEM.updatesimulation!EcoSISTEM.varcovarEcoSISTEM.worldclimhabitatEcoSISTEM.@nicheaxis