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.AbstractRecorderEcoSISTEM.AbstractRegimeEcoSISTEM.AbstractRegionEcoSISTEM.AbstractReportStageEcoSISTEM.AbstractRunCalendarEcoSISTEM.AbstractScheduleEcoSISTEM.AbstractSeriesCalendarEcoSISTEM.AbstractSeriesEndEcoSISTEM.AbstractShapeOperationEcoSISTEM.AbstractShapeRuleEcoSISTEM.AbstractShapeSpecEcoSISTEM.AbstractSpatialRelationEcoSISTEM.AbstractSpecEcoSISTEM.AbstractSpeciesEcoSISTEM.AbstractSpeciesRequirementEcoSISTEM.AbstractSupplyEcoSISTEM.AbstractSyntheticLayerSpecEcoSISTEM.AbstractSyntheticMaskSpecEcoSISTEM.AbstractSyntheticSpecEcoSISTEM.AbstractToleranceEcoSISTEM.AbstractTopologyEcoSISTEM.ActiveCellsEcoSISTEM.AddAbundanceEcoSISTEM.AddAbundanceTableEcoSISTEM.AddSpeciesEcoSISTEM.AdditiveFitEcoSISTEM.AdditiveFit2EcoSISTEM.AdditiveFit3EcoSISTEM.AdoptedFromLayersEcoSISTEM.AgreedByAllLayersEcoSISTEM.AllCellsEcoSISTEM.AllTerritoriesEcoSISTEM.AltitudeEcoSISTEM.AlwaysMovementEcoSISTEM.AnyOverlapEcoSISTEM.AsBuiltEcoSISTEM.AsInvestigatedEcoSISTEM.AtDatesEcoSISTEM.AtTimeEcoSISTEM.AtTimesEcoSISTEM.AxisNodeEcoSISTEM.BetweenTimesEcoSISTEM.BirthOnlyMovementEcoSISTEM.BoundedEcoSISTEM.BrownianEcoSISTEM.CDSRequestEcoSISTEM.CDSRequestEcoSISTEM.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.DatasetRecordEcoSISTEM.DatedSeriesEcoSISTEM.DayAxisEcoSISTEM.DayCountEcoSISTEM.DayOfYearEcoSISTEM.DeactivateEcoSISTEM.DefaultEcosystemEcoSISTEM.DemandEcoSISTEM.DemandCollection2EcoSISTEM.DerivedDataEcoSISTEM.DiversitySetEcoSISTEM.DiversitySetEcoSISTEM.ERAEcoSISTEM.EcoSISTEMSourceEcoSISTEM.EcosystemEcoSISTEM.EcosystemEcoSISTEM.EcosystemEcoSISTEM.EdgeTopologyEcoSISTEM.EnclosesEcoSISTEM.EqualPopEcoSISTEM.ErrorAtEndEcoSISTEM.EvapotranspirationEcoSISTEM.EvapotranspirationAxisEcoSISTEM.EvapotranspirationRangeEcoSISTEM.EveryIntervalEcoSISTEM.EveryStepEcoSISTEM.EveryYearEcoSISTEM.ExactDatesEcoSISTEM.FractionWithinEcoSISTEM.FrostChangeFrequencyEcoSISTEM.FullyWithinEcoSISTEM.GaussEcoSISTEM.GaussianKernelEcoSISTEM.GivenByUserEcoSISTEM.GradientSpecEcoSISTEM.GridHabitatEcoSISTEM.GridLandscapeEcoSISTEM.GridLandscapeEcoSISTEM.GrowingSeasonPrecipitationEcoSISTEM.HeterogeneityEcoSISTEM.HoldAtEndEcoSISTEM.HumidityAxisEcoSISTEM.IncrementByEcoSISTEM.InputRecordEcoSISTEM.InterventionEcoSISTEM.InterventionSetEcoSISTEM.IsRasterDataEcoSISTEM.IslandEcoSISTEM.IsothermalityEcoSISTEM.LandCoverTypologyEcoSISTEM.LandmassesAboveEcoSISTEM.LargestLandmassEcoSISTEM.LatLongEcoSISTEM.LayerAggregatedEcoSISTEM.LayerCacheEcoSISTEM.LayerCollectionEcoSISTEM.LayerInputEcoSISTEM.LayerKeptExactlyEcoSISTEM.LayerPlanEcoSISTEM.LayerRecordEcoSISTEM.LayerResampledEcoSISTEM.LayerSpecEcoSISTEM.LegacyLossEcoSISTEM.LongTailKernelEcoSISTEM.LookupEcoSISTEM.MPIEcosystemEcoSISTEM.MPIGridLandscapeEcoSISTEM.MaskSpecEcoSISTEM.MeanMonthsEcoSISTEM.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.ProvenanceEcoSISTEM.RainToleranceEcoSISTEM.RandomCellsEcoSISTEM.RasterDataAcceptableCodeEcoSISTEM.RasterSpecEcoSISTEM.RateChangeEcoSISTEM.ReactivateEcoSISTEM.RecordAbundanceEcoSISTEM.RecordDiversityEcoSISTEM.RegimeCollection2EcoSISTEM.RegimeCollection3EcoSISTEM.RegionMatchEcoSISTEM.RegionReportEcoSISTEM.RelativeChangeEcoSISTEM.RelativeHumidityEcoSISTEM.RelativeHumidityAxisEcoSISTEM.RelativeHumidityRangeEcoSISTEM.RemoveAbundanceEcoSISTEM.RepeatAtEndEcoSISTEM.ReplaceWithEcoSISTEM.ResourceEcoSISTEM.RevertToLayerEcoSISTEM.RoleEcoSISTEM.RoundedFromMeasurementEcoSISTEM.SaveAbundanceEcoSISTEM.SavedLandscapeEcoSISTEM.SavedLandscapeEcoSISTEM.SeriesChangeEcoSISTEM.SeriesLayerChangeEcoSISTEM.SetChangeEcoSISTEM.SetLandCoverEcoSISTEM.ShapeBufferEcoSISTEM.ShapeConvexHullEcoSISTEM.ShapeCoverageEcoSISTEM.ShapeDifferenceEcoSISTEM.ShapeIntersectionEcoSISTEM.ShapeMaskSpecEcoSISTEM.ShapeSimplifyEcoSISTEM.ShapeSpecEcoSISTEM.ShapeUnionEcoSISTEM.SimpleCategoricalToleranceEcoSISTEM.SiteWaterBalanceEcoSISTEM.SnowWaterEquivalentEcoSISTEM.SoilVolumeEcoSISTEM.SoilWaterVolumeEcoSISTEM.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.TwentyCREcoSISTEM.TypologyAxisEcoSISTEM.UndatedSeriesEcoSISTEM.UnifEcoSISTEM.UniformSpecEcoSISTEM.VapourPressureEcoSISTEM.VapourPressureDeficitEcoSISTEM.VapourPressureDeficitAxisEcoSISTEM.VapourPressureDeficitRangeEcoSISTEM.VaryingEcoSISTEM.VectorDataEcoSISTEM.WaterAxisEcoSISTEM.WholeBoundingBoxEcoSISTEM.WindSpeedEcoSISTEM.WindSpeedAxisEcoSISTEM.WindSpeedRangeEcoSISTEM.WithinBase.append!Base.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.RasterFileSpecEcoSISTEM.SurfaceSpecEcoSISTEM.TempChangeEcoSISTEM.TempFluctEcoSISTEM.Units.month_durationEcoSISTEM.Units.month_durationEcoSISTEM.abundancesEcoSISTEM.applyinterventions!EcoSISTEM.arenoderecordsemptyEcoSISTEM.assetdirEcoSISTEM.assetpathEcoSISTEM.assigntraits!EcoSISTEM.bioclimhabitatEcoSISTEM.boundingboxEcoSISTEM.boundsEcoSISTEM.brownian_motionEcoSISTEM.build_abundance_tableEcoSISTEM.build_ecosystemEcoSISTEM.build_habitatEcoSISTEM.build_speciesEcoSISTEM.calc_lookup_moves!EcoSISTEM.canonicalunitEcoSISTEM.cellregimeEcoSISTEM.cellsupplyEcoSISTEM.changeunitEcoSISTEM.check_boundsEcoSISTEM.checkcoverageEcoSISTEM.checkfileEcoSISTEM.checkfileEcoSISTEM.class_fractionsEcoSISTEM.clearcache!EcoSISTEM.compress_landcoverEcoSISTEM.continuous_evolveEcoSISTEM.convert_coordsEcoSISTEM.cyclic_changeEcoSISTEM.datasetinfoEcoSISTEM.demandtypeEcoSISTEM.densitywidthEcoSISTEM.discrete_evolveEcoSISTEM.dispersesafelyEcoSISTEM.dominant_classEcoSISTEM.empty_landscapeEcoSISTEM.emptypopulate!EcoSISTEM.equalpopEcoSISTEM.era5requestsEcoSISTEM.erahabitatEcoSISTEM.extract_valuesEcoSISTEM.fetchfilesEcoSISTEM.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.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.provenanceEcoSISTEM.provenanceEcoSISTEM.provenanceEcoSISTEM.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!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.verifyassetsEcoSISTEM.worldclimhabitatEcoSISTEM.write_provenanceEcoSISTEM.@nicheaxis
No extension is in this list. Every public name whose implementation lives in an extension keeps its docstring on a method-less stub in the parent, so the parent's modules document everything.
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: 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: RasterSpec (read raster data - a catalogued layer, or a file that belongs to no dataset), 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 eight: Deactivate, Reactivate, SetLandCover, SetChange, AddAbundance, RemoveAbundance, AddAbundanceTable 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. Eight 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 two exponents that say how those rates respond to the environment. EqualPop, PopGrowth and NoGrowth are the concrete forms.
Every subtype carries the same four 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.AbstractRecorder — Type
AbstractRecorderA value that keeps something from a run each time a simulate! schedule fires - RecordAbundance, RecordDiversity or SaveAbundance. Pass one to simulate! in place of a callback, or call recorder(eco, occurrence) from a callback of your own to keep several things from one run. Each holds the Provenance of the run as it stood at its last write, which provenance returns.
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.AbstractRunCalendar — Type
AbstractRunCalendarHow a run relates real dates to elapsed time - ExactDates or MeanMonths. Given as the calendar keyword of build_ecosystem, and used by everything in the run that turns a date into elapsed time or back: where each DatedSeries slice and the epoch fall, and the date simulationdate reports.
EcoSISTEM.AbstractSchedule — Type
AbstractScheduleWhen an Intervention fires - EveryStep, AtTime, AtTimes, BetweenTimes, EveryInterval, AtDates, EveryYear 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.AbstractShapeRule — Type
AbstractShapeRuleAbstract supertype of the rules that decide which cells a shape activates: AnyOverlap, FractionWithin, FullyWithin and WholeBoundingBox.
All but the last read one number - the share of the cell's own rectangle lying inside the shape - and admit a tolerance of one part in 100 000 of a cell, so a cell the shape meets only along an edge stays out while a cell covered to within rounding counts as covered.
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.
Which cells a shape activates is a question about rasterising rather than about geometry, so it is ShapeMaskSpec's: a shape used as a within mask on its own covers every cell at least half inside it, and ShapeMaskSpec(shape, rule) states any other rule.
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.AddAbundanceTable — Type
AddAbundanceTable(table)Add individuals to cells as a table lists them, each row naming a species, a cell, a count and a time - a population seeded from dated records, for instance.
It goes in an Intervention of its own, with EveryStep. Its rows say when, so each step adds the rows whose time falls within it, and a row at or before the start of the run is added to the starting state. The intervention's region filters the rows: ActiveCells() drops those in an inactive cell, and CellMask(mask) those outside the mask.
The rows of one species and cell that fall in the same step are summed and then rounded to a whole number of individuals, ties to even. A date is placed through the run's epoch and calendar as AtDates places one, and must fall at the end of a step unless the steps are a day or shorter. build_abundance_table writes a table in this form from species names and grid positions.
The table may be streamed. One offering whole columns - a DataFrame, a NamedTuple of vectors, a memory-mapped Arrow file - is searched for the rows each step needs, so the operation holds no state and can serve any number of runs. One offering only rows, such as a CSV.Rows or a generator of named tuples, is read once, forwards, as the run proceeds: its rows must be in time order, and the operation serves a single run.
Arguments
table: any Tables.jl source with the columnsspecies(a species' name or its index in the species list),cell(a cell's linear index into the grid, which is its column in the abundance matrix, or itsCartesianIndex(y, x)),time(an elapsed time from the start of the run, or a date) and, optionally,count(how many individuals, one per row without it).
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. A RecordAbundance writes into an array sized before the run starts, so a run that gains species needs RecordAbundance(eco, ntimes, maxspecies = ...), or storage from 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.AnyOverlap — Type
AnyOverlap()Activate every cell the shape covers any part of.
The most inclusive rule: a coastal cell is simulated whatever share of it is land, so no ground the shape names is left out of the grid.
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.AtDates — Type
AtDates(dates)Fires once for each of dates, on the step that reaches each - AtTimes given real dates rather than elapsed times. A date becomes an elapsed time through the run's epoch and calendar (see build_ecosystem), so a run with no epoch refuses one before its first step. A date at or before the epoch acts on the starting state, before the first step, as an elapsed time at or before zero does. A date the run reaches must fall at the end of a step, or the step be no longer than a day: one falling inside a longer step would be acted on late, so the run is refused before its first step.
Arguments
dates: theDates orDateTimes to fire at.
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. A time at or before the start of the run acts on the starting state, before the first step.
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]. It acts over steps taken, so not at the start of the run even when from is zero.
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.CDSRequest — Type
CDSRequest(dataset::AbstractString, request::AbstractDict, path::AbstractString)A file fetched from the Copernicus Climate Data Store on first use and kept at path: the CDS dataset to ask ("reanalysis-era5-single-levels-monthly-means"), the request as the CDS takes it (product type, variable, years, months, area, format), and where the answer is written. Nothing is fetched at construction; assetpath fetches it through CDSAPI.jl when path does not yet exist, so a file already downloaded is never asked for twice, and writes a provenance record beside it holding the request and the CDS job. An entry of a RasterSpec's files. CDSRequest(ERA, code; years, path) builds one from a catalogued layer instead of the CDS's own names.
Fields
dataset: the CDS dataset name.request: the request body, keys as the CDS documents them, values strings or vectors of strings.path: where the file lives once fetched.
EcoSISTEM.CDSRequest — Method
CDSRequest(::Type{ERA}, code; years, path, months = 1:12, area = nothing)Build the Climate Data Store request for one ERA5 monthly-means layer from its catalogue code, to be fetched into path on first use: CDSRequest(ERA, "t2m", years = 1990:1999, path = "era5_t2m_1990s.nc"). The CDS's own name for the variable comes from the ERA table's Request column, so a code with none is refused.
Arguments
code: the layer, as theERAtable spells it.years: the years to ask for, a range or a vector.path: where the file lives once fetched.months: the months of each year,1:12by default.area:(north, west, south, east)in degrees to cut to, ornothingfor the globe.
EcoSISTEM.CERA — Type
CERA <: EcoSISTEMSourceThe CERA-20C reanalysis archive, as a data source: one netCDF file per decade, named as for ERA - SourceSpec(CERA, "t2m", files = decades), joined along time on read.
Fieldless, as ERA is.
EcoSISTEM.CRUTS — Type
CRUTS <: EcoSISTEMSourceThe CRU TS archive, as a data source: a directory of monthly GeoTIFFs, named with SourceSpec(CRUTS, "tavg", directory = dir) and read as one series in file-name order.
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; path = nothing)An immutable descriptor for a file downloaded from url on first use: into EcoSISTEM.assetdir(owner = owner) under the URL's own file name, or to path where one is given, which is how a project keeps a download under its own data directory. Nothing is downloaded at construction - call assetpath to get the local path, downloading it first if it is not there. The download is resumed from whatever an interrupted one left, and a provenance record is written beside the file (see provenance).
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, and the catalogue row its provenance record is filled from where the owner is a data source.url: where to fetch it from.path: where it lives once fetched, ornothingfor the owner's cache directory.
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 study area is decided, so it narrows the grid the habitat is then built on.
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...; axis, combinestage = CombineOnTargetGrid(),
atend = RepeatAtEnd(), calendar = nothing)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.atend,calendar: for a combine returning a raster with a time axis, what the series it becomes does past its last slice and what its coordinates mean, as onSourceSpec.
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())Combine several shapes into one mask - the union of the United Kingdom, Ireland and the Isle of Man, a country with an island group cut out of it, or a study area of your own buffered by a distance - or transform one.
Shapes 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; read(spec) gives the pieces of ground the result is.
# 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, each wanting two or more members; or how one is transformed -ShapeBuffer,ShapeSimplifyorShapeConvexHull, each wanting exactly one; or a function handed one geometry per member and returning one.members: any shape specs - aShapeSpecof your own, aNaturalEarthSpec, or a nestedConstructedShapeSpec- as many as the operation wants.coverage: which components of the result to keep, applied after the operation -AllTerritoriesby default, since a combination usually means all of what it built.
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.DatasetRecord — Type
DatasetRecordA dataset's row of the shipped datasets.csv: the fixed facts about a whole data source that no layer row carries, returned by datasetinfo.
dataset: the source type as it is written -WorldClim{BioClim},CHELSA{Climate},ERA.format: how the files are encoded,:GeoTIFFor:netCDF, which chooses the backend that opens them, or:Shapefilefor a source of zipped vector outlines.longituderange: the longitude convention the files use,(-180°, 180°)or(0°, 360°), ornothingto read it off each file.crs: the coordinate reference system, anEPSGcode or aWellKnownText, ornothing.resolution: the cell sizes the provider offers, each a length or an angle, ornothing.extent: the ground the dataset covers, anExtents.ExtentofY/Xbounds in degrees, ornothing.fetch: how files are obtained -:getraster(throughRasterDataSources),:cds(a Copernicus request),:https(a plain download) or:none(they must be given).url,doi,licence,version,citation,notes: provenance, blank where unknown;citationis the text a paper prints for the dataset, as the DOI resolves to it.
A blank cell means ask the file, so every field but dataset, format and fetch may be nothing. A recorded fact the file can contradict is checked on the first read of that dataset - longituderange, crs, resolution and extent are header facts, compared against the file's own and refused, naming the table, when they disagree. Provenance and format are not checked: a wrong format fails to open on its own.
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: monthly means on single levels, one netCDF file per variable per decade as the Climate Data Store serves them. Name a layer with SourceSpec(ERA, "t2m", file = path) - or files = decades in time order, or a EcoSISTEM.CDSRequest entry fetched on first use - and read it, or build on it, like any other; the ERA layer table supplies the unit, axis and accumulation period.
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, VectorData 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 - and calendar the AbstractRunCalendar its dates are placed by. inputs holds the InputRecords of published data belonging to the run as a whole - those given to build_ecosystem, and those of every intervention that has acted - which provenance lists.
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.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.
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.EveryInterval — Type
EveryInterval(interval::Unitful.Time)Fires at every whole multiple of interval - 0, interval, 2interval and on - each on the step that reaches it, exactly as AtTimes would over that unending list. The multiples are counted from the start of the run, so the answer does not depend on the timestep; the multiple at zero acts on the starting state, before the first step.
Arguments
interval: the elapsed simulation time between firings, which must be positive.
EcoSISTEM.EveryStep — Type
EveryStep() <: AbstractSchedule - fires after every timestep, and not at the start.EcoSISTEM.EveryYear — Type
EveryYear(; month = 1, day = 1)Fires on the step that reaches day of month in every year of the run, from the epoch on - an anniversary on the epoch acts on the starting state, and one before it does not fire. Its dates are placed through the run's epoch and calendar as AtDates's are, so a run with no epoch refuses it before its first step, and so is each anniversary checked against the steps as a date is: under ExactDates 1 January is 365 or 366 days after the one before, so no step of month_mean_duration or year ends on every one, while under MeanMonths every twelfth month_mean_duration does.
Arguments
month: the month of the year, from 1 to 12.day: the day of that month, which must be one every year has - so 29 February is refused.
EcoSISTEM.ExactDates — Type
ExactDates()Dates are placed by the real time between them, so a slice dated 1 March 2000 falls 60 days after one dated 1 January 2000. The default. Real months are 28 to 31 days long, so a timestep of month_mean_duration against a dated monthly series leaves some months never current, and simulate! refuses such a run before its first step.
EcoSISTEM.FractionWithin — Type
FractionWithin(fraction)Activate every cell the shape covers at least fraction of.
FractionWithin(0.5) is what a shape passed as within means on its own, and roughly keeps the region's area: the ground lost from the cells that are less than half covered is about the ground gained from the cells that are more.
Arguments
fraction: the share of a cell that must be covered - greater than 0, and at most 1. WriteAnyOverlapfor any cover at all, which no positive threshold expresses.
EcoSISTEM.FrostChangeFrequency — Type
FrostChangeFrequency <: TemperatureAxis - frost change frequency, the number of days the temperature crosses 0 °C (BioClimPlus fcf; dimensionless).EcoSISTEM.FullyWithin — Type
FullyWithin()Activate only the cells the shape covers completely.
The conservative rule, for a run that must put nothing on ground the shape does not name: a coastal cell with any water in it is dropped. It is the same test as FractionWithin(1.0).
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.
Under MPI with more than one rank this is a collective call, made on every rank in the same order; see Building is collective.
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.InputRecord — Type
InputRecord(; role, dataset, code = nothing, path = nothing, url = nothing, request = nothing,
job = nothing, fetched = nothing, bytes = nothing, sha256 = nothing, doi = "",
licence = "", version = "", citation = "")The provenance of one published input to an experiment: a file this package fetched, or a dataset you handed it that it never fetched - an occurrence download, a trait table, a phylogeny. One shape for both, so that everything an ecosystem was built from can be listed together and a paper's references written from the list. provenance reads the records the package wrote; you write one for anything it could not have known about.
Fields
role: which part of the system the input entered by -:habitatfor a layer,:regionfor a shape or a named region's outline,:species,:phylogeny,:dispersal,:demographyor:interventionfor what you attached,:abundancefor records a starting population was placed from,:statefor a saved run a forward run starts from,:softwarefor the package itself.dataset: the source's name - a catalogue key such asTwentyCRorWorldClim{BioClim}, or your own name for a dataset of yours.code: which layer of the source, where the input is one.path: the file's own name, or a path relative to wherever its record sits - never an absolute one, since a record is meant to be committed and shared.url: where it was fetched from, where it was.request: the request body sent to a service, as it was sent.job: the identifier a service gave the request.fetched: when it was fetched, in UTC.bytes,sha256: the file's size and checksum at fetch, which is what tells a truncated or replaced copy from the original.doi,licence,version,citation: the dataset's own, blank where unknown;citationis the text a paper prints.
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.
An intervention built from published data - a land-use scenario, the occurrence records a population is seeded from - says so with provenance, an InputRecord or a vector of them. The records join the ecosystem's own the first time the intervention acts, so provenance of the ecosystem lists an intervention that has acted and not one that never fired.
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.inputs: the files each read came from, anInputRecordper file under the read's own key - a file's provenance record where it has one, and otherwise its name and the catalogue's facts about its dataset.
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. documentedceiling is its companion: the largest value the layer's documented unit could plausibly reach, from the DocumentedCeiling column, or nothing where the table says none. It is what tells a layer that is still published at publishedscale from one that has since been corrected, and so is only set where publishedscale is.
verticalextent is where above or below the surface the layer is measured, from the VerticalExtent column: a single signed height (2m for a 2 metre air temperature) or a from..to pair for a layer of ground (-7cm..0cm for the top soil layer), heights positive upward, or nothing for a surface value. Every reanalysis has one. A range on a layer whose values are a fraction of the layer's volume is what turns that fraction into a depth on read, and on a file holding several soil layers it is what selects the one to take; otherwise it is recorded, not checked.
file is where the layer's file is fetched from, for a source whose datasets.csv row says its files come by plain https download - a URL from the File column - or nothing where the table has no such column or the cell is blank. request is the name the layer goes by in a request to the source's service - the Climate Data Store's 2m_temperature for ERA5's t2m, from the Request column - or nothing likewise; EcoSISTEM.CDSRequest builds a request from it.
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 aggregated onto the grid from the source cells covering each of its cells, weighted by how much of the cell each covers - not exact, because the grid's cells are not unions of the layer's, which is the thing the whole alignment story exists to avoid. reason says why it was unavoidable. Where the grid is at least twice as coarse as the layer, the layer is first aggregated exactly on its own lattice by the whole part of the ratio and only the residual is sampled; reason says so too.
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. Every rank takes the first rank's species list and seed when the ecosystem is built, so a species list or seed drawn at random on each rank still gives one ecosystem.
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.MeanMonths — Type
MeanMonths()Every calendar month counts as month_mean_duration (30.44 days). A dated slice falls at the number of whole calendar months since its series' first slice times that duration, whatever day of the month it is dated, and the epoch falls at its own month plus the fraction of that month it has reached - as a MonthOfYearSeries climatology is already placed. A monthly series stepped by month_mean_duration then makes every month current exactly once. A dated series with two slices in one calendar month is refused, since counting months says nothing about days.
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())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.
EcoSISTEM.NaturalEarthSpec — Method
NaturalEarthSpec(match::EcoSISTEM.RegionMatch; coverage = AllTerritories())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.seed: an integer fixing the layout. It is drawn from a stream of its own, so the same seed gives the same map in any process whatever else has used the global random generator;nothing, the default, draws from the global generator.
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.
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.
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.Provenance — Type
ProvenanceWhat a study area, a habitat or an ecosystem can say about how it came to be, returned by provenance: the software, the published inputs, the grid and, for an ecosystem, the run.
Fields
software: a named tuple of thepackage, itsversion, thedoievery version of it is cited by, and thejuliaversion.inputs: anInputRecordper input, one per file, in a fixed order.grid: a named tuple of the grid'scrs(nothingfor a synthetic grid), itscellsize, theextentits cells cover, and how manycellsit has and how many of them areactive.run: for an ecosystem, a named tuple of itsseed, itsepoch(nothingwithout one), the runcalendarits dates were placed by and the timeelapsed;nothingfor a study area or a habitat.
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.RasterSpec — Type
RasterSpec{A <: NicheAxis, U} <: AbstractLazySpecName raster data to be read, without reading it - a layer of a catalogued data source, written SourceSpec(source, code; ...), or a raster file that belongs to no dataset, written RasterFileSpec(path; axis, ...). It holds no grid array: the read, the cut and the resample happen only when it is materialised onto a decided grid, so a global file costs the window the study area needs rather than the globe, and refining an area re-reads nothing.
Four things say what is read. What the data is: the source type and the code of the layer, which is what the shipped catalogue is keyed on for a unit and an axis, and which the caller may override; a file that belongs to no dataset has no code, so it must be told both. Where the files are: an explicit list, or nothing for a source that resolves its own, as a catalogued dataset does. How it is read: cut windows the read to a box, scale coarsens by a whole number of cells a side, and fn says how a block is reduced. And how the files become one array in time: times labels the slices where the files cannot, atend says what the series does past its last slice, and calendar what its coordinates mean.
Fields
source: the data source, a type markedEcoSISTEM.IsRasterData- a dataset such asWorldClim{BioClim}, orSyntheticDatafor a file that belongs to no dataset.code: which layer of the source, as oneCODE_TYPEor a vector of them;nothingfor a bare file, and never for a catalogued source, since a whole-dataset spec resolves the dataset's own code list at construction so that every layer's identity is known before anything is read and each can keep its own unit.files: the files to read, in time order, each a local path, theEcoSISTEM.CachedAsseta URL becomes, or aEcoSISTEM.CDSRequestfetched on first use;nothingwhere the source resolves them itself. Each file is opened by the backend its source's catalogue row names, so a netCDF file without an extension reads.unit: the physical unit attached on read.NoUnitswhere a multi-layer spec's layers disagree, as a neutral placeholder, and for a file given none.cut: anExtents.Extentof°intervals to window the read to, ornothingfor all of it. Applied before the pixels are fetched, so cutting a global layer to one country costs the country.scale: an integer factor to coarsen by on read, each block ofscale × scalecells becoming one, ornothingwhere the study area may choose one to suit its grid. A stated scale,1included, stands. A coarsened read of a whole file is memoised on disk, so the cost is paid once per file rather than once per study area; acutalongside skips the memo and the cost.fn: how a block is reduced to one cell, ornothingfor the axis to decide - the most frequent class (ties to the smallest code) for aTypologyAxis, whose codes must not be averaged, and the mean for any other. On a grid much coarser than the layer the reduction runs in two stages, on the layer's own lattice and then onto the grid, so it must compose: a mean, a maximum or a minimum do exactly, the most frequent class approximately.times: the coordinates of the third axis, one per slice, replacing what the files say - for files carrying no time coordinate, or to label them in elapsed time rather than calendar dates;nothingto take the files' own, or monthly ordinals where they have none.atend: what the series the stack becomes does past its last slice, anAbstractSeriesEnd;RepeatAtEndby default, which a climatology of even months cycles by. A series of real dates cannot cycle evenly and saysHoldAtEndorErrorAtEnd.calendar: what the coordinates mean, anAbstractSeriesCalendar, ornothingto infer it: real dates give aDatedSeries, anything else anUndatedSeries; a monthly climatology saysMonthOfYearSeriesitself.readkw: keywords the source needs to resolve its files, kept for the eventual read -month = 1:12for a monthly climatology, say. A spec nested inside aConstructedRasterSpeccan therefore carry its own read options.
Type parameters
A: the niche axis, which is what matches the layer to species niches. 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: the type ofunit.
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.RecordAbundance — Type
RecordAbundance(storage::AbstractArray)
RecordAbundance(eco::Ecosystem, ntimes::Integer; maxspecies = length(eco.spplist.abun))Record every species' abundance in every cell into storage, one slice per occurrence: storage[:, :, k] holds species by cells at occurrence k. Under MPI the ranks' abundances are gathered and the root writes them, every rank taking part in the gather.
The second form allocates the storage with generate_storage. A run reaching more occurrences than the storage has room for, or gaining more species, is refused when it tries to record them.
Arguments
storage: an integer array of at least species × cells × occurrences, as fromgenerate_storage.eco: the ecosystem whose species and cells size the storage.ntimes: how many occurrences to leave room for.maxspecies: how many species to leave room for, counting any an intervention adds.
EcoSISTEM.RecordDiversity — Type
RecordDiversity(storage::AbstractArray, measure, qs::AbstractVector)Record a subcommunity diversity measure - such as Diversity's norm_sub_alpha - at each of the orders qs into storage, one slice per occurrence: storage[:, :, k] holds cells by orders at occurrence k. Under MPI each rank's cells are gathered with gatherdiversity, so every rank holds and writes the whole answer.
Arguments
storage: a float array of at least cells × orders × occurrences, as fromgenerate_storage(eco, length(qs), ntimes, reps).measure: the subcommunity diversity function, returning aDataFramewith a:diversitycolumn. A metacommunity or individual measure is refused.qs: the orders to measure at.
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.
A supply is a per-cell capacity in whatever quantity measures it - a flux, such as light or rain per day, or a stock, such as ground or the water standing in the soil - and each is a proxy for the capacity along its axis rather than a thing that is used up: the model currently draws nothing down, so a stock and a flux regulate in exactly the same way, through the ratio of demand to supply. Both are therefore admissible, and an axis says which it provides in its resource unit.
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.SaveAbundance — Type
SaveAbundance(folder::AbstractString, name::AbstractString)Save every species' abundance in every cell to a JLD2 file at each occurrence, in folder, named name followed by the occurrence's number counted from 00 - so <name>00.jld2 holds the first - with the run's provenance beside each as <name>00.provenance.toml. Under MPI the ranks' abundances are gathered and the root writes the files.
Arguments
folder: the directory to write into, created if it does not exist.name: the start of each file's name.
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.ShapeCoverage — Type
ShapeCoverage(shape; axis)The share of each cell that a shape covers, as a layer: a coastline becomes the land area of every cell, with the water left out.
land = ShapeCoverage(NaturalEarthSpec("Scotland", coverage = LargestLandmass()),
axis = SurfaceArea)
GridHabitat(regime = ..., supply = land, area = area)The value is a fraction, from 0 where the shape misses a cell to 1 where it covers one, measured as the area of the cell's own rectangle lying inside the shape. A cell the shape touches only along an edge shares no area with it, and gets nothing. As a supply on SurfaceArea that fraction becomes an area per cell, using each cell's true area, so it is land rather than ground; as a regime it stays the fraction itself.
Every other value is built from the fraction with a ConstructedRasterSpec - f -> f .> 0 for the cells with any land, (land, cover) -> land .* cover to take a land-cover share of it.
It adopts the grid it is built on, as a generated layer does, so it never decides a study area's extent, resolution or CRS; and it needs a positioned area, since geometry can only be placed where there is a coordinate system to place it in.
Arguments
shape: anyAbstractShapeSpec- aShapeSpecof your own file, aNaturalEarthSpec, or aConstructedShapeSpeccombining them.axis: what the fraction means, as for every other layer spec. A categorical axis is refused: a covered share is a continuous quantity.
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.ShapeMaskSpec — Type
ShapeMaskSpec(shape, rule = FractionWithin(0.5))Mask a study area by a shape under a stated rule - how much of a cell the shape must cover for that cell to be simulated.
StudyArea(regime = temperature, cellsize = 1km, crs = EPSG(27700),
within = ShapeMaskSpec(NaturalEarthSpec("Scotland"), AnyOverlap()))A shape passed as within on its own means FractionWithin(0.5), so this is what to write when a different rule is wanted: AnyOverlap to keep every cell with any land in it, FullyWithin to keep only whole cells, WholeBoundingBox to take the box and rasterise nothing.
The rule belongs here rather than on the shape because it is a question about rasterising - it has an answer only once there is a grid - while a shape is geometry, and composes with other geometry exactly and at no resolution.
Arguments
shape: the ground, as anyAbstractShapeSpec- aShapeSpecof your own file, aNaturalEarthSpec, or aConstructedShapeSpeccombining them.rule: which cells that ground activates, as anAbstractShapeRule.
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, coverage = AllTerritories())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 dissolve of its features into connected pieces of ground, the 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; read(spec) gives the pieces themselves.
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. A URL must name a self-contained file - a.zip, a GeoJSON or a GeoPackage. Only the one named file is fetched, so a bare remote.shpcannot be read: its.shx,.dbfand.prjcompanions never arrive and GDAL refuses the result. Point at the zip the shapefile is published in instead, or download the set by hand and give the local.shppath.layer: which layer of the file, 0-indexed. Every polygon feature in it is used.coverage: how much of the ground the file covers to take, once its features are dissolved into connected pieces -AllTerritories, the default and everything the file holds,LargestLandmassfor the principal piece, orLandmassesAbovefor every piece clearing a threshold.
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.SoilVolume — Type
SoilVolume <: SpaceAxis - the soil available for rooting, as a depth of soil over a cell (m); a supply of m^3 per cell.EcoSISTEM.SoilWaterVolume — Type
SoilWaterVolume <: WaterAxis - the water standing in a soil layer, as a depth over the cell (mm; ERA5 swvl1, 20CRv3 soilw); a supply of m^3 per cell.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(source, code = nothing, unit = nothing; axis, files = nothing, file = nothing,
directory = nothing, cut = nothing, scale = nothing, fn = nothing,
times = nothing, atend = RepeatAtEnd(), calendar = nothing, readkw...)Name a layer of a catalogued data source, without reading it, as a RasterSpec - one whose files the source resolves for itself, or one reading files you name, which the catalogue still describes: SourceSpec(ERA, "t2m", file = path) reads variable t2m out of an ERA5 netCDF file with the unit, axis and accumulation period the ERA table gives it, and SourceSpec(CRUTS, "tavg", directory = dir) reads a directory of monthly GeoTIFFs as one series.
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.files,file,directory: where the data is, when the source does not fetch it itself - a vector of files in time order, one file, or a directory whose raster files are taken in name order; each a local path, a URL, or aEcoSISTEM.CDSRequest. At most one of the three. Required for a source whose catalogue row says its files are not fetched for it (ERA,CERA,CRUTS), and refused for none. A source whose row says its files come by plain download (TwentyCR) fetches the layer's own file into the asset cache on first use unless one of the three names a copy already held.cut,scale,fn: the read options, as theRasterSpecfields of those names. Give ascaleacutas well where the whole world is not needed: on its own ascalecoarsens the whole source file however small a result is wanted, because the aggregated form is memoised per file, and for a global dataset that first read can need many gigabytes.times,atend,calendar: how the files become one series, as theRasterSpecfields of those names. A netCDF file's own dates are kept unlesstimesreplaces them.- any other keyword: kept as a pass-through argument for the eventual read, so
SourceSpec(WorldClim{Climate}, :wind, month = 1:12)reads the twelve monthly layers andmonth = 1just the one.
EcoSISTEM.SpaceAxis — Type
SpaceAxis <: NicheAxis - the physical space niche axes: ground surface and soil; canopy 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.inputs: theInputRecords of the published data the species were built from - occurrence records, trait tables, parameters from the literature - as given withprovenance.
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}; names = nothing, provenance = InputRecord[])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.names: one name per species, unique, as a vector of strings. Left unset, the species are named"1"to"numspecies". The names label the species' Diversity types as well, so a diversity measure reports them.provenance: anInputRecord, or a vector of them, for the published data the species were built from;provenanceof an ecosystem built from them lists these.
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.
Under MPI with more than one rank this is a collective call, made on every rank in the same order; see Building is collective.
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 - a shape (ShapeSpecfor a file of your own,NaturalEarthSpecfor a named region,ConstructedShapeSpecfor a combination), aShapeMaskSpecsaying which cells such a shape activates, aCircleMaskSpec, aMatrix{Bool}, or a box in degrees as anExtents.Extent-EcoSISTEM.boundingbox("Scotland")gives one. 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: a cell's side - a length (1km) on a projected grid, an angle (30arcminute,0.5°) on a geographic one; the other way round is an error. 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.inputs: theInputRecords of the files read, kept when the cache that held them is discarded; a report still holding its cache has the rest there.stage: which of the two kinds of report this is - seeAbstractReportStage.
EcoSISTEM.StudyGrid — Type
StudyGrid{C, YD, XD} <: EcoBase.AbstractRegularGridThe 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.TwentyCR — Type
TwentyCR <: EcoSISTEMSourceThe NOAA-CIRES-DOE Twentieth Century Reanalysis, version 3 (20CRv3), as a data source: monthly means from 1806 to 2015 on a regular 1 degree grid, one netCDF file per variable as the NOAA Physical Sciences Laboratory serves them. Name a layer with SourceSpec(TwentyCR, "air") and the file is fetched into the asset cache on first use, some hundreds of megabytes each, or point at a copy you hold with file = path; the TwentyCR layer table supplies the unit, axis and, for the soil moisture layer, which of the file's four soil layers to take.
Fieldless, as ERA is.
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), ...).
A change's values are in the built layer's unit, which for a supply is per cell. A supply spec is stated per unit area and multiplied by each cell's area when the layer is built, so UniformSpec(40.0kJ / km^2 / day, axis = SolarRadiation) on 0.25 km^2 cells holds 10 kJ/day; a series varying it holds per-cell slices in kJ/day, and a rate is in kJ/day per unit time. Values given per unit area are refused before the run, naming the unit expected - changeunit returns it for a layer.
EcoSISTEM.VectorData — Type
VectorDataSource of a raster computed from geometry rather than read from a raster file or generated: the covered fraction a ShapeCoverage puts on a grid. It has no dataset, no layer codes and no catalogue row; what the shape was read from is recorded as the layer's provenance instead.
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.WholeBoundingBox — Type
WholeBoundingBox()Activate every cell in the box around the shape, rather than the cells the shape itself covers.
What to reach for when a region is only saying where to work: the grid is cut to the shape's extent and every cell in it is simulated, so no geometry is rasterised at all.
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(spec::AbstractShapeSpec)Read the ground a shape spec names - a vector file's polygons, a named region's, or what a combination of shapes builds - as the connected pieces it is, in WGS84 and before any grid exists: the eager step the spec defers. Each piece is a named tuple of its geometry (an ArchGDAL geometry), its envelope (the bounding box GDAL reports for it) and its area in square kilometres, ordered largest first, after the spec's coverage has said which to keep.
Building a study area resolves a shape through this, so calling it directly is for inspection - to see how many pieces a name is, or how large the one a coverage would drop is. A ShapeMaskSpec reads as the shape it masks by, its rule deciding which cells those pieces activate rather than which pieces there are.
Arguments
spec: what to read.
Base.read — Method
read(spec::RasterSpec; cut = spec.cut, scale = spec.scale, fn = spec.fn)Read the data a RasterSpec names into a ClimateRaster on the source's own grid, values in the spec's unit and the layer's code attached - the eager step the spec defers. A source that fetches its own files does so here (a catalogued dataset's download), and a spec naming its files reads them: each opened by the backend its source's catalogue row names, stacked along time with the coordinates the files carry, or times where given, or monthly ordinals where they have none; a file in the 0 to 360 longitude convention is rolled onto -180 to 180. What the files say about themselves is checked against the row on the way.
Building a layer reads a spec through this, windowed and coarsened to suit the study grid, so calling it directly is for inspection - a whole global layer at its own resolution can be large.
Arguments
spec: what to read.cut: anExtents.Extentof°intervals to window the read to; the spec's own by default.scale: an integer factor to coarsen by on read, each block ofscale × scalecells becoming one; the spec's own by default, and1where it states none.fn: how a block is reduced to one cell; the spec's own by default, and the axis's choice where it states none.
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.RasterFileSpec — Method
RasterFileSpec(path::AbstractString; axis, unit = NoUnits, source = SyntheticData,
cut = nothing, scale = nothing, fn = nothing, times = nothing,
atend = RepeatAtEnd(), calendar = nothing)Name a raster file as a layer, without reading it: a GeoTIFF or anything else GDAL reads, given by path or URL, that is not a layer of a catalogued dataset. Builds a RasterSpec whose files is that one file and whose code is nothing, so it is read, cut and resampled exactly as a SourceSpec is.
This is the lazy counterpart of in_memory_raster: that wraps a raster already read into memory, in full and cached nowhere; this holds only the path. Prefer a SourceSpec where the file is a layer of a catalogued dataset, since the catalogue then supplies the unit and axis. A file has no catalogue, so this spec must be told both.
Its values must be intensive - a rate, a density, a state, a fraction - because a layer reaches the grid by averaging the cells that cover each grid cell, and a count per cell would be averaged too and read as a density. Divide a count by the cell's area before naming the file.
It is a layer spec. To use a file as a within mask, say what in it marks a cell active with a ConstructedRasterSpec over it - ConstructedRasterSpec(r -> .!isnan.(r), spec, axis = NicheAxis).
Arguments
path: the file, or a URL naming a self-contained file (a.zipis read directly). A URL is downloaded intoEcoSISTEM.assetdir(owner = RasterSpec)as anEcoSISTEM.CachedAssetthe first time it is needed.axis: theNicheAxisthe values are on. Required: passNicheAxisitself for data whose meaning is not being claimed.unit: the physical unit the file's values are in, attached on read. Defaults toNoUnits, so a file of temperatures in kelvin needsunit = Kto become a temperature regime.source: the data source recorded on the raster -SyntheticDataby default, for a file that belongs to no catalogued dataset.cut,scale,fn: the read options, as theRasterSpecfields of those names.times,atend,calendar: for a file with a third axis, how its slices become a series, as theRasterSpecfields of those names.
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 - and, at elapsed zero, once before the first step's dynamics, so an intervention due at the start acts on the starting state.
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 seeded from
(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 - give simulate! a callback: it closes over the ecosystem and is handed the elapsed time it fires at, so it can decide and then act.
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; verify = false)
assetpath(request::CDSRequest; verify = false)
assetpath(relative_path::AbstractString)Return a local path to a file, downloading it first if it is not there yet, and writing a provenance record beside it when it does - see provenance.
Arguments
asset: aCachedAsset, fetched from itsurlinto its owner's subdirectory of EcoSISTEM's asset cache, or to its ownpath, if the file is not already there. An interrupted download is resumed from where it stopped, by this or a later run; a second process asking for the same file waits for the first rather than fetching it again.request: aCDSRequest, fetched from the Climate Data Store into its ownpathif that file does not already exist. The fetch needsCDSAPIloaded and a CDS key in~/.cdsapirc; a file already present needs neither.verify:truechecks a file that is already present against the checksum its provenance record holds, erroring on a mismatch - a truncated or replaced file. Off by default, since hashing a large file on every read would cost more than the read.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_abundance_table — Method
build_abundance_table(eco::AbstractEcosystem, table)Return the table an AddAbundanceTable reads best, built from one naming species and grid positions: each species name becomes its index, each (y, x) its cell's linear index, the rows of one species, cell and time are summed, and the rows are sorted by time.
The result is a NamedTuple of the vectors species, cell, count and time, itself a table offering whole columns, so it can be given to AddAbundanceTable as it is, or written to disk - as an Arrow file, say - and memory-mapped back for a run. The counts stay whole numbers where every row gave one, and an elapsed time is kept in seconds.
Arguments
eco: the ecosystem the table is for. A species it does not have, or a position off its grid, is an error naming the row.table: any Tables.jl source, read row by row, with the columnsspecies(a name or an index),yandx(integer indices into the grid),time(an elapsed time from the start of the run, or a date) and, optionally,count(one per row without it).
EcoSISTEM.build_ecosystem — Method
build_ecosystem(species::SpeciesList, environment::GridHabitat;
nichefit = nothing, seed = nothing, distributed = :auto, epoch = nothing,
calendar = ExactDates(), provenance = InputRecord[])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.
calendar is how dates become elapsed time: ExactDates, the default, places every dated slice and the epoch by the real time between them, and MeanMonths counts each calendar month as month_mean_duration, so a dated monthly series stepped by month_mean_duration makes every month current once. Under ExactDates such a run is refused by simulate!, since real months are 28 to 31 days long and the step skips some. The calendar also decides the date simulationdate reports.
provenance is an InputRecord, or a vector of them, for published data that belongs to the run as a whole rather than to its species or its environment - the records a starting population was seeded from, say, or the study's own DOI. provenance of the ecosystem lists them beside everything else it was built from.
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.
Under MPI it is a collective call, as GridHabitat is.
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,
abundance = 1000 * numspecies, native = true, names = nothing, seed = nothing,
provenance = InputRecord[])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- demographic rates (scalar rates give anEqualPop, vectors aPopGrowth).boostis deprecated and ignored: the birth multiplier is capped at 1.
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). names gives the species their names, one unique string each - binomials, say - which also label their Diversity types; left unset they are "1" to "numspecies". provenance is an InputRecord, or a vector of them, for the published data the species were built from - an occurrence download, a trait table - which provenance of the ecosystem then lists.
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.class_fractions — Method
class_fractions(raster::ClimateRaster; codes = nothing)Expand a raster of class codes into one band per class, 1.0 where a cell is that class and 0.0 where it is not, so that regridding the bands gives the fraction of each grid cell in each class.
Class codes cannot be averaged, and the most frequent class of a coarse cell taken in two stages - first on the data's own lattice, then onto the grid - is not the most frequent class of the cells covering it. Fractions have neither problem: their means compose, so a stack of them reaches any grid exactly as a measurement does, and dominant_class then takes the most frequent class once, at the end. Used as the combine of a ConstructedRasterSpec on the source grid, with dominant_class as a second spec's combine on the target grid, the two regrid a class layer by the plurality of its covering cells:
fractions = ConstructedRasterSpec(class_fractions, codes, axis = EcoSISTEM.NicheAxis,
combinestage = CombineOnSourceGrid())
regime = ConstructedRasterSpec(dominant_class, fractions, axis = LandCoverTypology)The bands lie along Dim{:layer}, labelled by code in ascending order, and an absent cell is absent in every band, so it drops out of every mean. This is the shape EarthEnv{LandCover} arrives in natively, as twelve cover fractions, which is why compress_landcover is dominant_class on that source. The result carries DerivedData of the input's source.
Arguments
raster: a two-dimensionalClimateRasterof class codes.codes: the classes to make bands for, in any order; by default every code present in the raster. Give an axis's full list where stacks from different windows must share their bands.
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. It is dominant_class on that source: a cell with no data in any band is absent in the result, and a tie goes to the lowest-numbered 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.datasetinfo — Method
datasetinfo(T::Type)Return the DatasetRecord for data source T from the shipped datasets.csv: its file format, longitude convention, coordinate reference system, resolutions, extent, how its files are fetched, and its provenance. Errors, naming the table, for a source with no row.
Arguments
T: the data source type, written as it is spelled -WorldClim{BioClim},ERA.
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.dominant_class — Method
dominant_class(raster::ClimateRaster)Collapse one band per class into a single layer of class codes: each cell takes the class whose band is largest there, the most frequent class where the bands are fractions, with ties to the smallest code, and is absent where no band has a value.
The bands lie along Dim{:layer}. Where its labels are numbers they are the codes, as class_fractions builds them; where they are names the code is the band's position, which is EarthEnv{LandCover}'s convention of twelve classes in a fixed order. The result carries DerivedData of the input's source and no layer code, since it is computed from the bands rather than being any one of them, and says nothing about being categorical: the spec's axis does that.
Arguments
raster: aClimateRasterwith aDim{:layer}dimension of class bands.
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.era5requests — Method
era5requests(code, years; dir, per = 10, months = 1:12, area = nothing)Build the EcoSISTEM.CDSRequests that fetch one ERA5 monthly-means layer over years as one file per per years - a decade each by default, which is the size the Climate Data Store serves comfortably - each written to dir as era5_<code>_<decade>s.nc, in time order, so the result is a spec's files: SourceSpec(ERA, "t2m", files = era5requests("t2m", 1940:2025, dir = "data/era5")). A block that does not fill its decade - the current one, or the first of a span - is named by the years it holds instead, era5_<code>_2020-2025.nc, so that asking for a later year names a new file rather than finding the old one present and stopping there.
Arguments
code: the layer, as theERAtable spells it.years: every year wanted.dir: the directory the files go in.per: how many years each request covers.months,area: as forEcoSISTEM.CDSRequest.
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.fetchfiles — Method
fetchfiles(spec::RasterSpec; dryrun = false)
fetchfiles(specs; dryrun = false)Fetch every file a spec reads that is not there yet, reading nothing, and return their local paths in the spec's order - the step to run on a node with a network before a run on nodes without one. A vector of specs is fetched spec by spec.
Arguments
spec,specs: what to fetch for.dryrun:truefetches nothing and instead returns, per file, a named tuple of theentry, whether it ispresent, and itsbyteswhere the server states them (a plain download'sContent-Length; a Climate Data Store request cannot say), so a user on a slow link can decide. A source that resolves its own files through RasterDataSources is reported as one entry with no size.
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. A metacommunity or individual measure is refused.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)
getcellat(x, places::AbstractVector)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- aSpatialLocationin the grid's own frame, or aLatLong, which is projected into the grid's CRS where the grid is projected.places- a vector of places, answered with a vector of cells. The grid is resolved and any projection set up once for all of them, and a place outside the grid givesnothingin its slot, since a set of records routinely includes some beyond a study area.
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 single place outside the grid throws: it is a caller mistake rather than a missing value.
getcellat is public but not exported, so call it as EcoSISTEM.getcellat or import it by name. Called bare without the import it raises an UndefVarError, which a try written to catch a place outside the grid would silently take for one.
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, which returns the species' dispersal kernel so that whatever it holds can be read directly.
This returns dist^2 * pi / 4 for the kernel's dist, which is not a statistic of the kernel's displacement, so it should not be read as a variance.
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, atend = RepeatAtEnd(), calendar = nothing)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. Its values must be intensive - a rate, a density, a state, a fraction - because that sampling averages the cells covering each grid cell, and a count per cell would be read as a density.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.atend,calendar: for a raster with a time axis, what the series it becomes does past its last slice and what its coordinates mean, as onSourceSpec.
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).
Under MPI with more than one rank this is a collective call, made on every rank in the same order; see Building is collective.
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.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 from the pair (seed, j) through the generator's own seeding, Xoshiro(UInt64[seed, j]), so its random stream is a pure function of (seed, j) - independent of how species are distributed across threads or MPI processes, and the same on every Julia version, since Base.hash, whose values change between versions, is never involved. 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) and across Julia releases. 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.
Under MPI with more than one rank this is a collective call, made on every rank in the same order; see Building is collective.
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.provenance — Method
provenance(path::AbstractString)
provenance(spec::RasterSpec)
provenance(spec::ConstructedRasterSpec)
provenance(spec::AbstractShapeSpec)Return what is known about where an input came from.
For a file, the InputRecord its provenance sidecar holds - written beside every file this package fetched or first used, as <file>.provenance.toml - or nothing for a file with none. A sidecar of that name that this package did not write is left alone and reports nothing too, with a warning saying so, since its fields mean whatever its writer meant.
For a raster spec, one entry per file the spec reads, in order: the file's record, or nothing where the file is absent or has no record. Nothing is fetched to answer; use fetchfiles first for a spec whose files are not there yet. A combination of layers lists its data members' entries in order, a synthetic member having none.
For a shape spec, the same for the files it outlines: a vector file's record, or a named region's Natural Earth zip, with the source's licence and citation and the version the zip states filled in where the record lacks them. A combination of shapes lists its members' in order.
Arguments
path: the file, not its sidecar.spec: the spec whose files to report on.
EcoSISTEM.provenance — Method
provenance(recorder::AbstractRecorder)Return the Provenance of the run a recorder has kept from, as it stood at the recorder's last write - how far the run had gone, and every intervention that had acted by then - or nothing before the recorder has written.
EcoSISTEM.provenance — Method
provenance(report::StudyAreaReport)
provenance(area::StudyArea)
provenance(habitat::GridHabitat)
provenance(eco::AbstractEcosystem)Return a Provenance: what this package version was, every input the object was built from, the grid it sits on and, for an ecosystem, the run. The same answer comes from each object holding the same study area, and on every MPI rank, since it is taken from the inputs alone.
An input is recorded by its provenance record where it has one - every file this package fetched - and otherwise by its file name, with the catalogue's facts about its dataset where it is a layer of one. The files read for the layers and those of the shape or mask that cut the grid are listed alike; a synthetic layer reads nothing and adds nothing. An ecosystem adds the records given as provenance to its species list and to build_ecosystem, and those of every Intervention that has acted on it.
Arguments
report,area,habitat,eco: what to report on.
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; source = SyntheticData, unit = NoUnits, cut = nothing)Deprecated: read a RasterFileSpec instead - read(RasterFileSpec(file, axis = NicheAxis, unit = unit, source = source, cut = cut)) - which is also what a layer built from the file does. This forwards to it.
Arguments
file: path to the raster, in any format GDAL reads.source,unit,cut: as the spec's keywords of those names.xmin,xmax,ymin,ymax: an older spelling ofcut; all four together, or none.
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(param, from_year, to_year, filename = "era5"; area = nothing)Deprecated: fetch ERA5 monthly means through a EcoSISTEM.CDSRequest instead - one per decade file, resolved by assetpath or on reading a SourceSpec(ERA, code, files = ...) that names it. This forwards to exactly that, one request per decade of from_year to to_year, each written to <filename>_<decade>.nc, and returns the paths. param is the variable's CDS name ("2m_temperature"); the old MARS parameter codes no longer resolve.
Arguments
param,from_year,to_year,filename: as above.area:[north, west, south, east]in degrees, ornothingfor the globe.
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!(f, eco::AbstractEcosystem, duration::Unitful.Time, timestep::Unitful.Time;
every = timestep, intervention = nothing)Run eco for duration in steps of timestep, as the three-argument simulate! does, calling f whenever the schedule every fires - usually written as a do block:
totals = Int[]
simulate!(eco, 10year, 1month_mean_duration, every = EveryInterval(1year)) do occurrence
push!(totals, sum(eco.abundances.matrix))
endf is handed one named tuple per occurrence: count, which occurrence of this call it is, from 1; elapsed, the simulation time it fires at; and date, that time as a date under the run's epoch and calendar, or nothing for a run with no epoch. The ecosystem is reached by closure. Each occurrence sees the state at exactly its time: on a run starting from elapsed zero the first is the starting state, after any intervention due at the start, and each later one comes after its step's dynamics, interventions and layer update.
f may also be a recorder - an AbstractRecorder such as RecordAbundance - which is called with the ecosystem and the occurrence; to keep several things from one run, call each from a callback of your own.
The callback is for observing the run - recording and logging. It must not draw from the global random number generator or write a layer's values, either of which would make the result depend on how the work was divided. Under MPI every rank runs the loop and the callback, so a collective the callback calls, such as gatherabundance or gatherdiversity, must be reached on every rank - a callback returning before it on the ranks other than the root leaves every rank waiting for ever. A callback writing abundances reaches only its own rank's species there, and the demand the next step computes does not include what it wrote. To change the ecosystem, declare an Intervention, which is applied once and identically everywhere.
Arguments
f: called at each occurrence with the named tuple above.eco: the ecosystem to run.duration,timestep: the length of the run and of each step; the run takesduration / timestepsteps - the nearest whole number for a step of a day or less, and otherwise exactly a whole number.every: whenfis called - anAbstractSchedule, or a duration meaningEveryIntervalof it. Every timestep by default, the starting state included.intervention: anInterventionorInterventionSetapplied as the run proceeds.
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)Deprecated: use simulate!(SaveAbundance(cacheFolder, scenario_name), eco, duration, timestep, every = EveryInterval(cacheInterval)) with a SaveAbundance, which writes the run's provenance beside each file. This runs eco for times in steps of timestep and saves its abundances to <scenario_name>NN.jld2 in cacheFolder on the step after the clock stood on each multiple of cacheInterval.
EcoSISTEM.simulate_action! — Method
simulate_action!(action!::Function, eco::AbstractEcosystem, times::Unitful.Time,
interval::Unitful.Time, timestep::Unitful.Time;
intervention = nothing, offset = false)Deprecated: give simulate! the callback instead, simulate!(f, eco, duration, timestep; every), whose callback is handed the occurrence's count, elapsed time and date and sees the state at each time every names. This calls action!(counting) on the step after the clock stood on a multiple of interval, which must be a whole multiple of timestep; offset starts that grid at timestep, the run a step shorter. intervention is applied as for simulate!.
EcoSISTEM.simulate_record! — Method
simulate_record!(storage::AbstractArray, eco::Ecosystem, times::Unitful.Time,
interval::Unitful.Time, timestep::Unitful.Time; intervention = nothing)Deprecated: use simulate!(RecordAbundance(storage), eco, duration, timestep, every = EveryInterval(interval)) with a RecordAbundance. This records the starting state and each multiple of interval, a whole multiple of timestep, into storage[:, :, k] over times / timestep steps, applying intervention as simulate! does, and returns storage.
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)Deprecated: use simulate!(RecordDiversity(storage, divfun, qs), eco, duration, timestep, every = EveryInterval(interval)) with a RecordDiversity for the first form, and a callback on simulate! computing the measures you want for the other two. These record on simulate_action!'s timing, interval a whole multiple of timestep: divfun at the orders qs into storage; normalised alpha, normalised beta and gamma at qs into substorage by cell and metastorage, returned as (subcommunity = substorage, metacommunity = metastorage); or each of divfuns at the order q into a column of storage.
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. The date is reached through the run's calendar, so under MeanMonths every month is one month_mean_duration long.
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, 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. On the first step, with the clock at zero, those due at the start run once more before the dynamics, so they act on the starting state.
eco is the ecosystem to advance, serial or distributed, timestep how far to advance it, and intervention an Intervention, an InterventionSet or nothing.
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).
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.verifyassets — Method
verifyassets(spec::RasterSpec)Check every file a spec reads that is present against the checksum its provenance record holds, erroring on the first that differs - a truncated or replaced copy - and return how many were checked. A file with no record, or whose record carries no checksum, has nothing to check against and is not counted; nothing is fetched.
Arguments
spec: the spec whose files to check.
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.write_provenance — Method
write_provenance(path::AbstractString, p::Provenance)
write_provenance(path::AbstractString, obj)Write what a study area, a habitat or an ecosystem was built from to path as TOML, and return the path: the software, the grid, the run where there is one, and every input with its DOI, licence, version, citation, file name and checksum - the file a paper's repository commits beside its figures, so a reader can see what made them.
An input is written as its record holds it, named by its file and never by a directory, so nothing in the file is particular to the machine that wrote it. Quantities, the coordinate reference system and the grid's extent are written as text, and fetch times and an epoch as TOML dates.
Arguments
path: the file to write; its directory is created if it does not exist.p: theProvenanceto write.obj: a study area report, aStudyArea, aGridHabitator an ecosystem, whoseprovenanceis written, or a recorder, whose run's provenance as of its last write is.
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.
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.AbstractRecorderEcoSISTEM.AbstractRegimeEcoSISTEM.AbstractRegionEcoSISTEM.AbstractReportStageEcoSISTEM.AbstractRunCalendarEcoSISTEM.AbstractScheduleEcoSISTEM.AbstractSeriesCalendarEcoSISTEM.AbstractSeriesEndEcoSISTEM.AbstractShapeOperationEcoSISTEM.AbstractShapeRuleEcoSISTEM.AbstractShapeSpecEcoSISTEM.AbstractSpatialRelationEcoSISTEM.AbstractSpecEcoSISTEM.AbstractSpeciesEcoSISTEM.AbstractSpeciesRequirementEcoSISTEM.AbstractSupplyEcoSISTEM.AbstractSyntheticLayerSpecEcoSISTEM.AbstractSyntheticMaskSpecEcoSISTEM.AbstractSyntheticSpecEcoSISTEM.AbstractToleranceEcoSISTEM.AbstractTopologyEcoSISTEM.ActiveCellsEcoSISTEM.AddAbundanceEcoSISTEM.AddAbundanceTableEcoSISTEM.AddSpeciesEcoSISTEM.AdditiveFitEcoSISTEM.AdditiveFit2EcoSISTEM.AdditiveFit3EcoSISTEM.AdoptedFromLayersEcoSISTEM.AgreedByAllLayersEcoSISTEM.AllCellsEcoSISTEM.AllTerritoriesEcoSISTEM.AltitudeEcoSISTEM.AlwaysMovementEcoSISTEM.AnyOverlapEcoSISTEM.AsBuiltEcoSISTEM.AsInvestigatedEcoSISTEM.AtDatesEcoSISTEM.AtTimeEcoSISTEM.AtTimesEcoSISTEM.AxisNodeEcoSISTEM.BetweenTimesEcoSISTEM.BirthOnlyMovementEcoSISTEM.BoundedEcoSISTEM.BrownianEcoSISTEM.CDSRequestEcoSISTEM.CDSRequestEcoSISTEM.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.DatasetRecordEcoSISTEM.DatedSeriesEcoSISTEM.DayAxisEcoSISTEM.DayCountEcoSISTEM.DayOfYearEcoSISTEM.DeactivateEcoSISTEM.DefaultEcosystemEcoSISTEM.DemandEcoSISTEM.DemandCollection2EcoSISTEM.DerivedDataEcoSISTEM.DiversitySetEcoSISTEM.DiversitySetEcoSISTEM.ERAEcoSISTEM.EcoSISTEMSourceEcoSISTEM.EcosystemEcoSISTEM.EcosystemEcoSISTEM.EcosystemEcoSISTEM.EdgeTopologyEcoSISTEM.EnclosesEcoSISTEM.EqualPopEcoSISTEM.ErrorAtEndEcoSISTEM.EvapotranspirationEcoSISTEM.EvapotranspirationAxisEcoSISTEM.EvapotranspirationRangeEcoSISTEM.EveryIntervalEcoSISTEM.EveryStepEcoSISTEM.EveryYearEcoSISTEM.ExactDatesEcoSISTEM.FractionWithinEcoSISTEM.FrostChangeFrequencyEcoSISTEM.FullyWithinEcoSISTEM.GaussEcoSISTEM.GaussianKernelEcoSISTEM.GivenByUserEcoSISTEM.GradientSpecEcoSISTEM.GridHabitatEcoSISTEM.GridLandscapeEcoSISTEM.GridLandscapeEcoSISTEM.GrowingSeasonPrecipitationEcoSISTEM.HeterogeneityEcoSISTEM.HoldAtEndEcoSISTEM.HumidityAxisEcoSISTEM.IncrementByEcoSISTEM.InputRecordEcoSISTEM.InterventionEcoSISTEM.InterventionSetEcoSISTEM.IsRasterDataEcoSISTEM.IslandEcoSISTEM.IsothermalityEcoSISTEM.LandCoverTypologyEcoSISTEM.LandmassesAboveEcoSISTEM.LargestLandmassEcoSISTEM.LatLongEcoSISTEM.LayerAggregatedEcoSISTEM.LayerCacheEcoSISTEM.LayerCollectionEcoSISTEM.LayerInputEcoSISTEM.LayerKeptExactlyEcoSISTEM.LayerPlanEcoSISTEM.LayerRecordEcoSISTEM.LayerResampledEcoSISTEM.LayerSpecEcoSISTEM.LegacyLossEcoSISTEM.LongTailKernelEcoSISTEM.LookupEcoSISTEM.MPIEcosystemEcoSISTEM.MPIGridLandscapeEcoSISTEM.MaskSpecEcoSISTEM.MeanMonthsEcoSISTEM.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.ProvenanceEcoSISTEM.RainToleranceEcoSISTEM.RandomCellsEcoSISTEM.RasterDataAcceptableCodeEcoSISTEM.RasterSpecEcoSISTEM.RateChangeEcoSISTEM.ReactivateEcoSISTEM.RecordAbundanceEcoSISTEM.RecordDiversityEcoSISTEM.RegimeCollection2EcoSISTEM.RegimeCollection3EcoSISTEM.RegionMatchEcoSISTEM.RegionReportEcoSISTEM.RelativeChangeEcoSISTEM.RelativeHumidityEcoSISTEM.RelativeHumidityAxisEcoSISTEM.RelativeHumidityRangeEcoSISTEM.RemoveAbundanceEcoSISTEM.RepeatAtEndEcoSISTEM.ReplaceWithEcoSISTEM.ResourceEcoSISTEM.RevertToLayerEcoSISTEM.RoleEcoSISTEM.RoundedFromMeasurementEcoSISTEM.SaveAbundanceEcoSISTEM.SavedLandscapeEcoSISTEM.SavedLandscapeEcoSISTEM.SeriesChangeEcoSISTEM.SeriesLayerChangeEcoSISTEM.SetChangeEcoSISTEM.SetLandCoverEcoSISTEM.ShapeBufferEcoSISTEM.ShapeConvexHullEcoSISTEM.ShapeCoverageEcoSISTEM.ShapeDifferenceEcoSISTEM.ShapeIntersectionEcoSISTEM.ShapeMaskSpecEcoSISTEM.ShapeSimplifyEcoSISTEM.ShapeSpecEcoSISTEM.ShapeUnionEcoSISTEM.SimpleCategoricalToleranceEcoSISTEM.SiteWaterBalanceEcoSISTEM.SnowWaterEquivalentEcoSISTEM.SoilVolumeEcoSISTEM.SoilWaterVolumeEcoSISTEM.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.TwentyCREcoSISTEM.TypologyAxisEcoSISTEM.UndatedSeriesEcoSISTEM.UnifEcoSISTEM.UniformSpecEcoSISTEM.VapourPressureEcoSISTEM.VapourPressureDeficitEcoSISTEM.VapourPressureDeficitAxisEcoSISTEM.VapourPressureDeficitRangeEcoSISTEM.VaryingEcoSISTEM.VectorDataEcoSISTEM.WaterAxisEcoSISTEM.WholeBoundingBoxEcoSISTEM.WindSpeedEcoSISTEM.WindSpeedAxisEcoSISTEM.WindSpeedRangeEcoSISTEM.WithinBase.append!Base.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.RasterFileSpecEcoSISTEM.SurfaceSpecEcoSISTEM.TempChangeEcoSISTEM.TempFluctEcoSISTEM.Units.month_durationEcoSISTEM.Units.month_durationEcoSISTEM.abundancesEcoSISTEM.applyinterventions!EcoSISTEM.arenoderecordsemptyEcoSISTEM.assetdirEcoSISTEM.assetpathEcoSISTEM.assigntraits!EcoSISTEM.bioclimhabitatEcoSISTEM.boundingboxEcoSISTEM.boundsEcoSISTEM.brownian_motionEcoSISTEM.build_abundance_tableEcoSISTEM.build_ecosystemEcoSISTEM.build_habitatEcoSISTEM.build_speciesEcoSISTEM.calc_lookup_moves!EcoSISTEM.canonicalunitEcoSISTEM.cellregimeEcoSISTEM.cellsupplyEcoSISTEM.changeunitEcoSISTEM.check_boundsEcoSISTEM.checkcoverageEcoSISTEM.checkfileEcoSISTEM.checkfileEcoSISTEM.class_fractionsEcoSISTEM.clearcache!EcoSISTEM.compress_landcoverEcoSISTEM.continuous_evolveEcoSISTEM.convert_coordsEcoSISTEM.cyclic_changeEcoSISTEM.datasetinfoEcoSISTEM.demandtypeEcoSISTEM.densitywidthEcoSISTEM.discrete_evolveEcoSISTEM.dispersesafelyEcoSISTEM.dominant_classEcoSISTEM.empty_landscapeEcoSISTEM.emptypopulate!EcoSISTEM.equalpopEcoSISTEM.era5requestsEcoSISTEM.erahabitatEcoSISTEM.extract_valuesEcoSISTEM.fetchfilesEcoSISTEM.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.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.provenanceEcoSISTEM.provenanceEcoSISTEM.provenanceEcoSISTEM.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!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.verifyassetsEcoSISTEM.worldclimhabitatEcoSISTEM.write_provenanceEcoSISTEM.@nicheaxis