sciforge 0.0.3

A comprehensive scientific computing library in pure Rust with zero dependencies
Documentation
pub fn defibrillation_energy(capacitance: f64, voltage: f64) -> f64 {
    0.5 * capacitance * voltage * voltage
}

pub fn electrode_impedance(resistance: f64, capacitance: f64, frequency: f64) -> f64 {
    let xc = 1.0 / (2.0 * std::f64::consts::PI * frequency * capacitance);
    (resistance * resistance + xc * xc).sqrt()
}

pub fn stimulation_strength_duration(rheobase: f64, chronaxie: f64, pulse_width: f64) -> f64 {
    rheobase * (1.0 + chronaxie / pulse_width)
}

pub fn bioimpedance_cole_model(
    r_inf: f64,
    r_0: f64,
    tau: f64,
    alpha: f64,
    frequency: f64,
) -> (f64, f64) {
    let omega = 2.0 * std::f64::consts::PI * frequency;
    let wt = omega * tau;
    let cos_a = (alpha * std::f64::consts::PI / 2.0).cos();
    let sin_a = (alpha * std::f64::consts::PI / 2.0).sin();
    let denom = 1.0 + 2.0 * wt.powf(alpha) * cos_a + wt.powf(2.0 * alpha);
    let delta_r = r_0 - r_inf;
    let real = r_inf + delta_r * (1.0 + wt.powf(alpha) * cos_a) / denom;
    let imag = -delta_r * wt.powf(alpha) * sin_a / denom;
    (real, imag)
}

pub fn transcranial_current_density(current: f64, electrode_area: f64) -> f64 {
    current / electrode_area
}

pub fn neural_recruitment_curve(
    stimulus: f64,
    threshold: f64,
    saturation: f64,
    steepness: f64,
) -> f64 {
    1.0 / (1.0 + (-(stimulus - threshold) / steepness).exp()) * saturation
}

pub fn charge_density(charge: f64, electrode_area: f64) -> f64 {
    charge / electrode_area
}

pub fn cathodic_charge_balanced(
    anodic_amplitude: f64,
    anodic_duration: f64,
    cathodic_duration: f64,
) -> f64 {
    anodic_amplitude * anodic_duration / cathodic_duration
}

pub fn pulse_train_energy(
    amplitude: f64,
    pulse_width: f64,
    frequency: f64,
    duration: f64,
    impedance: f64,
) -> f64 {
    let n_pulses = frequency * duration;
    n_pulses * amplitude * amplitude * pulse_width / impedance
}

pub fn tissue_heating(
    current_density: f64,
    conductivity: f64,
    duration: f64,
    specific_heat: f64,
    density: f64,
) -> f64 {
    current_density * current_density * duration / (conductivity * specific_heat * density)
}

pub fn tms_induced_efield(di_dt: f64, coil_inductance: f64, distance: f64) -> f64 {
    coil_inductance * di_dt / (2.0 * std::f64::consts::PI * distance)
}

pub fn dbs_volume_tissue_activated(current: f64, impedance: f64, threshold_efield: f64) -> f64 {
    let voltage = current * impedance;
    let radius = (voltage / threshold_efield).sqrt();
    (4.0 / 3.0) * std::f64::consts::PI * radius.powi(3)
}

pub fn cochlear_implant_spread(current: f64, distance: f64, sigma: f64) -> f64 {
    current / (4.0 * std::f64::consts::PI * sigma * distance)
}

pub fn fes_fatigue_index(initial_force: f64, final_force: f64) -> f64 {
    (initial_force - final_force) / initial_force
}

pub fn shannon_safety_limit(charge_per_phase_uc: f64, electrode_area_cm2: f64) -> f64 {
    (charge_per_phase_uc / electrode_area_cm2).log10()
}

pub fn biphasic_pulse_charge(amplitude: f64, phase_duration: f64) -> f64 {
    amplitude * phase_duration
}

pub fn interphase_gap_effect(threshold_no_gap: f64, gap_duration: f64, time_constant: f64) -> f64 {
    threshold_no_gap / (1.0 - (-gap_duration / time_constant).exp())
}

pub fn electrochemical_safety_margin(water_window: f64, electrode_potential: f64) -> f64 {
    water_window - electrode_potential.abs()
}

pub fn warburg_impedance(sigma: f64, frequency: f64) -> (f64, f64) {
    let omega = 2.0 * std::f64::consts::PI * frequency;
    let w = sigma / omega.sqrt();
    (w, -w)
}

pub fn constant_phase_element(q: f64, alpha: f64, frequency: f64) -> (f64, f64) {
    let omega = 2.0 * std::f64::consts::PI * frequency;
    let mag = 1.0 / (q * omega.powf(alpha));
    let phase = -alpha * std::f64::consts::PI / 2.0;
    (mag * phase.cos(), mag * phase.sin())
}

pub fn chronaxie_from_strength_duration(
    rheobase: f64,
    threshold_at_pw: f64,
    pulse_width: f64,
) -> f64 {
    pulse_width * (threshold_at_pw / rheobase - 1.0).recip()
}

pub fn galvanic_skin_response(
    baseline_conductance: f64,
    peak_conductance: f64,
    t: f64,
    tau_rise: f64,
    tau_decay: f64,
) -> f64 {
    let delta = peak_conductance - baseline_conductance;
    if t < 0.0 {
        return baseline_conductance;
    }
    baseline_conductance + delta * (1.0 - (-t / tau_rise).exp()) * (-t / tau_decay).exp()
}

pub fn total_charge_delivered(
    amplitude: f64,
    pulse_width: f64,
    frequency: f64,
    duration: f64,
) -> f64 {
    amplitude * pulse_width * frequency * duration
}

pub fn electrode_polarization_voltage(charge: f64, capacitance: f64) -> f64 {
    charge / capacitance
}

pub fn anodal_break_excitation_threshold(
    membrane_tau: f64,
    pulse_duration: f64,
    rheobase: f64,
) -> f64 {
    rheobase * (1.0 + membrane_tau / pulse_duration)
}