Skip to content

Configuration#

earthlens writes two different kinds of file, and they go to two different places.

What lands there Set it with Environment variable Default
Output the products you asked for set_output_dir() EARTHLENS_DATA_DIR ~/.earthlens/data
Cache regenerable intermediates set_cache_dir() EARTHLENS_CACHE the per-platform user cache directory

Keeping them apart matters: a cleanup script that deletes anything called a cache must not take your requested products with it.

Pointing earthlens at one location#

from earthlens.core import EarthLens, set_output_dir, set_cache_dir

set_output_dir("/data/earthlens")        # or: export EARTHLENS_DATA_DIR=/data/earthlens
set_cache_dir("/data/earthlens-cache")   # or: export EARTHLENS_CACHE=/data/earthlens-cache

EarthLens(data_source="chc", variables=["precipitation"],
          start="2009-01-01", end="2009-01-02").download()
# writes under /data/earthlens/chc

Resolution order for each directory, highest priority first:

  1. the set_*_dir() override;
  2. the environment variable;
  3. the built-in default.

Both are process-wide with no locking. Set them once at process start, before constructing any backend: a backend captures its output directory at construction, so changing the setting mid-run splits output across two locations rather than raising.

Where a download goes#

path= on a backend (or on the EarthLens facade) always wins:

You pass It writes to
path="out" ./out — a relative path is anchored to the working directory
path="/data/run" /data/run
path="" the current working directory
nothing at all the configured output directory

The facade adds a per-source subdirectory when path is omitted, so EarthLens(data_source="chc", …).download() writes under <output_dir()>/chc/.

This changed

