File: _core.py

package info (click to toggle)
python-rioxarray 0.22.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 7,572 kB
  • sloc: python: 8,937; makefile: 85
file content (176 lines) | stat: -rw-r--r-- 5,379 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
"""
Core convention methods for rioxarray.
"""

from typing import Optional, Union

import rasterio.crs
import xarray
from affine import Affine

from rioxarray._convention._base import ConventionProtocol
from rioxarray._convention.cf import CFConvention
from rioxarray._convention.zarr import ZarrConvention
from rioxarray._options import CONVENTION, get_option
from rioxarray.crs import crs_from_user_input
from rioxarray.enum import Convention

# Convention classes mapped by Convention enum
_CONVENTION_MODULES: dict[Convention, ConventionProtocol] = {
    Convention.CF: CFConvention,  # type: ignore[dict-item]
    Convention.ZARR: ZarrConvention,  # type: ignore[dict-item]
}


def _get_convention(convention: Convention | None) -> ConventionProtocol:
    """
    Get the convention module for writing.

    Parameters
    ----------
    convention : Convention enum value or None
        The convention to use. If None, uses the global default.

    Returns
    -------
    ConventionProtocol
        The module implementing the convention
    """
    if convention is None:
        convention = get_option(CONVENTION) or Convention.CF
    convention = Convention(convention)
    return _CONVENTION_MODULES[convention]


def read_crs_auto(
    obj: Union[xarray.Dataset, xarray.DataArray],
    **kwargs,
) -> Optional[rasterio.crs.CRS]:
    """
    Auto-detect and read CRS by trying convention readers.

    If a convention is set globally via set_options(), that convention
    is tried first for better performance. Then other conventions are
    tried as fallback.

    Parameters
    ----------
    obj : xarray.Dataset or xarray.DataArray
        Object to read CRS from
    **kwargs
        Convention-specific parameters (e.g., grid_mapping for CF)

    Returns
    -------
    rasterio.crs.CRS or None
        CRS object, or None if not found in any convention
    """
    # Try the configured convention first (if set)
    configured_convention = get_option(CONVENTION)
    if configured_convention is not None:
        result = _CONVENTION_MODULES[configured_convention].read_crs(obj, **kwargs)
        if result is not None:
            return result

    # Try all other conventions
    for conv_enum, convention in _CONVENTION_MODULES.items():
        if conv_enum == configured_convention:
            continue  # Already tried this one
        result = convention.read_crs(obj, **kwargs)
        if result is not None:
            return result

    # Legacy fallback: look in attrs for 'crs' (not part of any convention)
    try:
        return crs_from_user_input(obj.attrs["crs"])
    except KeyError:
        pass

    return None


def read_transform_auto(
    obj: Union[xarray.Dataset, xarray.DataArray],
    **kwargs,
) -> Optional[Affine]:
    """
    Auto-detect and read transform by trying convention readers.

    If a convention is set globally via set_options(), that convention
    is tried first for better performance. Then other conventions are
    tried as fallback.

    Parameters
    ----------
    obj : xarray.Dataset or xarray.DataArray
        Object to read transform from
    **kwargs
        Convention-specific parameters (e.g., grid_mapping for CF)

    Returns
    -------
    affine.Affine or None
        Transform object, or None if not found in any convention
    """
    # Try the configured convention first (if set)
    configured_convention = get_option(CONVENTION)
    if configured_convention is not None:
        result = _CONVENTION_MODULES[configured_convention].read_transform(
            obj, **kwargs
        )
        if result is not None:
            return result

    # Try all other conventions
    for conv_enum, convention in _CONVENTION_MODULES.items():
        if conv_enum == configured_convention:
            continue  # Already tried this one
        result = convention.read_transform(obj, **kwargs)
        if result is not None:
            return result

    # Legacy fallback: look in attrs for 'transform' (not part of any convention)
    try:
        return Affine(*obj.attrs["transform"][:6])
    except KeyError:
        pass

    return None


def read_spatial_dimensions_auto(
    obj: Union[xarray.Dataset, xarray.DataArray],
) -> Optional[tuple[str, str]]:
    """
    Auto-detect and read spatial dimensions by trying convention readers.

    If a convention is set globally via set_options(), that convention
    is tried first for better performance. Then other conventions are
    tried as fallback.

    Parameters
    ----------
    obj : xarray.Dataset or xarray.DataArray
        Object to read spatial dimensions from

    Returns
    -------
    tuple of (y_dim, x_dim) or None
        Tuple of dimension names, or None if not found in any convention
    """
    # Try the configured convention first (if set)
    configured_convention = get_option(CONVENTION)
    if configured_convention is not None:
        result = _CONVENTION_MODULES[configured_convention].read_spatial_dimensions(obj)
        if result is not None:
            return result

    # Try all other conventions
    for conv_enum, convention in _CONVENTION_MODULES.items():
        if conv_enum == configured_convention:
            continue  # Already tried this one
        result = convention.read_spatial_dimensions(obj)
        if result is not None:
            return result

    return None