Statistical data

This section describes the statistical data that is generated by the Chloris Platform and how to access it.

Units of measurement

The Chloris Platform internally uses the following SI units for most measurements:

  • Length: meters (m)
  • Area: square kilometers (km²)
  • Mass: tonnes (t)

And tonnes / hectare (t/ha) for biomass stock density.

Generally, we recommend rounding statistical data to three significant digits for display purposes.

Common conversions

  • 1 km² = 100 ha
  • 1 t biomass = 0.5 * (44 / 12) t CO₂e (may vary depending on local biomass composition)

Accessing statistical data

Statistical data produced for each reporting unit is available at :dataPath/stats.json, where dataPath is specified on the reporting unit entry. Some stats are copied to the reporting unit entry itself (such as start/end stock and net change), but where they differ, the stats.json file should be considered the authoritative source.

Values at the root level of the stats.json file are calculated for the entire reporting unit, excluding areas with no data such as permanent water.

The following additional nested statistical product datasets are available for most sites:

  • forest: Areas which are forest in the selected year.
  • non_forest: Areas which are not forest in the selected year (e.g. impervious surfaces, low biomass crops).
  • forest_area_gain: Areas which are forest in the given year, but not the previous year.
  • forest_area_loss: Areas which are not forest in the given year, but was forest in the previous year.
  • forest_area_degradation: Areas which remained forest in the given year, but experienced statistically significant losses in biomass.
  • forest_degradation: Losses allocated to degradation.
  • forest_biomass_loss: Losses allocated to loss of forest area. Gradual forest loss may be recognized up to 3 years before and 1 year after a forest area loss event.

The contents of the stats.json file follow this schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "description": "Reporting unit stats created by the Chloris platform. Note that each reporting unit may represent a single site or multiple sites, each composed of one or more polygonal areas.",
  "type": "object",
  "properties": {
    "organizationId": {
      "type": "string",
      "description": "The organization id of the reporting unit."
    },
    "reportingUnitId": {
      "type": "string",
      "description": "The reporting unit id, may be a tag name or a UUID7."
    },
    "branchId": {
      "type": "string",
      "description": "If an aggregate branch (i.e. a tag or collection), this is the branch ID",
      "example": "12341234-1234-1234-1234-123412341234"
    },
    "resolution": {
      "type": "integer",
      "description": "The nominal length of one edge of each pixel in the reporting unit in meters. Typically 10 or 30, which are 100 m2 and 900 m2 pixels, respectively. Note that actual pixel sizes in rasters may vary slightly based on underlying imagery. If the reporting unit is a branch, the maximum value (largest area pixels) of the sites in the branch is used."
    },
    "count": {
      "type": "integer",
      "description": "The number of sites in the branch"
    },
    "areaKm2": {
      "type": "number",
      "description": "The area of the reporting unit(s) in square kilometers."
    },
    "reportingUnitIds": {
      "type": "array",
      "description": "The reporting unit ids of all sites in the branch."
    },
    "areaKm2DistributionBinWidth": {
      "type": "number",
      "description": "The bin width for the area distribution in square kilometers."
    },
    "areaKm2DistributionValues": {
      "type": "array",
      "description": "The frequency counts for the area distribution. For example, given a bin width of 10, and bin values of [1,2,3], there is 1 site with an area between 0-10 km2, 2 sites with an area between 10-20 km2, and 3 sites with an area between 20-30 km2."
    },
    "areaKm2Mean": {
      "type": "number",
      "description": "The mean area of sites in square kilometers."
    },
    "periodChangeStartYear": {
      "type": "integer",
      "description": "The start of the period of interest",
      "example": 2000
    },
    "periodChangeEndYear": {
      "type": "integer",
      "description": "The end of the period of interest (inclusive)",
      "example": 2023
    },
    "periodChangeStartYearStock": {
      "type": "number",
      "description": "The stock value for the start of the period of interest"
    },
    "periodChangeStartYearStockError": {
      "type": "number",
      "description": "The stock error for the start of the period of interest"
    },
    "periodChangeEndYearStock": {
      "type": "number",
      "description": "The stock value for the end of the period of interest"
    },
    "periodChangeEndYearStockError": {
      "type": "number",
      "description": "The stock error for the end of the period of interest"
    },
    "periodChange": {
      "type": "number",
      "description": "The net change in stock over the period of interest"
    },
    "periodChangeError": {
      "type": "number",
      "description": "The error in the net change in stock over the period of interest"
    },
    "periodChangeGain": {
      "type": "number",
      "description": "The gain in stock over the period of interest"
    },
    "periodChangeGainError": {
      "type": "number",
      "description": "The error in the gain in stock over the period of interest"
    },
    "periodChangeLoss": {
      "type": "number",
      "description": "The loss in stock over the period of interest"
    },
    "periodChangeLossError": {
      "type": "number",
      "description": "The error in the loss in stock over the period of interest"
    },
    "periodChangeCarryover": {
      "type": "number",
      "description": "The carryover net change in stock from sites which ended prior to the periodChangeEndYear (tonnes)"
    },
    "periodChangeCarryoverError": {
      "type": "number",
      "description": "The uncertainty (based on a 95% CI) in the carryover net change in stock."
    },
    "periodChangeCarryoverGain": {
      "type": "number",
      "description": "The carryover gain in stock from sites which ended prior to the periodChangeEndYear (tonnes)"
    },
    "periodChangeCarryoverGainError": {
      "type": "number",
      "description": "The uncertainty (based on a 95% CI) in the carryover gain in stock."
    },
    "periodChangeCarryoverLoss": {
      "type": "number",
      "description": "The carryover loss in stock from sites which ended prior to the periodChangeEndYear (tonnes)"
    },
    "periodChangeCarryoverLossError": {
      "type": "number",
      "description": "The uncertainty (based on a 95% CI) in the carryover loss in stock."
    },
    "distributionBinWidth": {
      "type": "number",
      "description": "The bin width for the distribution of stock."
    },
    "annualYears": {
      "type": "array",
      "description": "The years for which annual data is available. Index for all other annual* properties"
    },
    "annualCount": {
      "type": "array",
      "description": "The count of sites for each year in the branch"
    },
    "annualAreaKm2": {
      "type": "array",
      "description": "The area of the site(s) for each year"
    },
    "annualStock": {
      "type": "array",
      "description": "The stock value for each year (tonnes)."
    },
    "annualStockError": {
      "type": "array",
      "description": "The uncertainty (based on a 95% CI) in stock for each year (tonnes)."
    },
    "annualStockMin": {
      "type": "array",
      "description": "The minimum pixel-level stock density for each year (t/ha)."
    },
    "annualStockMax": {
      "type": "array",
      "description": "The maximum pixel-level stock density for each year (t/ha)."
    },
    "annualChange": {
      "type": "array",
      "description": "The net change for each year vs. the previous year (tonnes). First index will always be null for annualChange* properties."
    },
    "annualChangeError": {
      "type": "array",
      "description": "The uncertainty (based on a 95% CI) for the net change (tonnes)."
    },
    "annualChangeMin": {
      "type": "array",
      "description": "The minimum pixel-level year-over-year change for each year (t/ha)."
    },
    "annualChangeMax": {
      "type": "array",
      "description": "The maximum pixel-level year-over-year change for each year (t/ha)."
    },
    "annualChangeLoss": {
      "type": "array",
      "description": "Stock loss for each year vs. the previous year (tonnes)."
    },
    "annualChangeLossError": {
      "type": "array",
      "description": "The uncertainty (based on a 95% CI) for the loss in stock (tonnes)."
    },
    "annualChangeGain": {
      "type": "array",
      "description": "Stock gain for each year vs. the previous year (tonnes)."
    },
    "annualChangeGainError": {
      "type": "array",
      "description": "The uncertainty (based on a 95% CI) for the gain in stock (tonnes)."
    },
    "annualDistributionMeanValue": {
      "type": "number",
      "description": "The mean value of stock for each year."
    },
    "annualDistributionBinValues": {
      "type": "array",
      "description": "The bin values for the distribution of stock densities for each year.",
      "items": {
        "description": "The bin values for a single year. So, for example, if the bin width is 10, and the bin values are [300,200,100], there are 300 pixels between 0-10 t/ha, 200 pixels between 10-20 t/ha, and 100 pixels between 20-30 t/ha.",
        "type": "array",
        "items": {
          "type": "number",
          "description": "The bin value for a single year for a specific bin. Typically whole numbers, but may be fractional if branch includes mixed 10m and 30m sites."
        }
      }
    }
  },
  "additionalProperties": {
    "type": "object",
    "description": "Additional data products, like forest coverage and change, appear as nested stats objects."
  }
}

