InVEST Coastal Blue Carbon: Main Model.

Implementation Notes

Comparison with the Prior Implementation

This model is a timeseries analysis, where we iterate through each year in the timeseries and track the state of carbon over time: the state of carbon stocks, net sequestration, rates of accumulation, carbon emitted, etc, all for each relevant carbon pool. A lot of files are produced in both the intermediate and output directories in the target workspace.

While some of these operations could be summarized per transition (which would result in fewer files produced), this implementation avoids such summary. This is because the implementation that this file replaces did just that, and there were a number of issues that arose from that implementation:

  1. Unbounded memory consumption This model has no upper bound on how many years the timeseries can operate over. So even if we were to have each task operating on only those years between transitions, even that number could be very large and exhaust available memory. We had many issues with memory usage in the prior model, and iterating over lots of files is the safest general-case solution for a timeseries model with an unbounded number of years.

  2. In practice, the intermediate rasters are useful for analyses The prior implementation wrote as few rasters out as it could, which ultimately ended up making it harder for some of our partner organizations to to the science they needed. By providing all these intermediate rasters, we allow our users to do their own analytics and summaries on how carbon stocks change over time, which would have been game-changing to our colleagues in analyses past.

  3. Debugging multidimensional arrays is time-consuming and tricky The prior implementation used 3D arrays (m x n x n_years) for its analysis, which was more concise to implement but so incredibly difficult to debug when there were issues. If we were to only output a few summary rasters per transition year, we would still have these 3D arrays, and debugging would be much trickier. Admittedly, there’s probably a way to make all this much easier to debug than the prior implementation, but even if we were to do so, we’d still have the unbounded-array-size problem, mentioned in point 1.

The implementation as stated plays it safe, writing out individual rasters per component per timestep. There’s a lot of bookkeeping as a result, but the final model is consistent with development standards, correct (according to the model’s specification in the InVEST User’s guide) and will be easier to maintain and debug as issues arise.

“Advanced” Mode

The Coastal Blue Carbon model as specified in the User’s Guide is tied to the landcover classifications provided by the user, and only offers an interesting perspective on carbon stored when a landcover class transitions to another landcover class. This approach seriously hampers the ability to model spatial carbon distributions.

In response to this shortcoming, the model now offers an ‘advanced’ entrypoint, where a user can provide their own maps of spatial parameters, such as rates of accumulation, half-lives of carbon, and other parameters for finer-grained control. See the docstring for execute_transition_analysis for more information.

Units of Inputs and Outputs

The units of carbon in the model’s inputs and outputs are, across the board, density of CO2-equivalent per hectare. Megatonnes of CO2-equivalent per Ha are the units specified in the user’s guide, but any such density could be used as no conversion of units takes place in the model.

There has been some conversation within the Natural Capital Project staff of whether to convert this carbon density per hectare to carbon density per pixel, for consistency with the rest of InVEST (which often displays metrics per pixel), and also for easier aggregation of spatial metrics such as total carbon sequestered in the landscape. The carbon density per hectare has been retained here for several reasons:

  1. Many carbon scientists, including on the NatCap staff, prefer to work directly with carbon densities.

  2. Converting from CO2E/Ha to CO2E/pixel is an easy calculation should the conversion be desired, and can be done via a raster calculator call in any GIS software.

  3. Using rates of CO2E/Ha allows for the model to operate on landscapes where pixels might be non-square, or may vary in size over space such as in lat/long coordinate systems. In such systems, converting to units per pixel would be nontrivial due to the area of a pixel varying across the raster. Thus, using rates per hectare enables the model to be used across very large areas without modification.


