Skip to main content

oxigdal_temporal/
lib.rs

1//! OxiGDAL Temporal Analysis
2//!
3//! Comprehensive multi-temporal raster analysis library for geospatial time series.
4//!
5//! This crate provides advanced temporal analysis capabilities for raster data including:
6//! - Time-indexed raster collections with lazy loading
7//! - Temporal compositing (median, mean, max NDVI, quality-weighted)
8//! - Temporal interpolation and gap filling
9//! - Temporal aggregation (daily, weekly, monthly, yearly, rolling)
10//! - Change detection (BFAST, LandTrendr, differencing)
11//! - Trend analysis (Mann-Kendall, Sen's slope, linear regression)
12//! - Seasonality detection and decomposition
13//! - Anomaly detection
14//! - Time series forecasting
15//! - Breakpoint detection
16//! - Multi-dimensional data cube operations
17//!
18//! # Features
19//!
20//! - `timeseries` - Time series raster collections
21//! - `compositing` - Temporal compositing methods
22//! - `interpolation` - Temporal interpolation
23//! - `aggregation` - Temporal aggregation
24//! - `change_detection` - Change detection algorithms
25//! - `trend_analysis` - Trend analysis methods
26//! - `phenology` - Vegetation phenology
27//! - `datacube` - Data cube operations
28//! - `zarr` - Zarr storage integration
29//! - `parallel` - Parallel processing support
30//!
31//! # Examples
32//!
33//! ## Creating a Time Series
34//!
35//! ```rust,no_run
36//! use oxigdal_temporal::timeseries::{TimeSeriesRaster, TemporalMetadata};
37//! use chrono::{DateTime, NaiveDate, Utc};
38//! use scirs2_core::ndarray::Array3;
39//!
40//! let mut ts = TimeSeriesRaster::new();
41//!
42//! let dt = DateTime::from_timestamp(1640995200, 0).expect("valid timestamp");
43//! let date = NaiveDate::from_ymd_opt(2022, 1, 1).expect("valid date");
44//! let metadata = TemporalMetadata::new(dt, date);
45//! let data = Array3::zeros((100, 100, 3));
46//!
47//! ts.add_raster(metadata, data).expect("should add");
48//! ```
49//!
50//! ## Temporal Compositing
51//!
52//! ```rust,no_run
53//! use oxigdal_temporal::compositing::{TemporalCompositor, CompositingConfig, CompositingMethod};
54//! # use oxigdal_temporal::timeseries::TimeSeriesRaster;
55//! # let ts = TimeSeriesRaster::new();
56//!
57//! let config = CompositingConfig {
58//!     method: CompositingMethod::Median,
59//!     max_cloud_cover: Some(20.0),
60//!     ..Default::default()
61//! };
62//!
63//! let composite = TemporalCompositor::composite(&ts, &config)
64//!     .expect("should create composite");
65//! ```
66//!
67//! ## Trend Analysis
68//!
69//! ```rust,no_run
70//! use oxigdal_temporal::analysis::trend::{TrendAnalyzer, TrendMethod};
71//! # use oxigdal_temporal::timeseries::TimeSeriesRaster;
72//! # let ts = TimeSeriesRaster::new();
73//!
74//! let result = TrendAnalyzer::analyze(&ts, TrendMethod::MannKendall)
75//!     .expect("should analyze trend");
76//! ```
77//!
78//! ## Change Detection
79//!
80//! ```rust,no_run
81//! use oxigdal_temporal::change::{ChangeDetector, ChangeDetectionConfig, ChangeDetectionMethod};
82//! # use oxigdal_temporal::timeseries::TimeSeriesRaster;
83//! # let ts = TimeSeriesRaster::new();
84//!
85//! let config = ChangeDetectionConfig {
86//!     method: ChangeDetectionMethod::BFAST,
87//!     ..Default::default()
88//! };
89//!
90//! let changes = ChangeDetector::detect(&ts, &config)
91//!     .expect("should detect changes");
92//! ```
93
94#![cfg_attr(not(feature = "std"), no_std)]
95#![warn(missing_docs)]
96#![warn(clippy::unwrap_used)]
97#![warn(clippy::expect_used)]
98
99#[cfg(feature = "alloc")]
100extern crate alloc;
101
102pub mod error;
103
104// Core time series module
105#[cfg(feature = "timeseries")]
106pub mod timeseries;
107
108// Stack module (always available)
109pub mod stack;
110
111// Analysis modules (requires timeseries)
112#[cfg(feature = "timeseries")]
113pub mod analysis;
114
115// Change detection modules
116#[cfg(feature = "change_detection")]
117pub mod change;
118
119// Compositing modules
120#[cfg(feature = "compositing")]
121pub mod compositing;
122
123// Gap filling modules (requires timeseries)
124#[cfg(feature = "timeseries")]
125pub mod gap_filling;
126
127// Aggregation module
128#[cfg(feature = "aggregation")]
129pub mod aggregation;
130
131// Phenology module
132#[cfg(feature = "phenology")]
133pub mod phenology;
134
135// Interpolation module (legacy, use gap_filling instead)
136#[cfg(feature = "interpolation")]
137pub mod interpolation {
138    //! Legacy interpolation module - use gap_filling instead
139    pub use crate::gap_filling::*;
140}
141
142// Trend module (legacy, use analysis::trend instead)
143#[cfg(feature = "trend_analysis")]
144pub mod trend {
145    //! Legacy trend module - use analysis::trend instead
146    pub use crate::analysis::trend::*;
147}
148
149// Re-exports for convenience
150pub use error::{Result, TemporalError};
151
152#[cfg(feature = "timeseries")]
153pub use timeseries::{
154    CubeDimensions, CubeMetadata, DataCube, PixelStatistics, TemporalMetadata, TemporalRasterEntry,
155    TemporalResolution, TimeSeriesRaster, TimeSeriesStats,
156};
157
158pub use stack::{InterpolationMethod, RasterStack, StackConfig, StackMetadata};
159
160// Analysis re-exports
161#[cfg(feature = "timeseries")]
162pub use analysis::anomaly::{AnomalyDetector, AnomalyMethod, AnomalyResult};
163#[cfg(feature = "timeseries")]
164pub use analysis::forecast::{ForecastMethod, ForecastParams, ForecastResult, Forecaster};
165#[cfg(feature = "timeseries")]
166pub use analysis::seasonality::{SeasonalityAnalyzer, SeasonalityMethod, SeasonalityResult};
167#[cfg(feature = "timeseries")]
168pub use analysis::trend::{TrendAnalyzer, TrendMethod, TrendResult};
169
170#[cfg(feature = "compositing")]
171pub use compositing::{CompositeResult, CompositingConfig, CompositingMethod, TemporalCompositor};
172
173#[cfg(feature = "change_detection")]
174pub use change::{
175    BreakpointDetector, BreakpointMethod, BreakpointParams, BreakpointResult,
176    ChangeDetectionConfig, ChangeDetectionMethod, ChangeDetectionResult, ChangeDetector,
177};
178
179#[cfg(feature = "timeseries")]
180pub use gap_filling::{GapFillMethod, GapFillParams, GapFillResult, GapFiller};
181
182#[cfg(feature = "aggregation")]
183pub use aggregation::{
184    AggregationConfig, AggregationResult, AggregationStatistic, TemporalAggregator, TemporalWindow,
185};
186
187#[cfg(feature = "phenology")]
188pub use phenology::{PhenologyConfig, PhenologyExtractor, PhenologyMethod, PhenologyMetrics};
189
190/// Library version
191pub const VERSION: &str = env!("CARGO_PKG_VERSION");
192
193/// Get library version information
194#[must_use]
195pub fn version() -> &'static str {
196    VERSION
197}
198
199#[cfg(test)]
200mod tests {
201    use super::*;
202
203    #[test]
204    fn test_version() {
205        let v = version();
206        assert!(!v.is_empty());
207        assert!(v.contains('.'));
208    }
209
210    #[test]
211    fn test_error_types() {
212        let err = TemporalError::invalid_input("test");
213        assert!(format!("{}", err).contains("test"));
214    }
215}