Internal Modules

These modules contain the internal implementation of the EcoPlots library. They are not part of the public API but are documented here for contributors and advanced users.

class terndata.ecoplots._base.Iterable[source]

Bases: object

terndata.ecoplots._base.resolve_facet(user_input, allowed_facets, threshold=70)[source]

Resolve user input to the closest allowed facet using fuzzy matching.

Parameters:
  • user_input (str) – The input string from the user to be matched against allowed facets.

  • allowed_facets (list) – A list of valid facet names that the user input can be matched to.

  • threshold (int) – The minimum similarity score (0-100) required for a match. Defaults to 70.

Returns:

The matched facet name if found, else None.

Return type:

str | None

Notes

  • Intended for internal use only.

terndata.ecoplots._base.resolve_region_type(user_input, allowed_region_types=['subregions', 'bioregions', 'nrm-regions', 'states-and-territories', 'local-government-areas', 'wwf-ecoregions', 'terrestrial-capad-regions'], threshold=90)[source]

Resolve a user-provided region type or URL to the closest allowed region type.

Parameters:
  • user_input (str) – The user input, which can be a region type label or a URL.

  • allowed_region_types (list) – List of allowed region type labels to match against. Defaults to REGION_TYPES.

  • threshold (int) – Minimum fuzzy match score required to consider a match valid. Defaults to 90.

Returns:

The resolved region type label if a match is found; otherwise, None.

Raises:

EcoPlotsError – If the input cannot be resolved to a known region type or URL, or if no close matches are found.

Return type:

str | None

Notes

  • Intended for internal use only.

terndata.ecoplots._base.validate_facet(facet, value)[source]

Validate and resolve user-provided values for a given facet to their corresponding URLs.

Parameters:
  • facet – The name of the facet to validate (e.g., a field or category).

  • value (Any) – The value(s) to validate. Can be a single value or a list/tuple of values.

Returns:

tuple

A tuple containing:
  • facet (str): The facet name.

  • urls (list): List of resolved URLs corresponding to the provided values.

  • matched (list): List of values that were successfully matched.

  • unmatched (list): List of values that could not be matched.

  • corrected (list): List of corrected values, if any corrections were applied.

Raises:

None

Return type:

tuple

class terndata.ecoplots._base.EcoPlotsBase(filterset=None, query_filters=None, mode='observations')[source]

Bases: object

Base class providing internal filter management and API query building.

This class implements the low-level mechanics for holding, validating and converting user-supplied filters into API-ready query filters. It is intended for internal use by ecoplots subclasses and is not part of the user-facing public API.

Parameters:
  • filterset (dict | None)

  • query_filters (dict | None)

  • mode (str)

_filters

Human/canonical filter values as provided.

_query_filters

API-ready filter values (usually URLs).

select(filters=None, **kwargs)[source]

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

remove(filters=None, **kwargs)[source]

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

clear()[source]

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.

from_date(date)[source]

Set an earliest-date filter (inclusive).

Chainable with till(). The date string is parsed tolerantly — "DD/MM/YYYY", "21 May 2020", "21st May 2020", "YYYY-MM-DD" etc. are all accepted. For all-numeric inputs the day-first convention (DD-MM-YYYY) is always used.

Equivalent to select(date_from=date).

Parameters:
  • date (str) – Start date in any recognisable human format.

  • self (SelfType)

Returns:

self (chainable)

Raises:

EcoPlotsError – If the date string cannot be parsed.

Return type:

SelfType

Examples

ec.select(site_id="ABC").from_date("01/01/2020").to_date("31/12/2022")
to_date(date)[source]

Set a latest-date filter (inclusive).

Chainable with from_date(). Accepts the same flexible date formats — "DD/MM/YYYY", "31 Dec 2022", "YYYY-MM-DD", etc.

Equivalent to select(date_to=date).

Parameters:
  • date (str) – End date in any recognisable human format.

  • self (SelfType)

Returns:

self (chainable)

Raises:

EcoPlotsError – If the date string cannot be parsed.

Return type:

SelfType

Examples

ec.select(site_id="ABC").from_date("01/01/2020").to_date("31/12/2022")
get_filter(facet=None)[source]

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

get_api_query_filters(facet=None)[source]

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

discover(discovery_facet, region_type=None)[source]

Resolve and call the discovery endpoint for a facet.

Parameters:
  • discovery_facet (str) – Facet to discover (must resolve via configured discovery facets).

  • region_type (str | None) – Optional region type used when discovering regions.

Returns:

Parsed JSON payload returned by the discovery endpoint.

Raises:

EcoPlotsError – If the facet cannot be resolved.

Return type:

dict

Notes

  • Internal use only

  • A 60-second request timeout is enforced.

