EcoPlots Samples Workflow

The EcoPlots client in samples mode lets you discover and retrieve physical specimen samples collected during field surveys — including soil, plant tissue, and plant voucher specimens — along with associated metadata such as IGSN identifiers and sample images.

from terndata.ecoplots import EcoPlots

ec = EcoPlots(mode="samples")                         # enable samples mode
ec.select(material_sample_type="Soil Pit Sample")     # pick a sample type
ec.preview()
df = ec.get_data(dformat="pd")                        # returns a DataFrame

Note

All methods on this page are available on both EcoPlots (synchronous) and AsyncEcoPlots (asynchronous). For AsyncEcoPlots, use df = await ec.get_data(dformat="pd") in the final step.

Note

In samples mode the TERN Ecosystem Surveillance dataset is always applied automatically. You cannot remove it; it is required for all sample queries.

Note

A runnable walkthrough of all samples-mode features is available in the Samples Demo Notebook.


Creating the Client

from terndata.ecoplots import EcoPlots

# Pass mode="samples" at creation time
ec = EcoPlots(mode="samples")

# Or reload a saved samples project
ec = EcoPlots.load("my_samples.ecoproj")

Selectables & Discoverable Facets

Filters passed to select() are called facets. The table below lists every facet available in samples mode, what it represents, and the discovery method you can call to see valid values for it.

Facet

Type

Description

Discover with

material_sample_type

str

Sample type. Exactly one must be selected before calling get_data(). See get_material_sample_types() for all available types.

get_material_sample_types()

dataset

str / list

Dataset. Fixed to TERN Ecosystem Surveillance — applied automatically and cannot be removed.

get_datasources()

site_id

str / list

One or more site identifiers.

get_sites()

region_type

str

Category of geographic region (e.g. "bioregions", "states"). Must be provided before or alongside region.

get_region_types()

region

str / list

Region name(s) within the chosen region_type.

get_regions()

speciesname

str / list

Species name. Applicable to plant tissue and voucher sample types only.

get_speciesname()

soil_subsite_id

int / list[int]

Soil sub-site identifier(s). Applicable to soil sample types only.

get_soilpit()

soil_depth_range

[min, max]

Filter samples by soil depth in metres. Applicable to soil sample types only.

get_soil_depth_range()

has_image

bool

If True, limit results to samples that have attached photographs.

(pass True or False)

spatial

WKT / GeoJSON

Spatial bounding geometry to restrict results geographically. Set interactively via select_spatial(), or pass a WKT string or GeoJSON geometry dict directly.

select_spatial() (widget)


Discovery Methods

Use these methods to explore what samples data is available before downloading. All return pandas.DataFrame and respect your current filters.

Material Sample Types

EcoPlots.get_material_sample_types()[source]

Get the material sample types from the applied filters. Available only in “samples” mode.

Returns:

A DataFrame containing the material sample types.

Raises:

EcoPlotsError – If called in a mode other than “samples”.

Return type:

DataFrame

Available types

Label

Description

Plant Tissue Sample

Subsampled tissue taken from a collected plant

Plant Voucher Specimen

Full pressed herbarium voucher specimen (may have images)

Soil Pit Sample

Bulk soil sample from a defined pit depth

Soil Subsite Sample

Replicate soil samples from sub-locations within a site

Soil Metagenomic Sample

DNA-grade soil sample for metagenomic analysis

Example

ec.get_material_sample_types()

Datasets

EcoPlots.get_datasources()[source]

Get the data sources available for applied filters.

Returns:

A DataFrame containing the data sources.

Return type:

DataFrame

Sites

EcoPlots.get_sites()[source]

Get the sites from the applied filters.

Returns:

A DataFrame containing the sites.

Return type:

DataFrame

Regions

EcoPlots.get_region_types()[source]

Get the available region types from the applied filters.

Returns:

A DataFrame containing the region types.

Return type:

DataFrame

EcoPlots.get_regions(region_type)[source]

Get the available regions for a specific region type from the applied filters.

Parameters:

region_type (str) – The region type to retrieve regions for.

Returns:

A DataFrame containing the regions for the specified region type.

Return type:

DataFrame

Species Names

EcoPlots.get_speciesname()[source]

Get species name distribution for the current filters.

Available only in “samples” mode.

This method preserves all current query filters, including has_image.

Returns:

A DataFrame with two columnsspeciesname and count.

Raises:
  • EcoPlotsError – If called in a mode other than “samples”.

  • EcoPlotsError – If none of the required material sample types are selected.

