eorst 1.0.1

Earth Observation and Remote Sensing Toolkit - library for raster processing pipelines
//! RasterDataset module for handling raster data.

/// Builder for constructing RasterDataset instances.
pub mod builder;
/// Implementation methods for RasterDataset.
pub mod impl_methods;
/// Processing methods (apply, reduce, mosaic).
pub mod processing;
/// Rasterization methods.
pub mod rasterization;
/// Sampling and extraction methods.
pub mod sampling;
/// ML methods (feature-gated).
#[cfg(feature = "use_lgbm")]
pub mod ml;
/// Zonal statistics methods (feature-gated).
#[cfg(feature = "use_polars")]
pub mod zonal_stats;
/// I/O methods (read_block, write_window3).
pub mod io;
/// Composition methods (stack, extend).
pub mod composition;

use crate::core_types::RasterType;
use crate::metadata::RasterMetadata;
use crate::blocks::RasterBlock;
use std::path::PathBuf;

// Re-export RasterDatasetBuilder from builder module
pub use builder::RasterDatasetBuilder;

/// Main data structure of eorst. Stores the raster dataset [metadata](crate::RasterMetadata) and [blocks](crate::RasterBlock).
///
/// The easiest way to create a RasterDataset is by using [`RasterDatasetBuilder`]:
///
/// ```rust,ignore
/// use std::path::PathBuf;
/// use eorst::{types::BlockSize, RasterDatasetBuilder, DataSourceBuilder, RasterDataset};
///
/// let data_source = DataSourceBuilder::from_file(&PathBuf::from("scene.tif")).build();
/// let rds: RasterDataset<u16> = RasterDatasetBuilder::from_source(&data_source)
///     .block_size(BlockSize { cols: 2048, rows: 2048 })
///     .build();
/// ```
///
/// ## Processing with [`apply`](RasterDataset::apply)
///
/// [`apply`](RasterDataset::apply) is the main entry point. Pass a worker function
/// that receives a [`RasterDataBlock`] — the block data, metadata, and no-data value.
/// The worker returns an `Array4` which is written directly to the output GeoTIFF:
///
/// ```rust,ignore
/// use eorst::{RasterDataBlock, RasterDataset};
/// use anyhow::Result;
/// use ndarray::Array4;
///
/// fn worker(block: &RasterDataBlock<u16>) -> Result<Array4<i16>> {
///     let red = block.select_layers(&["red"])?;
///     let nir = block.select_layers(&["nir"])?;
///     let ndvi = ((&nir.data - &red.data) / (&nir.data + &red.data + 1e-10)) * 10000i16;
///     Ok(ndvi.cast::<i16>()?)
/// }
///
/// rds.apply::<i16>(worker, 8, &PathBuf::from("output.tif"))?;
/// ```
///
/// The [`Select`](crate::selection::Select) trait on `RasterDataBlock` lets you select
/// layers and time slices by name without tracking indices manually.
///
/// ## Alternative: Manual Block Iteration
///
/// You can also iterate over blocks manually:
///
/// ```rust,ignore
/// for iter in rds.iter() {
///     let block_id = iter.iter_index;
///     let block_data = rds.read_block::<i32>(block_id);
///     // ... process block_data directly
/// }
/// ```

#[derive(Debug, Clone, PartialEq)]
pub struct RasterDataset<T>
where
    T: RasterType,
{
    /// Metadata of a RasterDataset
    pub metadata: RasterMetadata<T>,
    /// Blocks of a RasterDataset
    pub blocks: Vec<RasterBlock<T>>,
    /// Temporaty layers, removed when the RasterDataset is Dropped.
    pub(crate) tmp_layers: Vec<PathBuf>,
}