8 Time, climatology, and anomalies
cube_aggregate_time() is the canonical time-only aggregator for day, ISO week, calendar month, meteorological season, and calendar year. It preserves Date or UTC POSIXct class, inserts internal empty periods, and uses equal observation weights. Observation coverage is available with diagnostics = TRUE; it is not duration coverage. Irregular or gapped sampling therefore requires scientific interpretation.
to_month() is the compatibility wrapper. Its supported built-in reducers use the selective core, while a deprecated arbitrary fun may still materialise the complete cube. The wrapper preserves its historical POSIXct-to-Date output; call cube_aggregate_time() when POSIXct must remain POSIXct.
cube_climatology() is the canonical recurrent climatology core for day, month, and DJF/MAM/JJA/SON season cycles. It first averages finite observations within each day-year, month-year, or season-year and then gives every valid replicate one equal climatological weight. This differs from pooling all raw observations across years. The mean is stored in data; aligned sample SD is always available in climatology$sd.
Climatology outputs contain complete 365/366-day, 12-month, or four-season pseudo-time cycles while requested and effective reference periods remain separate metadata. Date inputs retain Date; POSIXct inputs retain UTC POSIXct. diagnostics = TRUE adds replicate counts and coverage, where min_n counts valid period-year replicates. For daily climatology, drop omits February 29, keep preserves it, and corrected feb28 handling merges February 28 and 29 inside each leap year before the year enters the climatology. Lazy NetCDF input is processed by bounded period/block reads without a full chronological intermediate.
clim_month() and clim_day() remain compatibility wrappers. Their 0.2.0 results use the same two-stage science; in particular, they no longer pool raw observations and clim_day() no longer double-weights leap years under leap = "feb28".
cube_anomaly(x, climatology, type) is the canonical anomaly engine. It uses the climatology’s recurrent group key, never pseudo-time proximity, and requires exact coordinates, variables, units, calendar, and source time class. type = "difference" preserves source units; type = "z" returns unit "1". Non-finite inputs or climatological means produce missing output. For z anomalies, zero or non-finite SD also produces missing output, every positive finite SD remains valid, and negative finite SD is rejected as an invalid climatology. The source shape and timestamps are preserved, and lazy NetCDF sources are read in bounded blocks before the result is materialised in memory.
anom_diff() and anom_z() are compatibility wrappers over this engine for modern clim_day()/clim_month() results. Incomplete historical climatology objects must be recomputed. signal_noise() is the legacy standardized climatological anomaly-magnitude helper: it returns abs(z) by default and canonical z when signed = TRUE. Its numerator is the deviation from the climatological mean and its denominator is the two-stage sample SD described above; despite the historical name it is not a general signal-to-noise ratio. It accepts daily/monthly ocean_clim objects only; use cube_anomaly() directly for canonical or seasonal climatologies. annual_index() remains a specialised post-core annual table, not a yearly cube wrapper. layer_mean() provides vertical summaries.
cube_trend() computes a descriptive OLS slope independently for every longitude, latitude, depth, and variable cell against actual elapsed historical time. Date uses civil-day differences and POSIXct retains UTC subdaily precision; a year is exactly 365.2425 days. Irregular spacing is accepted with one equal weight per finite stored observation, so aggregate first with cube_aggregate_time() when equal-period weighting is intended. The output is an in-memory cube whose time axis is the representational midpoint of the selected timestamp range and whose units are source-unit per selected time unit. Recurrent climatology pseudo-time is rejected. Optional diagnostics add finite count, cell time span, fitted value at the anchor, R2, and residual SD; the core provides no Sen slope, Mann–Kendall test, inference, change metric, or breakpoint. Lazy NetCDF sources are processed in bounded blocks in one pass.
Always inspect time coverage, missingness, sample counts, and units before interpreting climatology products.