Return type:

DataFrame

Example (requires Plant Tissue Sample or Plant Voucher Specimen selected)

ec.select(material_sample_type="Plant Voucher Specimen")
ec.get_speciesname()

Filter Methods

All filter methods return self for chaining.

EcoPlots.select(filters=None, **kwargs)

Add/merge filters and validate them.

Accepts either a dict or keyword arguments.

Parameters:
  • filters (dict | None) – Mapping like {"site_id": [...], "dataset": [...]}.

  • **kwargs

    Alternative way to pass filters, e.g. site_id="ABC". Special keyword filters (handled separately from facet resolution):

    • spatial: WKT string or GeoJSON geometry dict to spatially restrict results to a custom region.

    • has_image (bool, samples mode only): Limit to samples that have attached images.

    • soil_subsite_id (int or list[int], samples mode only): Restrict to specific soil sub-site identifiers.

    • soil_depth_range ([min, max] or {"min": x, "max": y}, samples mode only): Filter samples by soil depth in metres.

    • date_from (str): Earliest date (inclusive) in any recognisable format — "DD/MM/YYYY", "21 May 2020", "21st May 2020", "YYYY-MM-DD" etc. Normalised to "YYYY-MM-DD" internally. Day-first is assumed for all-numeric inputs (MM-DD-YYYY is never accepted).

    • date_to (str): Latest date (inclusive), same format rules as date_from.

  • self (SelfType)

Raises:
Returns:

self for chaining.

Return type:

SelfType

EcoPlots.remove(filters=None, **kwargs)

Remove whole facets or specific values (same ergonomics as select).

Accepts either a dict or keyword arguments. For each facet:
  • value is None → remove the entire facet

  • value is a string → remove that single value

  • value is a list/tuple → remove those values

Parameters:
  • filters (dict | None) – Mapping like {"site_id": ["TCFTNS0002"], "dataset": None}.

  • **kwargs – Alternative way to pass removals, e.g. site_id="TCFTNS0002".

  • self (SelfType)

Raises:
  • EcoPlotsError – Unknown filter keys (not in QUERY_FACETS).

  • EcoPlotsError – If dataset is targeted while in samples mode (the TERN Ecosystem Surveillance dataset is protected).

  • KeyError – Facet not present in current filters.

  • EcoPlotsError – Specific values requested but not found for that facet.

Returns:

self (chainable)

Return type:

SelfType

EcoPlots.clear()

Clear all filters from the instance.

The method mutates the instance and returns it to allow fluent/chained calls.

Returns:

self (chainable)

Parameters:

self (SelfType)

Return type:

SelfType

Notes

In samples mode the TERN Ecosystem Surveillance dataset filter is preserved; only user-added filters are cleared.

EcoPlots.get_filter(facet=None)

Return the current filter values for a specific facet or all applied filters.

Parameters:

facet (str | None) – The facet to retrieve the filter for. Defaults to All.

Raises:

EcoPlotsError – If an invalid facet name is provided.

Returns:

A list of values for the specified facet, or None if the facet is not currently applied. If facet is None, returns a dict mapping each applied facet to its list of values.

Return type:

list | dict | None

EcoPlots.get_api_query_filters(facet=None)

Return the current query filters for ecoplots API for a specified facet or all facet.

Parameters:

facet (str | None) – The facet to retrieve the query filters for. Defaults to None.

Raises:

EcoPlotsError – If an invalid facet name is provided.

Returns:

A list of resolved API values for the specified facet, or None if the facet is not currently applied. If facet is None, returns a dict of all resolved query filters.

Return type:

list | dict | None

Samples-specific filter options

The following extra keyword arguments are accepted by select() only in samples mode:

Keyword

Type

Description

material_sample_type

str

Filter to a specific sample type (see table above).

has_image

bool

If True, limit to samples that have attached photographs.

soil_subsite_id

int or list[int]

Restrict to specific soil sub-site identifiers.

soil_depth_range

[min, max] or {"min": x, "max": y}

Restrict samples by soil depth in metres.

Example

ec.select(
    material_sample_type="Soil Pit Sample",
    soil_depth_range=[0.0, 0.5],
)

# Filter to samples with images only
ec.select(
    material_sample_type="Plant Voucher Specimen",
    has_image=True,
)

Note

Exactly one material_sample_type must be selected before calling get_data() in samples mode.


IGSN Identifiers

