nexrad-process 1.0.0-rc.1

Processing algorithms for NEXRAD weather radar data.
Documentation
//! Processing algorithms for NEXRAD weather radar data.
//!
//! This crate provides processing traits and algorithms that operate on the field types
//! defined in [`nexrad_model`]. The core abstraction is the [`SweepProcessor`] trait,
//! which transforms one [`SweepField`] into another. Processors can be composed into
//! pipelines using [`SweepPipeline`].
//!
//! # Architecture
//!
//! Three processing traits cover different scopes:
//!
//! - [`SweepProcessor`] — single-sweep algorithms (filtering, smoothing)
//! - [`ScanProcessor`] — multi-elevation algorithms (velocity dealiasing)
//! - [`ScanDerivedProduct`] — produces a [`CartesianField`] from a full scan
//!   (composite reflectivity, VIL)
//!
//! # Example
//!
//! ```ignore
//! use nexrad_process::{SweepPipeline, filter::ThresholdFilter};
//! use nexrad_model::data::{SweepField, Product};
//!
//! let field = SweepField::from_radials(sweep.radials(), Product::Reflectivity).unwrap();
//! let filtered = SweepPipeline::new()
//!     .then(ThresholdFilter { min: Some(5.0), max: None })
//!     .execute(&field)?;
//! ```

#![forbid(unsafe_code)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![warn(clippy::correctness)]
#![deny(missing_docs)]

/// Derived products computed from radar scans.
pub mod derived;
/// Storm cell detection algorithms.
pub mod detection;
/// Filtering algorithms for sweep field data.
pub mod filter;
/// Composable processing pipelines.
pub mod pipeline;
/// Result and error types for processing operations.
pub mod result;

pub use pipeline::SweepPipeline;
pub use result::{Error, Result};

use nexrad_model::data::{CartesianField, Scan, SweepField};
use nexrad_model::geo::{GeoExtent, RadarCoordinateSystem};

/// Transforms one [`SweepField`] into another.
///
/// This is the primary processing trait for single-sweep algorithms such as
/// filtering, smoothing, and clutter removal.
pub trait SweepProcessor {
    /// A human-readable name for this processor.
    fn name(&self) -> &str;

    /// Process the input field, producing a new field with the same geometry.
    fn process(&self, input: &SweepField) -> Result<SweepField>;
}

/// Processes fields with full scan context (multiple elevations).
///
/// This trait is for algorithms that need to consider data across elevations,
/// such as velocity dealiasing.
///
/// No built-in implementations are provided. This trait is an extension point
/// for downstream crates to implement scan-level processing algorithms.
pub trait ScanProcessor {
    /// A human-readable name for this processor.
    fn name(&self) -> &str;

    /// Process sweep fields using the full scan context.
    ///
    /// Takes the scan metadata and all sweep fields for the relevant product,
    /// returning a new set of processed fields (one per input field).
    fn process_scan(&self, scan: &Scan, fields: &[SweepField]) -> Result<Vec<SweepField>>;
}

/// Produces a [`CartesianField`] from a full scan.
///
/// This trait is for derived products that combine data from multiple elevations
/// into a single geographic surface, such as composite reflectivity, echo tops,
/// and vertically integrated liquid (VIL).
pub trait ScanDerivedProduct {
    /// A human-readable name for this product.
    fn name(&self) -> &str;

    /// Compute the derived product from the scan.
    ///
    /// # Parameters
    ///
    /// - `scan` — Scan metadata (site info, VCP, etc.)
    /// - `fields` — Sweep fields for the relevant product, one per elevation
    /// - `coord_system` — Radar coordinate system for geographic projection
    /// - `output_extent` — Geographic extent of the output grid
    /// - `output_resolution` — (width, height) of the output grid in cells
    fn compute(
        &self,
        scan: &Scan,
        fields: &[SweepField],
        coord_system: &RadarCoordinateSystem,
        output_extent: &GeoExtent,
        output_resolution: (usize, usize),
    ) -> Result<CartesianField>;
}