Before this was introduced, omitting path= wrote to the current working directory, and the facade wrote to ./earthlens-data/<source>/. If you have a script that globbed ./earthlens-data/** afterwards, it now finds nothing. To keep the old behaviour, pass path="" for the working directory, or set EARTHLENS_DATA_DIR=. — and your existing files are still wherever they were written, nothing was moved for you.

Where cached intermediates go#

Backends that download an archive, extract or index on the way to their output cache it under the shared cache directory, each in its own subdirectory:

Backend Cache subdirectory
aqueduct, catrare, flopros, glaciers, solar_wind_atlas aqueduct/, catrare/, …
cmip6 cmip6/
caravan caravan/
nwp nwp/idx/
osm osm_pbf/

Backends that expose a cache_dir= argument still let you override it for one request.

This changed too

These nine backends previously cached in three different places: some under your output path= (<path>/_aqueduct_cache/ and friends), some under ~/.earthlens/cache/, and some under the platform user cache. They now all follow cache_dir().

Nothing is migrated for you, so anything cached by an earlier version is simply left behind. It is all regenerable — delete the old directories whenever convenient:

  • ~/.earthlens/cache/ (the old osm and cmip6 caches)
  • the old platform cache, which on Windows had a doubled path segment (…\AppData\Local\earthlens\earthlens\Cache, now …\AppData\Local\earthlens\Cache)
  • any _aqueduct_cache/, _catrare_cache/, _flopros_cache/, _glaciers_cache/ or _cache/gsa/ folder sitting inside a previous output directory

The caravan cache in particular can be tens of GB, so it is worth checking.

API#

Process-wide directories for earthlens output and cached intermediates.

earthlens writes two different kinds of file, and they belong in two different places:

  • Output — the products a caller asked for. A backend given an explicit path= writes there; otherwise the location is resolved by output_dir(), so a whole project can be pointed at one location (a NAS mount, say) without threading path= through every call.
  • Cache — raw intermediates a backend downloads on the way to that output: archives it unzips, .osm.pbf extracts, GRIB index sidecars, catalog CSVs. These are regenerable, so they are kept out of the output tree and resolved by cache_dir(). Backends that expose a cache_dir= argument still let a caller override it per request.

Keeping them apart matters: a cleanup script that deletes anything called a cache must not take requested products with it.

Both settings are process-wide module state with no locking. Set them once at process start, before any backend is constructed: a backend captures its output directory at construction, so changing a setting mid-run splits output across two locations rather than raising.

Resolution order for each, highest priority first:

output cache
1 set_output_dir(...) set_cache_dir(...)
2 EARTHLENS_DATA_DIR EARTHLENS_CACHE
3 ~/.earthlens/data the per-platform user cache directory
Example
from earthlens.core import EarthLens, set_output_dir

set_output_dir("/data/earthlens")             # or: set EARTHLENS_DATA_DIR=...
EarthLens(data_source="chc", ...).download()  # writes under /data/earthlens/chc

set_output_dir(path) #

Set the process-wide directory downloads are written to.

Takes precedence over the EARTHLENS_DATA_DIR environment variable. Only None clears a previous override; every other value is treated as a directory, so "" means the current working directory rather than a reset.

Parameters:

Name Type Description Default
path str | PathLike[str] | None

The directory to use, or None to clear a previous override and fall back to the environment variable (then the built-in default). ~ is expanded and the value is made absolute, so a relative value is anchored to the current working directory. The directory is not created here; it is created lazily when a download first writes to it.

required

Examples:

  • Point every backend at one directory, then clear the override:
    >>> from earthlens.config import output_dir, set_output_dir
    >>> set_output_dir("/data/earthlens")
    >>> output_dir().name
    'earthlens'
    >>> set_output_dir(None)
    
  • The override wins over whatever the environment says:
    >>> from earthlens.config import output_dir, set_output_dir
    >>> set_output_dir("/data/first")
    >>> output_dir().name
    'first'
    >>> set_output_dir("/data/second")
    >>> output_dir().name
    'second'
    >>> set_output_dir(None)
    
See Also

output_dir: Reads back the directory this function sets. set_cache_dir: The equivalent for regenerable intermediates.

Source code in libs/core/src/earthlens/config.py
def set_output_dir(path: str | os.PathLike[str] | None) -> None:
    """Set the process-wide directory downloads are written to.

    Takes precedence over the `EARTHLENS_DATA_DIR` environment variable. Only
    `None` clears a previous override; every other value is treated as a
    directory, so `""` means the current working directory rather than a reset.

    Args:
        path: The directory to use, or `None` to clear a previous override and
            fall back to the environment variable (then the built-in default).
            `~` is expanded and the value is made absolute, so a relative value
            is anchored to the current working directory. The directory is not
            created here; it is created lazily when a download first writes to
            it.

    Examples:
        - Point every backend at one directory, then clear the override:
            ```python
            >>> from earthlens.config import output_dir, set_output_dir
            >>> set_output_dir("/data/earthlens")
            >>> output_dir().name
            'earthlens'
            >>> set_output_dir(None)

            ```
        - The override wins over whatever the environment says:
            ```python
            >>> from earthlens.config import output_dir, set_output_dir
            >>> set_output_dir("/data/first")
            >>> output_dir().name
            'first'
            >>> set_output_dir("/data/second")
            >>> output_dir().name
            'second'
            >>> set_output_dir(None)

            ```

    See Also:
        output_dir: Reads back the directory this function sets.
        set_cache_dir: The equivalent for regenerable intermediates.
    """
    global _output_override
    _output_override = None if path is None else _resolve(path)

output_dir() #

Resolve the directory earthlens downloads are written to.

Resolution order: the set_output_dir() override, then the EARTHLENS_DATA_DIR environment variable, then ~/.earthlens/data.

Returns:

Type Description
Path

The resolved absolute directory. It is not created here; backends

Path

create it lazily on the first download that writes to it.

Examples:

  • Read back the directory the next download will write to:
    >>> from earthlens.config import output_dir, set_output_dir
    >>> set_output_dir("/data/earthlens")
    >>> output_dir().is_absolute()
    True
    >>> output_dir().name
    'earthlens'
    >>> set_output_dir(None)
    
  • Resolving the directory never creates it on disk:
    >>> from earthlens.config import output_dir, set_output_dir
    >>> set_output_dir("/data/earthlens-not-created-by-resolving")
    >>> output_dir().exists()
    False
    >>> set_output_dir(None)
    
See Also

set_output_dir: Sets the override this function reads first. earthlens.base.AbstractDataSource: Falls back to this directory when it is constructed without an explicit path.

Source code in libs/core/src/earthlens/config.py
def output_dir() -> Path:
    """Resolve the directory earthlens downloads are written to.

    Resolution order: the `set_output_dir()` override, then the
    `EARTHLENS_DATA_DIR` environment variable, then `~/.earthlens/data`.

    Returns:
        The resolved absolute directory. It is *not* created here; backends
        create it lazily on the first download that writes to it.

    Examples:
        - Read back the directory the next download will write to:
            ```python
            >>> from earthlens.config import output_dir, set_output_dir
            >>> set_output_dir("/data/earthlens")
            >>> output_dir().is_absolute()
            True
            >>> output_dir().name
            'earthlens'
            >>> set_output_dir(None)

            ```
        - Resolving the directory never creates it on disk:
            ```python
            >>> from earthlens.config import output_dir, set_output_dir
            >>> set_output_dir("/data/earthlens-not-created-by-resolving")
            >>> output_dir().exists()
            False
            >>> set_output_dir(None)

            ```

    See Also:
        set_output_dir: Sets the override this function reads first.
        earthlens.base.AbstractDataSource: Falls back to this directory when it
            is constructed without an explicit `path`.
    """
    if _output_override is not None:
        return _output_override
    env = os.environ.get(OUTPUT_DIR_ENV)
    if env:
        return _resolve(env)
    return _resolve(Path.home() / ".earthlens" / "data")

set_cache_dir(path) #

Set the process-wide directory regenerable intermediates are cached in.

Takes precedence over the EARTHLENS_CACHE environment variable. Only None clears a previous override; every other value is treated as a directory, so "" means the current working directory rather than a reset.

This is the root each backend hangs its own subdirectory off — the archives, extracts and index sidecars it downloads on the way to producing output. It is not where requested products land; that is output_dir().

Parameters:

Name Type Description Default
path str | PathLike[str] | None

The directory to use, or None to clear a previous override and fall back to the environment variable (then the built-in default). ~ is expanded and the value is made absolute. The directory is not created here; each backend creates its own subdirectory on first use.

required

Examples:

  • Point every backend's intermediates at one directory:
    >>> from earthlens.config import cache_dir, set_cache_dir
    >>> set_cache_dir("/data/earthlens-cache")
    >>> cache_dir().name
    'earthlens-cache'
    >>> set_cache_dir(None)
    
  • Backends hang their own subdirectory off it:
    >>> from earthlens.config import cache_dir, set_cache_dir
    >>> set_cache_dir("/data/earthlens-cache")
    >>> (cache_dir() / "osm_pbf").name
    'osm_pbf'
    >>> set_cache_dir(None)
    
See Also

cache_dir: Reads back the directory this function sets. set_output_dir: The equivalent for requested products.

Source code in libs/core/src/earthlens/config.py
def set_cache_dir(path: str | os.PathLike[str] | None) -> None:
    """Set the process-wide directory regenerable intermediates are cached in.

    Takes precedence over the `EARTHLENS_CACHE` environment variable. Only
    `None` clears a previous override; every other value is treated as a
    directory, so `""` means the current working directory rather than a reset.

    This is the root each backend hangs its own subdirectory off — the archives,
    extracts and index sidecars it downloads on the way to producing output. It
    is not where requested products land; that is `output_dir()`.

    Args:
        path: The directory to use, or `None` to clear a previous override and
            fall back to the environment variable (then the built-in default).
            `~` is expanded and the value is made absolute. The directory is not
            created here; each backend creates its own subdirectory on first use.

    Examples:
        - Point every backend's intermediates at one directory:
            ```python
            >>> from earthlens.config import cache_dir, set_cache_dir
            >>> set_cache_dir("/data/earthlens-cache")
            >>> cache_dir().name
            'earthlens-cache'
            >>> set_cache_dir(None)

            ```
        - Backends hang their own subdirectory off it:
            ```python
            >>> from earthlens.config import cache_dir, set_cache_dir
            >>> set_cache_dir("/data/earthlens-cache")
            >>> (cache_dir() / "osm_pbf").name
            'osm_pbf'
            >>> set_cache_dir(None)

            ```

    See Also:
        cache_dir: Reads back the directory this function sets.
        set_output_dir: The equivalent for requested products.
    """
    global _cache_override
    _cache_override = None if path is None else _resolve(path)

cache_dir() #

Resolve the directory regenerable intermediates are cached in.

Resolution order: the set_cache_dir() override, then the EARTHLENS_CACHE environment variable, then the per-platform user cache directory (platformdirs.user_cache_dir), which is the correct spelling on Windows as well as Linux and macOS.

Backends append their own name, so two backends never share a cache tree.

Returns:

Type Description
Path

The resolved absolute directory. It is not created here; each backend

Path

creates its own subdirectory on first use.

Examples:

  • Read back the cache root a backend will hang its subdirectory off:
    >>> from earthlens.config import cache_dir, set_cache_dir
    >>> set_cache_dir("/data/earthlens-cache")
    >>> cache_dir().is_absolute()
    True
    >>> cache_dir().name
    'earthlens-cache'
    >>> set_cache_dir(None)
    
  • Resolving the directory never creates it on disk:
    >>> from earthlens.config import cache_dir, set_cache_dir
    >>> set_cache_dir("/data/earthlens-cache-not-created")
    >>> cache_dir().exists()
    False
    >>> set_cache_dir(None)
    
See Also

set_cache_dir: Sets the override this function reads first. output_dir: Where requested products land, as opposed to intermediates.

Source code in libs/core/src/earthlens/config.py
def cache_dir() -> Path:
    """Resolve the directory regenerable intermediates are cached in.

    Resolution order: the `set_cache_dir()` override, then the
    `EARTHLENS_CACHE` environment variable, then the per-platform user cache
    directory (`platformdirs.user_cache_dir`), which is the correct spelling on
    Windows as well as Linux and macOS.

    Backends append their own name, so two backends never share a cache tree.

    Returns:
        The resolved absolute directory. It is *not* created here; each backend
        creates its own subdirectory on first use.

    Examples:
        - Read back the cache root a backend will hang its subdirectory off:
            ```python
            >>> from earthlens.config import cache_dir, set_cache_dir
            >>> set_cache_dir("/data/earthlens-cache")
            >>> cache_dir().is_absolute()
            True
            >>> cache_dir().name
            'earthlens-cache'
            >>> set_cache_dir(None)

            ```
        - Resolving the directory never creates it on disk:
            ```python
            >>> from earthlens.config import cache_dir, set_cache_dir
            >>> set_cache_dir("/data/earthlens-cache-not-created")
            >>> cache_dir().exists()
            False
            >>> set_cache_dir(None)

            ```

    See Also:
        set_cache_dir: Sets the override this function reads first.
        output_dir: Where requested products land, as opposed to intermediates.
    """
    if _cache_override is not None:
        return _cache_override
    env = os.environ.get(CACHE_DIR_ENV)
    if env:
        return _resolve(env)
    return _resolve(platformdirs.user_cache_dir("earthlens", appauthor=False))

resolve_output_path(path) #

Resolve a backend's path= argument to an absolute output directory.

The single place the path= contract is implemented, so every backend resolves it identically.

Parameters:

Name Type Description Default
path str | PathLike[str] | None

The backend's path= argument. None means "not given" and falls back to output_dir(). Any other value is a directory; surrounding whitespace is stripped, ~ is expanded, and an empty result means the current working directory. The path is made absolute rather than resolved, so a mapped drive or a junction the caller typed is handed back as typed.

required

Returns:

Type Description
Path

The absolute output directory. It is not created here.

Examples:

  • An omitted path follows the configured output directory:
    >>> from earthlens.config import resolve_output_path, set_output_dir
    >>> set_output_dir("/data/earthlens")
    >>> resolve_output_path(None).name
    'earthlens'
    >>> set_output_dir(None)
    
  • An explicit value wins, and is made absolute:
    >>> from earthlens.config import resolve_output_path, set_output_dir
    >>> set_output_dir("/data/earthlens")
    >>> resolve_output_path("/tmp/here").is_absolute()
    True
    >>> resolve_output_path("/tmp/here").name
    'here'
    >>> set_output_dir(None)
    
See Also

output_dir: The fallback used when path is None.

Source code in libs/core/src/earthlens/config.py
def resolve_output_path(path: str | os.PathLike[str] | None) -> Path:
    """Resolve a backend's `path=` argument to an absolute output directory.

    The single place the `path=` contract is implemented, so every backend
    resolves it identically.

    Args:
        path: The backend's `path=` argument. `None` means "not given" and
            falls back to `output_dir()`. Any other value is a directory;
            surrounding whitespace is stripped, `~` is expanded, and an empty
            result means the current working directory. The path is made
            absolute rather than resolved, so a mapped drive or a junction the
            caller typed is handed back as typed.

    Returns:
        The absolute output directory. It is not created here.

    Examples:
        - An omitted path follows the configured output directory:
            ```python
            >>> from earthlens.config import resolve_output_path, set_output_dir
            >>> set_output_dir("/data/earthlens")
            >>> resolve_output_path(None).name
            'earthlens'
            >>> set_output_dir(None)

            ```
        - An explicit value wins, and is made absolute:
            ```python
            >>> from earthlens.config import resolve_output_path, set_output_dir
            >>> set_output_dir("/data/earthlens")
            >>> resolve_output_path("/tmp/here").is_absolute()
            True
            >>> resolve_output_path("/tmp/here").name
            'here'
            >>> set_output_dir(None)

            ```

    See Also:
        output_dir: The fallback used when `path` is `None`.
    """
    if path is None:
        return output_dir()
    return Path(str(path).strip() or ".").expanduser().absolute()