Every sample in the TERN Ecosystem Surveillance program is registered with the International Geo Sample Number (IGSN) system and assigned a persistent DOI. The IGSN DOI landing page for a sample is its authoritative record — it displays the officially registered attributes for that sample, including collection date, location, sample type, and parentage.

get_sample_igsn() returns a DataFrame of sample names paired with their IGSN DOIs. view_sample_igsn() opens an interactive widget with an embedded iframe that loads the DOI landing page for any sample you select from a dropdown.

EcoPlots.get_sample_igsn()[source]

Get sample names and derived IGSN values.

Available only in samples mode. This method discovers sample_name values using the current query filters, then returns a DataFrame with: - sample_name: sample name with alphabetic characters capitalized. - igsn: derived as 10.60792/{sample_name_raw}.

Returns:

A DataFrame with columns sample_name and igsn.

Raises:

EcoPlotsError – If called in a mode other than samples.

Return type:

DataFrame

EcoPlots.view_sample_igsn(igsn=None)[source]

Open an interactive notebook viewer for sample IGSN DOI pages.

Available only in samples mode. This method discovers sample names, builds IGSN values, and displays either: - a dropdown + iframe widget (default), or - a single iframe for a provided IGSN/DOI value.

Parameters:

igsn (str | None) – Optional IGSN value or DOI URL. Accepted inputs include 10.60792/..., doi.org/10.60792/..., and https://doi.org/10.60792/....

Returns:

ipywidgets.VBox – Interactive IGSN viewer widget.

Raises:

Example

# Retrieve IGSN DOIs for the currently filtered samples
ec.get_sample_igsn()

# Open the IGSN viewer widget — choose a sample to load its
# DOI landing page (registered attributes) in the embedded iframe
ec.view_sample_igsn()

# Or navigate directly to a known sample's landing page
ec.view_sample_igsn(igsn="10.60792/AUSM-0017401")
IGSN viewer widget with a sample selected and its DOI landing page loaded in the iframe

The IGSN viewer widget. Choose a sample from the dropdown to load its IGSN DOI landing page — displaying the officially registered attributes for that sample — in the embedded iframe.


Soil Analysis

EcoPlots.get_soil_depth_range()[source]

Get the soil depth range for the current filters.

Available only in “samples” mode.

Returns:

A GeoDataFrame containing aggregated soil depth range values.

Raises:
  • EcoPlotsError – If called in a mode other than “samples”.

  • EcoPlotsError – If none of the required material sample types are selected.

Return type:

geopandas.GeoDataFrame

EcoPlots.get_soilpit()[source]

Get soil pit distribution for the current filters.

Available only in “samples” mode.

Returns:

A DataFrame with two columnssoilpit and counts.

Raises:
  • EcoPlotsError – If called in a mode other than “samples”.

  • EcoPlotsError – If none of the required material sample types are selected.

Return type:

DataFrame

Example (requires a soil material sample type to be selected)

ec.select(material_sample_type="Soil Pit Sample")

# Aggregated depth-range summary as a GeoDataFrame
ec.get_soil_depth_range()

# Soil pit distribution counts
ec.get_soilpit()

Sample Image Viewer

For samples that have photographs attached, view_sample_images() opens an interactive viewer. Each image may be available in multiple resolutions — the viewer lets you select the resolution you want to display.

EcoPlots.view_sample_images(data=None, image_column='sample_images', sample_id_column='sample_id', sample_name_column='sample_name', scientific_name_column='scientific_name')[source]

Open an interactive notebook image browser for sample images.

Parameters:
  • data (DataFrame | None) – Optional DataFrame to browse. If omitted, data is fetched in samples mode using current filters.

  • image_column (str) – Name of image column in dataframe.

  • sample_id_column (str) – Name of sample identifier column in dataframe.

  • sample_name_column (str) – Name of sample name column in dataframe.

  • scientific_name_column (str) – Name of scientific name column in dataframe.

Returns:

ipywidgets.VBox – Interactive viewer widget.

Example

ec.select(
    material_sample_type="Plant Voucher Specimen",
    has_image=True,
)
ec.view_sample_images()   # fetches data and opens the image viewer widget
Sample image viewer widget showing a grid of plant specimen photos

The sample image viewer widget. Navigate through specimen photos using the previous/next controls.


Spatial Filter Widget

Draw a polygon or rectangle on a map to restrict results to a geographic area.

EcoPlots.select_spatial(**kwargs)[source]