Coastal Blue Carbon.

  • args['workspace_dir'] (string) – the path to a workspace directory where outputs should be written.

  • args['results_suffix'] (string) – (optional) If provided, a string suffix that will be added to each output filename.

  • args['n_workers'] (int) – (optional) If provided, the number of workers to pass to taskgraph.

  • args['landcover_snapshot_csv'] (string) – The path to a transitions CSV table containing transition years and the LULC rasters representing that year. Required for transition analysis.

  • args['analysis_year'] (int) – the year of the final analysis.

  • args['do_economic_analysis'] (bool) – Whether to do valuation.

  • args['use_price_table'] (bool) – Whether to use a table of annual carbon prices for valuation. Defaults to False.

  • args['price_table_path'] (string) – The path to a table of prices to use for valuation. Required if args['use_price_table'] is True.

  • args['inflation_rate'] (number) – The rate of inflation. The number provided is multiplied by 0.01 to compute the actual rate of inflation. Required if args['use_price_table'] is False.

  • args['price'] (number) – The carbon price. Required if args['use_price_table'] is False.

  • args['discount_rate'] (number) – The discount rate. The number provided is multiplied by 0.01 to compute the actual discount rate. Required if args['do_economic_analysis'].

  • args['biophysical_table_path'] (string) – The path to the biophysical table on disk. This table has many required columns. See ARGS_SPEC for the required columns.

  • args['landcover_transitions_table'] (string) – The path to the landcover transitions table, indicating the behavior of carbon when the landscape undergoes a transition.




Execute a transition analysis.

The calculations required for an analysis centered around a baseline period are trivial and can be accomplished with a few calls to your raster_calculator of choice because of the linear rates of carbon accumulation that this model assumes. By contrast, the raster calculations required for an analysis involving transitions are much more complex, and by providing this function separate from execute, the adept modeller is able to provide spatially-explicit distributions of rates of accumulation, the magnitudes of disturbances, carbon half-lives and carbon stocks for each carbon pool as desired.

There are certain constraints placed on some of these inputs:

  • The years listed in args['transition_years'] must match the keys

    in args['disturbance_magnitude_rasters'], args['half_life_rasters'], and args['annual_rate_of_accumulation_rasters'].

  • All rasters provided to this function must be in the same projected

    coordinate system and have identical dimensions and pixel sizes.

  • All rasters provided to this function are assumed to be 32-bit

    floating-point rasters with a nodata value matching this module’s NODATA_FLOAT32_MIN attribute.

  • All data structures provided to this function that use pools as an

    index assume that the pools are strings matching the POOL_SOIL, POOL_BIOMASS and POOL_LITTER attributes of this module.

  • Most dicts passed to this function are nested dictionaries indexed

    first by transition year, then by pool (see note about pool keys). These dicts are accessed like so:

  • The “baseline period” is the range of years between the baseline year

    and the first transition, not including the year of the first transition.

  • args['workspace_dir'] (string) – The path to a workspace directory where outputs should be written.

  • args['results_suffix'] (string) – If provided, a string suffix that will be added to each output filename. Optional.

  • args['n_workers'] (int) – The number of workers that taskgraph may use.

  • args['transition_years'] (set) – A python set of int years in which a transition will take place.

  • args['disturbance_magnitude_rasters'] (dict) – A 2-level deep dict structure mapping int transition years to string pools to raster paths representing the magnitude (0-1, float32) of a disturbance.

  • args['half_life_rasters'] (dict) – A 2-level deep dict structure mapping int transition years to string pools to raster paths representing the half-life of the given carbon pool at that transition year.

  • args['annual_rate_of_accumulation_rasters'] (dict) – A 2-level deep dict structure mapping int transition years to string pools to raster paths representing the annual rate of accumulation for this pool in the given transition period.

  • args['carbon_prices_per_year'] (dict) – A dict mapping int years to the floating-point price of carbon in that year. Every year between the baseline year and the analysis year (inclusive) must have a key-value pair defined.

  • args['discount_rate'] (number) – The discount rate for carbon valuation.

  • args['analysis_year'] (int) – The analysis year. Must be greater than or equal to the final transition year.

  • args['do_economic_analysis'] (bool) – Whether to do valuation.

  • args['baseline_lulc_raster'] (string) – The path to the baseline lulc raster on disk.

  • args['baseline_lulc_year'] (int) – The year of the baseline scenario.

  • args['sequestration_since_baseline_raster'] (string) – The string path to a raster on disk representing the total carbon sequestration across all 3 carbon pools in the entire baseline period.

  • args['stocks_at_first_transition'] (dict) – A dict mapping pool strings (see above for the valid pool identifiers) to rasters representing the carbon stocks at the end of the baseline period.