dda-rs 0.1.4

Rust interface for the run_DDA_AsciiEdf binary (Cosmopolitan Libc APE) for Delay Differential Analysis
Documentation

dda-rs

Rust library for Delay Differential Analysis (DDA). Provides a type-safe interface to execute the run_DDA_AsciiEdf binary and parse its output.

The DDA binary is required. Please download the most recent version from the file server.

Crates.io Documentation

Features

  • Type-safe API: Strongly-typed request/response structures with serde support
  • Spec-generated variants: Variant metadata auto-generated from the canonical DDA spec
  • Cross-platform: Handles APE binary execution on Unix (sh wrapper) and Windows
  • Async execution: Built on Tokio for non-blocking DDA analysis
  • Binary resolution: Automatic discovery of the DDA binary via env vars and standard paths
  • Output parsing: Processes raw DDA output into Q matrices

Installation

[dependencies]
dda-rs = "0.1.4"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }

Quick Start

use dda_rs::{
    DDARunner, DDARequest, WindowParameters, DelayParameters,
    TimeRange, PreprocessingOptions, AlgorithmSelection,
    generate_select_mask, format_select_mask,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create runner with path to the DDA binary
    let runner = DDARunner::new("/path/to/run_DDA_AsciiEdf")?;

    // Generate SELECT mask for ST and SY variants
    let mask = generate_select_mask(&["ST", "SY"]);
    let mask_str = format_select_mask(&mask); // "1 0 0 0 0 1"

    // Build analysis request
    let request = DDARequest {
        file_path: "/path/to/data.edf".to_string(),
        channels: Some(vec![0, 1, 2]),  // 0-based channel indices
        time_range: TimeRange { start: 0.0, end: 100.0 },
        preprocessing_options: PreprocessingOptions {
            highpass: None,
            lowpass: None,
        },
        algorithm_selection: AlgorithmSelection {
            enabled_variants: vec!["ST".to_string(), "SY".to_string()],
            select_mask: Some(mask_str),
        },
        window_parameters: WindowParameters {
            window_length: 1024,
            window_step: 512,
            ct_window_length: None,  // Required for CT/CD/DE variants
            ct_window_step: None,
        },
        delay_parameters: DelayParameters {
            delays: vec![7, 10],  // Tau values passed to -TAU
        },
        ct_channel_pairs: None,   // For CT variant
        cd_channel_pairs: None,   // For CD variant
        model_parameters: None,   // Expert mode: dm, order, nr_tau
        variant_configs: None,
        sampling_rate: None,      // Set if > 1000 Hz
    };

    // Run analysis with sample bounds
    let result = runner.run(
        &request,
        Some(0),      // start_bound (sample index)
        Some(10000),  // end_bound (sample index)
        None,         // edf_channel_names for labeling
    ).await?;

    println!("Analysis ID: {}", result.id);
    println!("Q matrix: {} channels × {} timepoints",
        result.q_matrix.len(),
        result.q_matrix.first().map(|r| r.len()).unwrap_or(0)
    );

    // Access individual variant results
    if let Some(variants) = &result.variant_results {
        for v in variants {
            println!("{}: {} × {}",
                v.variant_name,
                v.q_matrix.len(),
                v.q_matrix.first().map(|r| r.len()).unwrap_or(0)
            );
        }
    }

    Ok(())
}

Variant Metadata

The crate includes spec-generated variant metadata for all DDA analysis types:

Variant Position Stride Channel Format Description
ST 0 4 Individual Single Timeseries - analyzes channels independently
CT 1 4 Pairs Cross-Timeseries - symmetric channel pair relationships
CD 2 2 Directed Pairs Cross-Dynamical - directed causal relationships
RESERVED 3 1 - Internal (always 0 in production)
DE 4 1 Individual Delay Embedding - ergodic behavior testing
SY 5 1 Individual Synchronization - synchronized behavior detection
use dda_rs::{ST, CT, CD, DE, SY, VariantMetadata};

// Access variant metadata
println!("ST stride: {}", ST.stride);           // 4
println!("CT requires: {:?}", CT.required_params); // ["-WL_CT", "-WS_CT"]

// Look up by abbreviation
let variant = VariantMetadata::from_abbrev("ST").unwrap();
println!("{}: {}", variant.name, variant.documentation);

Binary Resolution

The DDA binary is resolved in this order:

  1. Explicit path passed to DDARunner::new()
  2. $DDA_BINARY_PATH environment variable
  3. $DDA_HOME/bin/run_DDA_AsciiEdf
  4. Default paths: ~/.local/bin, ~/bin, /usr/local/bin, /opt/dda/bin
use dda_rs::{find_binary, require_binary};

// Find binary (returns Option)
if let Some(path) = find_binary(None) {
    println!("Found binary at: {}", path.display());
}

// Require binary (returns Result)
let path = require_binary(None)?;

Modules

Module Description
variants Spec-generated variant metadata, SELECT mask utilities
types Request/response structures (DDARequest, DDAResult)
runner DDA binary execution logic
parser Output file parsing and Q matrix transformation
error Error types (DDAError) and Result alias
network_motifs Network motif analysis utilities
profiling Performance profiling helpers

Code Generation

The variants module is auto-generated from the canonical DDA specification. Do not edit it manually. To regenerate:

cd packages/dda-spec
cargo run --bin dda-codegen -- --output ..

License

MIT