Open the spatial selection widget.

A minimal map based spatial selector, similar to spatial selection tool in EcoPlots Portal.

Parameters:

**kwargs – Additional keyword arguments to pass to the widget.

Returns:

ipywidgets.VBox – The widget. Use it in a notebook cell to display.

Example

ec.select_spatial()

Data Preview & Retrieval

EcoPlots.summary(dformat=None)[source]

Summarize the EcoPlots data.

Parameters:

dformat (str | None) – The desired format for the summary. If "json", returns the raw summary dict from the API. Defaults to None, which returns a pandas.DataFrame.

Returns:

When dformat is "json", returns the raw summary dict from the API. Otherwise, returns a pandas.DataFrame with columns metric and count summarising the current selection (e.g. total observations, unique sites, datasets).

Return type:

DataFrame | str

EcoPlots.preview(dformat=None)[source]

Fetch a small preview of EcoPlots data. # noqa: DAR401, D415

Mirrors get_data() but limits results to 10 records for a quick look.

In observations mode, fetches CSV from up to 2 feature types (5 rows each). In samples mode, calls the samples endpoint and returns the first 10 rows; "geojson"/"json" formats are not supported in this mode.

Parameters:

dformat (str | None) – Output format. - "geojson" or "json": returns a GeoJSON dict (observations only). - "pandas" (or "pd"): returns a pandas.DataFrame. - "geopandas" (or "gpd") (default): returns a GeoDataFrame.

Returns:

Preview data in the requested format.

Raises:
  • EcoPlotsError – If an invalid dformat is provided.

  • RuntimeError – If no feature types found (observations mode).

Return type:

geopandas.GeoDataFrame | dict | str

EcoPlots.get_data(allow_full_download=False, dformat='gpd')[source]

Retrieve EcoPlots data based on the current filters.

Parameters:
  • allow_full_download (bool | None) – If True, allows downloading the full dataset without filters. Defaults to False.

  • dformat (str | None) –

    Output format. - “geojson” or “json”: returns a pretty-printed GeoJSON string. - “pandas” (or ‘pd’): returns a pandas DataFrame. - “geopandas” (or ‘gpd’) (default): returns a GeoDataFrame.

    In “samples” mode, only “pandas”/”pd” and “geopandas”/”gpd” are supported (no “geojson”/”json”).

    In “samples” mode, exactly one material_sample_type must be selected at a time.

Raises:
  • RuntimeError – If no filters are set and allow_full_download is False.

  • EcoPlotsError – If an invalid dformat is provided.

Returns:

Data in the requested format.

Return type:

geopandas.GeoDataFrame

Typical workflow

# 1. Confirm there are matching records
ec.summary()

# 2. Quick preview before full download
ec.preview()

# 3. Download the full dataset
df  = ec.get_data(dformat="pd")   # pandas DataFrame
gdf = ec.get_data()               # GeoDataFrame (default)

Note

In samples mode get_data() does not support the "geojson" / "json" formats. Use "pd" or "gpd" only.


Project Save / Load

EcoPlots.save(path=None)

Save project state to a single .ecoproj file (atomic, checksummed).

Writes the current filters and query_filters into a compact binary file with a small header and a JSON (orjson) payload. The filename resolution is:

  • If path is None: save as ./ecoplots_<UTCSTAMP>.ecoproj.

  • If path has no .ecoproj suffix and no parent directory: save as

    ./<name>.ecoproj in the current working directory.

  • If path ends with .ecoproj: save exactly to that location.

Parameters:

path (str | Path | None) – Optional target path or bare name. If omitted, a timestamped filename is created in the current working directory.

Returns:

Absolute path to the saved .ecoproj file.

Raises:

Exception – Any unexpected error during the write; temporary files are cleaned up best-effort before re-raising.

Return type:

str

classmethod EcoPlots.load(path)

Load a .ecoproj file, validate integrity, and return a new instance.

Parameters:

path (str | Path) – Path to a .ecoproj file previously created by save().

Returns:

A new instance of the calling class with filters and query_filters restored from the file.

Raises:
  • FileNotFoundError – If the file does not exist.

  • EcoPlotsError – If the file does not have a .ecoproj suffix, the magic header or version is invalid, the file is truncated, or the checksum does not match the payload.

Return type:

SelfType

Example

path = ec.save("soil_pit_survey.ecoproj")

# Reload — mode and all filters are fully restored
ec2 = EcoPlots.load(path)
ec2.get_filter()