Here is an example of how to retrieve the stats data for a site using the chloris-app-sdk in Python:

# download_stats.py
from chloris_app_sdk import ChlorisAppClient

# create the client
client = ChlorisAppClient(
    organization_id="your-organization-id",
    refresh_token="your-refresh-token", # env: CHLORIS_REFRESH_TOKEN
    # or
    # id_token="your-id-token" # env: CHLORIS_ID_TOKEN
)

reporting_unit_id = 'abcd1234'

# get the stats of a reporting unit
reporting_unit_entry = client.get_reporting_unit(reporting_unit_id)
stats = client.get_reporting_unit_stats(reporting_unit_entry)

# print a mini report with data from 2019
print(f"Total area: {reporting_unit_entry['areaKm2']} km²")
print(f"Period start/end: {stats['periodChangeStartYear']} - {stats['periodChangeEndYear']}")

for i in range(len(stats["annualYears"])):
    year = stats["annualYears"][i]
    if year != 2019:
        continue
    print(f"Total stock ({year}): {stats['annualStock'][i]} t")
    if "forest" in stats:
        print(f"Forest area ({year}): {stats['forest']['annualAreaKm2'][i]} km²")
        print(f"Forest stock ({year}): {stats['forest']['annualStock'][i]} t")

Here is an example of how to retrieve the stats data for a site in Javascript (node):

// downloadStats.mjs
import fetch from "node-fetch";

const organizationId = "your-organization-id";
const reportingUnitId = "abcd1234";

const reporting_unit_entry_response = await fetch(`https://app.chloris.earth/api/reportingUnit/`, {
  headers: {
    Authorization: `Bearer ${idToken}`,
  },
  body: JSON.stringify({
    organizationId,
    reportingUnitId,
  }),
});
const reporting_unit_entry = await reporting_unit_entry_response.json();

const dataPath = reporting_unit_entry.dataPath.replace("s3://chloris-app-data/", "https://app.chloris.earth/");

const url = `${dataPath}/stats.json`;

const stats_response = await fetch(url);
const stats_response_json = await stats_response.json();

console.log(stats_response_json);