0
# Utilities and Configuration
1
2
Core utilities for units handling, calendar operations, missing data management, and global configuration. These utilities provide the foundation for XClim's robust climate data processing capabilities.
3
4
## Capabilities
5
6
### Units Operations
7
8
Unit handling and conversion utilities for climate data processing with automatic CF-compliant unit management.
9
10
```python { .api }
11
def convert_units_to(da, target, context="none"):
12
"""
13
Convert data array to target units.
14
15
Parameters:
16
- da: xr.DataArray, input data with units attribute
17
- target: str, target unit specification (e.g., "degC", "mm/day")
18
- context: str, unit conversion context (default "none")
19
20
Returns:
21
xr.DataArray: Data converted to target units
22
"""
23
24
def check_units(da, expected):
25
"""
26
Check if data array has expected units.
27
28
Parameters:
29
- da: xr.DataArray, input data to check
30
- expected: str or list, expected unit(s)
31
32
Raises:
33
ValidationError: If units don't match expected
34
"""
35
36
def ensure_cf_units(da):
37
"""
38
Ensure data array has CF-compliant units.
39
40
Parameters:
41
- da: xr.DataArray, input data
42
43
Returns:
44
xr.DataArray: Data with CF-compliant units
45
"""
46
47
def infer_sampling_units(freq):
48
"""
49
Infer temporal sampling units from frequency string.
50
51
Parameters:
52
- freq: str, frequency string (e.g., "D", "MS", "YS")
53
54
Returns:
55
str: Inferred temporal units
56
"""
57
58
def str2pint(unit_str):
59
"""
60
Parse unit string to pint Quantity.
61
62
Parameters:
63
- unit_str: str, unit specification
64
65
Returns:
66
pint.Quantity: Parsed unit quantity
67
"""
68
69
def units2pint(units):
70
"""
71
Convert various unit specifications to pint units.
72
73
Parameters:
74
- units: str, pint.Unit, or pint.Quantity, unit specification
75
76
Returns:
77
pint.Unit: Standardized pint unit
78
"""
79
```
80
81
### Calendar Operations
82
83
Calendar handling and conversion utilities for different calendar systems used in climate models.
84
85
```python { .api }
86
def convert_calendar(da, target_calendar, align_on="date", **kwargs):
87
"""
88
Convert data array to different calendar system.
89
90
Parameters:
91
- da: xr.DataArray, input data with time coordinate
92
- target_calendar: str, target calendar ("standard", "noleap", "360_day", etc.)
93
- align_on: str, alignment method ("date", "year", "random")
94
- **kwargs: additional conversion parameters
95
96
Returns:
97
xr.DataArray: Data converted to target calendar
98
"""
99
100
def get_calendar(da):
101
"""
102
Get calendar type from data array time coordinate.
103
104
Parameters:
105
- da: xr.DataArray, input data with time coordinate
106
107
Returns:
108
str: Calendar type ("standard", "noleap", "360_day", etc.)
109
"""
110
111
def common_calendar(calendars):
112
"""
113
Find common calendar from list of calendar types.
114
115
Parameters:
116
- calendars: list, calendar type strings
117
118
Returns:
119
str: Common calendar type
120
"""
121
122
def datetime_to_decimal_year(dt):
123
"""
124
Convert datetime to decimal year representation.
125
126
Parameters:
127
- dt: datetime-like, input datetime
128
129
Returns:
130
float: Decimal year value
131
"""
132
133
def days_in_year(year, calendar="standard"):
134
"""
135
Get number of days in year for specified calendar.
136
137
Parameters:
138
- year: int, year value
139
- calendar: str, calendar type (default "standard")
140
141
Returns:
142
int: Number of days in year
143
"""
144
145
def max_doy(calendar="standard"):
146
"""
147
Maximum day of year for calendar type.
148
149
Parameters:
150
- calendar: str, calendar type (default "standard")
151
152
Returns:
153
int: Maximum day of year (365, 366, or 360)
154
"""
155
156
def percentile_doy(percentiles, calendar="standard"):
157
"""
158
Day of year percentiles for calendar type.
159
160
Parameters:
161
- percentiles: list, percentile values (0-100)
162
- calendar: str, calendar type
163
164
Returns:
165
list: Day of year values for percentiles
166
"""
167
168
def resample_doy(da, doy, **kwargs):
169
"""
170
Resample data by day of year.
171
172
Parameters:
173
- da: xr.DataArray, input data with time coordinate
174
- doy: int or list, day(s) of year to select
175
- **kwargs: additional resampling parameters
176
177
Returns:
178
xr.DataArray: Resampled data for specified days of year
179
"""
180
181
def within_bnds_doy(doy, bnds, calendar="standard"):
182
"""
183
Check if day of year is within bounds.
184
185
Parameters:
186
- doy: int, day of year to check
187
- bnds: tuple, (start, end) day of year bounds
188
- calendar: str, calendar type
189
190
Returns:
191
bool: True if day of year is within bounds
192
"""
193
```
194
195
### Missing Data Management
196
197
Missing data validation and handling for robust climate analysis.
198
199
```python { .api }
200
class MissingBase:
201
"""
202
Base class for missing data validators.
203
204
Provides interface for custom missing data validation logic.
205
"""
206
207
def is_missing(self, data, freq):
208
"""
209
Determine if data has missing values based on criteria.
210
211
Parameters:
212
- data: xr.DataArray, input data to validate
213
- freq: str, resampling frequency
214
215
Returns:
216
xr.DataArray: Boolean array indicating missing periods
217
"""
218
219
class AtLeastNValid(MissingBase):
220
"""
221
Validator requiring at least N valid values.
222
223
Parameters:
224
- n: int, minimum number of valid values required
225
"""
226
227
def __init__(self, n):
228
self.n = n
229
230
class AnyMissing(MissingBase):
231
"""
232
Validator that flags any missing data as invalid.
233
234
Strictest validation - requires complete data.
235
"""
236
237
class AllMissing(MissingBase):
238
"""
239
Validator that only flags periods with all missing data.
240
241
Most permissive validation.
242
"""
243
244
class FromContext(MissingBase):
245
"""
246
Validator that uses context-dependent missing data rules.
247
248
Parameters:
249
- context: str, validation context name
250
"""
251
252
def __init__(self, context):
253
self.context = context
254
255
class Percentage(MissingBase):
256
"""
257
Validator requiring minimum percentage of valid data.
258
259
Parameters:
260
- pct: float, minimum percentage of valid data (0-100)
261
"""
262
263
def __init__(self, pct):
264
self.pct = pct
265
266
class SkipMissing(MissingBase):
267
"""
268
Validator that skips missing data validation entirely.
269
270
Allows computation to proceed regardless of missing data.
271
"""
272
```
273
274
### Global Configuration
275
276
Global options and settings management for XClim behavior customization.
277
278
```python { .api }
279
def set_options(**kwargs):
280
"""
281
Set global XClim options.
282
283
Available options:
284
- metadata_locales: list, locales for metadata translation
285
- cf_compliance: str, CF compliance level ("strict", "warn", "log")
286
- data_validation: str, data validation level ("strict", "warn", "log")
287
- missing_options: dict, missing data handling options
288
- check_missing: str, missing data checking ("any", "wmo", "percent", "skip")
289
290
Parameters:
291
- **kwargs: option names and values to set
292
293
Examples:
294
set_options(cf_compliance="warn", check_missing="wmo")
295
set_options(metadata_locales=["en", "fr"])
296
"""
297
298
def get_options():
299
"""
300
Get current global XClim options.
301
302
Returns:
303
dict: Current option values
304
"""
305
306
def reset_options():
307
"""
308
Reset all options to default values.
309
"""
310
311
def register_option(name, default_value, validator=None, doc=None):
312
"""
313
Register a new global option.
314
315
Parameters:
316
- name: str, option name
317
- default_value: any, default value for option
318
- validator: callable, validation function (optional)
319
- doc: str, documentation string (optional)
320
"""
321
322
def unregister_option(name):
323
"""
324
Remove a registered option.
325
326
Parameters:
327
- name: str, option name to remove
328
"""
329
```
330
331
### Data Validation and Quality Flags
332
333
Data quality assessment and flag generation for climate data QC.
334
335
```python { .api }
336
def data_flags(data, checks=None, **kwargs):
337
"""
338
Generate data quality flags based on various checks.
339
340
Parameters:
341
- data: xr.DataArray or xr.Dataset, input climate data
342
- checks: list, quality check names to apply
343
- **kwargs: additional parameters for specific checks
344
345
Returns:
346
xr.DataArray: Data quality flag array
347
"""
348
349
def temperature_warnings(tasmin, tasmax, **kwargs):
350
"""
351
Generate warnings for temperature data quality issues.
352
353
Parameters:
354
- tasmin: xr.DataArray, minimum temperature data
355
- tasmax: xr.DataArray, maximum temperature data
356
- **kwargs: threshold parameters for warnings
357
358
Returns:
359
xr.DataArray: Temperature warning flags
360
"""
361
362
def precipitation_warnings(pr, **kwargs):
363
"""
364
Generate warnings for precipitation data quality issues.
365
366
Parameters:
367
- pr: xr.DataArray, precipitation data
368
- **kwargs: threshold parameters for warnings
369
370
Returns:
371
xr.DataArray: Precipitation warning flags
372
"""
373
374
def wind_warnings(sfcwind, **kwargs):
375
"""
376
Generate warnings for wind data quality issues.
377
378
Parameters:
379
- sfcwind: xr.DataArray, surface wind speed data
380
- **kwargs: threshold parameters for warnings
381
382
Returns:
383
xr.DataArray: Wind warning flags
384
"""
385
386
def ecad_compliant(data, **kwargs):
387
"""
388
Check ECAD (European Climate Assessment & Dataset) compliance.
389
390
Parameters:
391
- data: xr.DataArray, input climate data
392
- **kwargs: compliance checking parameters
393
394
Returns:
395
bool: True if data meets ECAD standards
396
"""
397
```
398
399
## Usage Examples
400
401
### Unit Conversion
402
403
```python
404
import xarray as xr
405
from xclim.core import units
406
407
# Load temperature data in Kelvin
408
ds = xr.tutorial.open_dataset("air_temperature")
409
tas_k = ds.air.rename("tas")
410
tas_k.attrs["units"] = "K"
411
412
# Convert to Celsius
413
tas_c = units.convert_units_to(tas_k, "degC")
414
415
# Check units
416
units.check_units(tas_c, "degC") # No error if correct
417
418
# Convert precipitation units
419
pr = ds.precip.rename("pr") if "precip" in ds else None
420
if pr is not None:
421
pr.attrs["units"] = "kg m-2 s-1"
422
pr_mm = units.convert_units_to(pr, "mm/day")
423
```
424
425
### Calendar Operations
426
427
```python
428
from xclim.core import calendar
429
430
# Check calendar type
431
cal_type = calendar.get_calendar(tas_k)
432
print(f"Calendar: {cal_type}")
433
434
# Convert to no-leap calendar
435
tas_noleap = calendar.convert_calendar(tas_k, "noleap", align_on="date")
436
437
# Work with day of year
438
max_day = calendar.max_doy("360_day") # Returns 360
439
percentiles = calendar.percentile_doy([25, 50, 75], "noleap")
440
```
441
442
### Missing Data Validation
443
444
```python
445
from xclim.core.missing import AtLeastNValid, Percentage
446
447
# Create validators
448
validator_5days = AtLeastNValid(5) # Need at least 5 valid days
449
validator_80pct = Percentage(80) # Need 80% valid data
450
451
# Use with indicators (example)
452
import xclim.atmos as xca
453
454
# Apply strict validation
455
xca.tg_mean.missing = validator_5days
456
result = xca.tg_mean(tas_c, freq="MS") # Monthly with validation
457
```
458
459
### Global Configuration
460
461
```python
462
import xclim
463
464
# Set global options
465
xclim.set_options(
466
cf_compliance="warn", # Warn about CF compliance issues
467
check_missing="wmo", # Use WMO missing data standards
468
metadata_locales=["en", "fr"] # English and French metadata
469
)
470
471
# Check current options
472
options = xclim.get_options()
473
print(options)
474
475
# Reset to defaults
476
xclim.reset_options()
477
```
478
479
### Data Quality Checking
480
481
```python
482
from xclim.core import dataflags
483
484
# Generate quality flags
485
flags = dataflags.data_flags(
486
{"tasmin": tasmin, "tasmax": tasmax},
487
checks=["temperature_coherence", "valid_range"]
488
)
489
490
# Temperature-specific warnings
491
temp_warnings = dataflags.temperature_warnings(tasmin, tasmax)
492
493
# Check for common issues
494
if temp_warnings.any():
495
print("Temperature data quality issues detected")
496
```