discover_samples(discovery_facet, region_type=None)[source]

Resolve and call the discovery endpoint for samples.

Parameters:
  • discovery_facet (str) – Facet to discover (must resolve via SAMPLE_DISCOVERY_FACETS).

  • region_type (str | None) – Optional region type used when discovering regions. Required when discovery_facet is “region”.

Returns:

Parsed JSON payload returned by the discovery endpoint.

Raises:

EcoPlotsError – If the facet cannot be resolved or region_type is missing when discovering regions.

Return type:

dict

Notes

  • Internal use only

  • A 60-second request timeout is enforced.

discover_soil_depth_range()[source]

Discover soil depth range aggregates for the current query.

Sends the current samples query to the /samples/soildepth endpoint and returns a single-row GeoDataFrame with descriptive depth summary columns.

Returns:

geopandas.GeoDataFrame – One-row table with soil depth aggregate values.

Raises:

EcoPlotsError – If called outside samples mode.

discover_soilpit()[source]

Discover soil pit distribution for the current samples query.

Sends the current query to the /samples/soilpit endpoint and returns a two-column table with the soil pit identifier and its document count.

Returns:

pandas.DataFrame – Columns are soilpit and counts.

Raises:

EcoPlotsError – If called outside samples mode.

discover_species()[source]

Discover species name distribution for the current samples query.

Sends the current query to the /samples/speciesname endpoint and returns a two-column table with species name and document count.

Notes

  • Preserves all query filters including has_image.

Returns:

pandas.DataFrame – Columns are speciesname and count.

Raises:

EcoPlotsError – If called outside samples mode.

async fetch_data(page_number=None, page_size=None, dformat='geojson', **extras)[source]

Fetch data for the current query, optionally paginated.

Posts the current query filters to EcoPlots API data endpoint.

Parameters:
  • page_number (int | None) – Page index to request. Must be provided together with page_size.

  • page_size (int | None) – Number of items per page. Must be provided together with page_number.

  • dformat (str) – Output format, either “geojson” (default) or “csv”.

  • **extras – Additional query filters to merge into the current query

Returns:

Parsed JSON payload (GeoJSON) returned by the data endpoint.

Raises:

EcoPlotsError – If an invalid dformat is provided.

Return type:

dict

Notes

  • Timeout is 300s (5 min) when pagination is used; 3000s (50 min) otherwise.

  • Socket read timeout matches total timeout; connection timeout is 30s.

  • Intended for internal use only.

async fetch_samples_data()[source]

Fetch sample data from the samples endpoint.

Returns data as a geopandas GeoDataFrame extracted from the _source field of response hits.

Returns:

A geopandas GeoDataFrame with sample data.

Raises:

EcoPlotsError – If material_sample_type is not selected or if multiple material_sample_types are selected (only one allowed).

Notes

  • Timeout is 300s (5 min)

  • material_sample_type is required and must be single-valued

  • Intended for internal use only

discover_attributes(discovery_attribute)[source]

Discovers attribute URIs for a given entity type.

Parameters:

discovery_attribute (str) – Attribute namespace to discover (must resolve via configured discovery attributes).

Returns:

Parsed JSON payload containing attribute identifiers.

Raises:

EcoPlotsError – If the attribute cannot be resolved.

Return type:

dict

Notes

  • A 30-second request timeout is enforced.

  • Intended for internal use only.

summarise_data(query_filters=None)[source]

Request a lightweight summary for the given or current query filters.

Parameters:

query_filters (dict | None) – Canonical filters to use for the summary. When omitted, the instance’s current canonical query filters are used.

Returns:

Parsed JSON payload containing counts and related summary fields.

Return type:

dict

Notes

  • A 30-second request timeout is enforced.

  • Intended for internal use only.

save(path=None)[source]

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 load(path)[source]

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

Custom exceptions for the EcoPlots library.

This module defines custom exception classes that provide cleaner error messages in Jupyter/IPython environments while maintaining standard Python exception behavior in scripts.

exception terndata.ecoplots._exceptions.EcoPlotsError[source]

Bases: Exception

Base exception class for EcoPlots library errors.

This exception provides clean, user-friendly error messages in Jupyter notebooks by displaying errors with an ❌ emoji prefix instead of verbose Python tracebacks with file paths. In standard Python scripts, it behaves like a normal exception.

The clean display is automatically enabled when running in IPython/Jupyter environments and falls back to standard exception behavior otherwise.

Examples

In a Jupyter notebook:
>>> raise EcoPlotsError("Invalid filter configuration")
❌ Invalid filter configuration
In a Python script:
>>> raise EcoPlotsError("Invalid filter configuration")
Traceback (most recent call last):
  ...
EcoPlotsError: Invalid filter configuration

Notes

  • Detection of Jupyter environment is done via get_ipython() builtin

  • The __str__ method is called by Jupyter for display representation

  • Standard exception message is preserved for programmatic access via str(e)

class terndata.ecoplots._utils.Coroutine[source]

Bases: Awaitable

abstractmethod send(value)[source]

Send a value into the coroutine. Return next yielded value or raise StopIteration.

abstractmethod throw(typ, val=None, tb=None)[source]

Raise an exception in the coroutine. Return next yielded value or raise StopIteration.

close()[source]

Raise GeneratorExit inside coroutine.

class terndata.ecoplots._utils.datetime(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])

Bases: date

The year, month and day arguments are required. tzinfo may be None, or an instance of a tzinfo subclass. The remaining arguments may be ints.

astimezone()

tz -> convert to local time in new timezone tz

classmethod combine()

date, time -> datetime with same date and time fields

ctime()

Return ctime() style string.

date()

Return date object with same year, month and day.

dst()

Return self.tzinfo.dst(self).

fold
classmethod fromisoformat(object, /)

string -> datetime from a string in most ISO 8601 formats

classmethod fromtimestamp()

timestamp[, tz] -> tz’s local time from POSIX timestamp.

hour
isoformat()

[sep] -> string in ISO 8601 format, YYYY-MM-DDT[HH[:MM[:SS[.mmm[uuu]]]]][+HH:MM]. sep is used to separate the year from the time, and defaults to ‘T’. The optional argument timespec specifies the number of additional terms of the time to include. Valid options are ‘auto’, ‘hours’, ‘minutes’, ‘seconds’, ‘milliseconds’ and ‘microseconds’.

max = datetime.datetime(9999, 12, 31, 23, 59, 59, 999999)
microsecond
min = datetime.datetime(1, 1, 1, 0, 0)
minute
classmethod now(tz=None)

Returns new datetime object representing current time local to tz.

tz

Timezone object.

If no tz is specified, uses local timezone.

replace()

Return datetime with new specified fields.

resolution = datetime.timedelta(microseconds=1)
second
classmethod strptime()

string, format -> new datetime parsed from a string (like time.strptime()).

time()

Return time object with same time but with tzinfo=None.

timestamp()

Return POSIX timestamp as float.

timetuple()

Return time tuple, compatible with time.localtime().

timetz()

Return time object with same time and tzinfo.

tzinfo
tzname()

Return self.tzinfo.tzname(self).

classmethod utcfromtimestamp()

Construct a naive UTC datetime from a POSIX timestamp.

classmethod utcnow()

Return a new datetime representing UTC day and time.

utcoffset()

Return self.tzinfo.utcoffset(self).

utctimetuple()

Return UTC time tuple, compatible with time.localtime().

class terndata.ecoplots._utils.timezone

Bases: tzinfo

Fixed offset from UTC implementation of tzinfo.

dst(object, /)

Return None.

fromutc(object, /)

datetime in UTC -> datetime in local time.

max = datetime.timezone(datetime.timedelta(seconds=86340))
min = datetime.timezone(datetime.timedelta(days=-1, seconds=60))
tzname(object, /)

If name is specified when timezone is created, returns the name. Otherwise returns offset as ‘UTC(+|-)HH:MM’.

utc = datetime.timezone.utc
utcoffset(object, /)

Return fixed offset.

class terndata.ecoplots._utils.Any(*args, **kwargs)[source]

Bases: object

Special type indicating an unconstrained type.

  • Any is compatible with every type.

  • Any assumed to have all methods.

  • All values assumed to be instances of Any.

Note that all the above statements are true from the point of view of static type checkers. At runtime, Any should not be used with instance checks.

Configuration constants for the EcoPlots library.

Defines the API base URL, cache settings, magic bytes for .ecoproj binary project files, and the facet lists that control which filter keys are valid in each operational mode ("observations" / "samples").

terndata.ecoplots._nlp_utils.resolve_facet(user_input, allowed_facets, threshold=70)[source]

Resolve user input to the closest allowed facet using fuzzy matching.

Parameters:
  • user_input (str) – The input string from the user to be matched against allowed facets.

  • allowed_facets (list) – A list of valid facet names that the user input can be matched to.

  • threshold (int) – The minimum similarity score (0-100) required for a match. Defaults to 70.

Returns:

The matched facet name if found, else None.

Return type:

str | None

Notes

  • Intended for internal use only.

terndata.ecoplots._nlp_utils.resolve_region_type(user_input, allowed_region_types=['subregions', 'bioregions', 'nrm-regions', 'states-and-territories', 'local-government-areas', 'wwf-ecoregions', 'terrestrial-capad-regions'], threshold=90)[source]

Resolve a user-provided region type or URL to the closest allowed region type.

Parameters:
  • user_input (str) – The user input, which can be a region type label or a URL.

  • allowed_region_types (list) – List of allowed region type labels to match against. Defaults to REGION_TYPES.

  • threshold (int) – Minimum fuzzy match score required to consider a match valid. Defaults to 90.

Returns:

The resolved region type label if a match is found; otherwise, None.

Raises:

EcoPlotsError – If the input cannot be resolved to a known region type or URL, or if no close matches are found.

Return type:

str | None

Notes

  • Intended for internal use only.

terndata.ecoplots._nlp_utils.resolve_single_input(candidate, labels_dict, threshold=80)[source]

Resolve a single input (name or URL) to the canonical URL using RapidFuzz.

Parameters:
  • candidate (str) – The user input to resolve.

  • labels_dict (dict[str, str]) – A dictionary mapping canonical URLs to user-friendly names.

  • threshold (int) – The minimum similarity score for a match to be considered valid.

Raises:

EcoPlotsError – If the input cannot be resolved to a known label or URL.

Returns:

The resolved canonical URL if a match is found; otherwise, raises a EcoPlotsError.

Return type:

str

Notes

  • Intended for internal use only.

async terndata.ecoplots._nlp_utils.resolve_facet_inputs(facet, user_values, region_type=None)[source]

Resolve all user inputs for a facet to canonical URLs.

Runs sequentially but can be scheduled concurrently per facet.

Parameters:
  • facet (str) – The facet to resolve.

  • user_values (list[str]) – The user input values to resolve.

  • region_type (str | None) – The region type to use for resolution (if applicable).

Raises:

EcoPlotsError – If region facet is used without region_type.

Returns:

A list of resolved canonical URLs.

Return type:

list[str]

Notes

  • If a user value cannot be resolved, a warning will be issued.

terndata.ecoplots._nlp_utils.resolve_filter_values_to_urls(facet, user_values, labels_dict, threshold=75)[source]

Validate and resolve a list of filter values (labels or URLs) for a facet.

Parameters:
  • facet (str) – The facet name (e.g., “region”, “dataset”).

  • user_values (list) – The user input values to resolve.

  • labels_dict (dict) – A dictionary mapping URLs to user-friendly names.

  • threshold (int) – The minimum similarity score for a match to be considered valid.

Returns:

A list of canonical URLs; raises warning for fuzzy, error for not found.

Notes

  • If a user value cannot be resolved, a warning will be issued.

  • Intended for internal use only.

terndata.ecoplots._nlp_utils.validate_facet(facet, value)[source]

Validate and resolve user-provided values for a given facet to their corresponding URLs.

Parameters:
  • facet – The name of the facet to validate (e.g., a field or category).

  • value (Any) – The value(s) to validate. Can be a single value or a list/tuple of values.

Returns:

tuple

A tuple containing:
  • facet (str): The facet name.

  • urls (list): List of resolved URLs corresponding to the provided values.

  • matched (list): List of values that were successfully matched.

  • unmatched (list): List of values that could not be matched.

  • corrected (list): List of corrected values, if any corrections were applied.

Raises:

None

Return type:

tuple

Spatial selector widget for EcoPlots.

This module provides a Jupyter/ipywidgets-based map control that lets a user draw a rectangle or polygon and then preview/confirm a WKT spatial filter that is passed to ecoplots.select(spatial=<WKT>). It embeds TERN/EcoPlots branding and keeps the map bounded to Australia.

class terndata.ecoplots._gui.spatial_selector.Any(*args, **kwargs)[source]

Bases: object

Special type indicating an unconstrained type.

  • Any is compatible with every type.

  • Any assumed to have all methods.

  • All values assumed to be instances of Any.

Note that all the above statements are true from the point of view of static type checkers. At runtime, Any should not be used with instance checks.

terndata.ecoplots._gui.spatial_selector.spatial_selector(ecoplots, *, center=(-25.0, 133.0), zoom=4)[source]

Create a Jupyter widget to select a spatial filter and apply it via select().

Workflow:
  1. Draw rectangle or polygon on the map

  2. Click Preview to print the WKT POLYGON(…)

  3. Click Confirm to call ecoplots.select(spatial=<WKT>)

  4. Clear resets selection and zooms back to Australia

Parameters:
  • ecoplots (Any) – EcoPlots instance to update upon Confirm.

  • center (tuple[float, float]) – Initial center (lat, lon).

  • zoom (int) – Initial zoom level.

Returns:

ipywidgets.VBox for display in Jupyter.

Return type:

ipywidgets.VBox