SonataSmooth.Tune 3.1.5

dotnet add package SonataSmooth.Tune --version 3.1.5
                    
NuGet\Install-Package SonataSmooth.Tune -Version 3.1.5
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SonataSmooth.Tune" Version="3.1.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SonataSmooth.Tune" Version="3.1.5" />
                    
Directory.Packages.props
<PackageReference Include="SonataSmooth.Tune" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SonataSmooth.Tune --version 3.1.5
                    
#r "nuget: SonataSmooth.Tune, 3.1.5"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SonataSmooth.Tune@3.1.5
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SonataSmooth.Tune&version=3.1.5
                    
Install as a Cake Addin
#tool nuget:?package=SonataSmooth.Tune&version=3.1.5
                    
Install as a Cake Tool

SonataSmooth.Tune

High‑performance 1D numeric signal smoothing & export toolkit for .NET (C#).
Implements Rectangular (Moving Average), Binomial (Pascal) Average, Weighted Median (Binomial weights), Gaussian, and Savitzky-Golay smoothing with configurable boundary handling and optional parallelization. Includes CSV and Excel (COM) export helpers that materialize multiple smoothing "voices" side‑by‑side for inspection or charting.

Target : .NET Standard 2.0 (core algorithms & CSV export)
Optional Excel COM automation sections use conditional compilation (#if NET48) or late binding (dynamic COM) when available.


Contents

  • Features
  • Installation
  • Quick Start
  • Concepts & Design Notes
  • Boundary Handling
  • Implemented Filters
  • Performance Characteristics
  • CSV Header Ordering Note
  • API Reference
    • Enum: BoundaryMode
    • Core static class: SmoothingConductor
      • ApplySmoothing
      • GetValueWithBoundary
      • CalcBinomialCoefficients
      • ComputeGaussianCoefficients
      • ComputeSavitzkyGolayCoefficients
      • ValidateSmoothingParameters
      • Validation helper : ScoreConformanceChecker
      • CSV / Excel export helpers (ExportCsvAsync, ExportCsvAsyncFromResults, ExportExcelAsync)
    • Additional CSV tuning parameters :
      • progressCheckInterval (int, default 1): Throttles how often progress is recomputed / reported (every N rows).
      • customFlushLineThreshold (int?): Overrides the adaptive buffered write flush batch size; null keeps adaptive logic.
    • Data containers: SmoothingScore, SmoothingNotation
    • CSV export types: CsvScoreRequest, CsvExportResult, CsvScoreWriter
    • Excel export types: ExcelScoreRequest, ExcelScoreWriter, ExcelInteropNotAvailableException
  • Error & Exception Reference
  • Usage Examples
  • Best Practices
  • Thread Safety
  • Limitations & Known Inconsistencies
  • License (MIT)

Features

  • Compute up to five smoothing variants in a single pass over the source data.
  • Window-based convolution / order polynomial fitting (Savitzky-Golay) with user-specified radius.
  • Weighted median using binomial coefficients for robust noise suppression.
  • Automatic parallel execution threshold (n ≥ 2000) for CPU-bound steps.
  • Culture-invariant numeric formatting for export.
  • Large dataset CSV partitioning honoring Excel row limit (1,048,576).
  • Efficient buffered CSV writer with adaptive flush strategy.
  • Excel export :
    • Full multi-series line chart generation.
    • Multi-column continuation for > 1,048,573 rows (per-column fill strategy).
    • Document properties + playful meta "phrases" (retained).
    • Late binding fallback when strong interop PIAs not available (non-NET48).
    • Boundary labels in Excel : high-level ExcelScoreWriter uses abbreviated labels ("Symmetric", "Replicate", "ZeroPad"); the core SmoothingConductor Excel export uses extended forms ("Symmetric (Mirror)", etc.)
    • Worksheet header note : SmoothingConductor.ExportExcelAsync writes "Subject" and "Comments" rows into the worksheet; ExcelScoreWriter.ExportAsync stores these only as document properties (not repeated as sheet rows).
  • Configurable boundary modes: Symmetric (mirror), Replicate (clamp), ZeroPad (explicit zeros), Adaptive (full in‑range sliding window; asymmetric near edges; no synthetic samples).

Installation

NuGet (preferred) : dotnet add package SonataSmooth.Tune
Package Manager : Install-Package SonataSmooth.Tune


Quick Start

using SonataSmooth.Tune;

double[] data = { 1, 2, 3, 10, 9, 5, 4, 3, 2 };

int radius = 2;           // Smoothing window size calculated from radius: (2 * radius) + 1 = 5
int polyOrder = 2;        // Degree of the polynomial used in Savitzky-Golay smoothing

var (rect, binomAvg, median, gauss, sg) = SmoothingConductor.ApplySmoothing(
    data,
    r: radius,
    polyOrder: polyOrder,
    boundaryMode: BoundaryMode.Symmetric,
    doRect: true,
    doAvg: true,
    doMed: true,
    doGauss: true,
    doSG: true
);
// (Optional) Validate parameters first using the tuple helper
using SonataSmooth.Tune.Export;

var (ok, validationError) = ScoreConformanceChecker.Validate(
    dataCount: data.Length,
    r: radius,
    polyOrder: polyOrder,
    useSG: true   // set to false if you disable SG
);

if (!ok)
{
    Console.WriteLine(validationError);
    return; // Abort before running smoothing/export
}

CSV export (computed internally) :

using SonataSmooth.Tune.Export;

var req = new CsvScoreRequest
{
    Title = "Demo Dataset",
    BaseFilePath = @"C:\Temp\demo.csv",
    InitialData = data,
    Radius = radius,
    PolyOrder = polyOrder,
    BoundaryMode = BoundaryMode.Symmetric,
    Flags = new SmoothingNotation
    {
        Rectangular = true,
        BinomialAverage = true,
        BinomialMedian = true,
        Gaussian = true,
        SavitzkyGolay = true
    }
};

var result = await CsvScoreWriter.ExportAsync(req);

Note : When using CsvScoreWriter.ExportAsync the "Boundary Method" header uses abbreviated labels ("Symmetric", "Replicate", "ZeroPad"). The lower-level SmoothingConductor.ExportCsvAsync / ExportCsvAsyncFromResults use extended labels ("Symmetric (Mirror)", "Replicate (Nearest)", "Zero Padding").


CSV Header Ordering Note

High-level CSV export (CsvScoreWriter.ExportAsync) writes header metadata in this order:

  1. Kernel Radius
  2. Kernel Width
  3. Boundary Method
  4. Polynomial Order (only when Savitzky–Golay enabled)
  5. Derivative Order (only when Savitzky–Golay enabled and DerivOrder > 0)

Lower-level conductor exports (SmoothingConductor.ExportCsvAsync / ExportCsvAsyncFromResults) place polynomial (and derivative, if present) lines before the boundary method line:

  1. Kernel Radius
  2. Kernel Width
  3. Polynomial Order (if SG)
  4. Derivative Order (if SG & d > 0)
  5. Boundary Method

This divergence is intentional for legacy compatibility. If you parse headers automatically, normalize by key name rather than relying on positional order.


Savitzky–Golay Derivative Order (d)

This library supports Savitzky–Golay derivative filters in addition to 0th‑order smoothing.

  • Core APIs:
    • SmoothingConductor.ComputeSavitzkyGolayCoefficients(windowSize, polyOrder, derivativeOrder, delta)
    • SmoothingConductor.ApplySGDerivative(input, r, polyOrder, derivativeOrder, delta, boundaryMode)
  • Request DTOs:
    • CsvScoreRequest.DerivOrder (int, default 0)
    • ExcelScoreRequest.DerivOrder (int, default 0)

Behavior:

  • d = 0 yields classic smoothing (coefficients normalized to sum = 1).
  • d ≥ 1 yields the d‑th derivative estimate at the window center; output is scaled by d! / Δ^d.
  • Exports:
    • When Flags.SavitzkyGolay is true and DerivOrder > 0, the “Savitzky–Golay Filtering” column contains the derivative series (not the smoothed series).
    • CSV/Excel headers include “Derivative Order : d”. CSV/Excel writers assume Δ = 1.0 for exported derivatives.

Constraints:

  • Radius r ≥ 0; windowSize = 2r + 1 must fit in the dataset length.
  • 0 ≤ derivativeOrder ≤ polyOrder
  • 0 ≤ polyOrder < windowSize
  • delta > 0 (only in low‑level APIs; export writers use 1.0)

Notes:

  • ScoreConformanceChecker.Validate does not take DerivOrder. Derivative constraints are validated by CsvScoreWriter/ExcelScoreWriter and by SmoothingConductor at execution time.
  • For non‑unit sample spacing (Δ ≠ 1), call SmoothingConductor.ApplySGDerivative directly with your Δ and then export via SmoothingConductor.ExportCsvAsyncFromResults.

Example: First derivative (d = 1)

var d1 = SmoothingConductor.ApplySGDerivative(
    input: samples,
    r: 4,
    polyOrder: 3,
    derivativeOrder: 1,
    delta: 1.0,
    boundaryMode: BoundaryMode.Symmetric
);

// CSV export with derivative (Δ = 1.0)
var csvReq = new SonataSmooth.Tune.Export.CsvScoreRequest
{
    Title = "Run A (d=1)",
    BaseFilePath = @"C:\out\runA_deriv.csv",
    InitialData = samples,
    Radius = 4,
    PolyOrder = 3,
    BoundaryMode = BoundaryMode.Symmetric,
    Flags = new SonataSmooth.Tune.Export.SmoothingNotation
    {
        SavitzkyGolay = true
    },
    DerivOrder = 1
};

var csvResult = await SonataSmooth.Tune.Export.CsvScoreWriter.ExportAsync(csvReq);

// Excel export with derivative (Δ = 1.0)
var xlsReq = new SonataSmooth.Tune.Export.ExcelScoreRequest
{
    DatasetTitle = "Signal 42 (d=1)",
    InitialData = samples,
    Radius = 4,
    PolyOrder = 3,
    BoundaryMode = BoundaryMode.Symmetric,
    Flags = new SonataSmooth.Tune.Export.SmoothingNotation
    {
        SavitzkyGolay = true
    },
    DerivOrder = 1
};

await SonataSmooth.Tune.Export.ExcelScoreWriter.ExportAsync(xlsReq);

Note (Adaptive + Derivatives) : Adaptive boundary handling applies equally to derivative kernels (via ApplySGDerivative) : the per-position asymmetric fit is still used; no special derivative-only padding is introduced.

Concepts & Design Notes

Concept Note
Radius Half-width of kernel. Window size = 2 * r + 1 (must be odd, > 0).
One-pass allocation Arrays allocated once; each enabled filter computed per index.
Parallelization Parallel.For engaged when n >= 2000.
Weighted Median Re-computes local window list + sort per index (O(w log w)); heavier than simple linear filters.
Gaussian σ Chosen as (2r + 1)/6 for approximate coverage of ±3σ across the window.
Savitzky-Golay Normalized to unit DC gain (coefficients sum = 1).
Binomial limit Length ≤ 63 to prevent overflow (64-bit safety).

Boundary Handling

BoundaryMode :

  • Symmetric : Mirror index (reflective). Example: index -1 → element 0 mirrored (implemented as -idx - 1 mapping).
  • Replicate : Clamp to nearest endpoint (edge value continuation).
  • ZeroPad : Outside indices treated as 0.

Historical Note: Earlier UI tooltips referenced “Adaptive (Local Poly + Median)” implying SG-only behavior. Current implementation applies Adaptive sliding uniformly to all enabled filters.

Adaptive Mode

Adaptive keeps the nominal window length (2 * r + 1) but slides the window fully inside the valid data range for every index:

  • No mirrored, clamped, or zero-padded synthetic samples are introduced.
  • For Rectangular, Binomial Average, Weighted Median, and Gaussian filters: an in‑range (possibly asymmetric) block is used directly.
  • For Savitzky–Golay: per-position asymmetric coefficients are computed (cached) for (left,right) around the logical center.
  • Benefits: avoids artificial edge energy inflation/attenuation.
  • Trade‑off: near edges the “center” of the polynomial fit is no longer geometrically centered relative to the original index (phase / alignment shift).
  • Implementation detail: loops bypass GetValueWithBoundary when Adaptive to gather a shifted real-sample window.

Use Symmetric when strict geometric centering at edges is more important than removing padding artifacts.

Note : Adaptive boundary handling applies equally to derivative kernels; per-position asymmetric fits are used for all supported filters.


Implemented Filters (Brief)

Filter Characteristic Complexity per sample
Rectangular Average Uniform weights O(w)
Binomial Average Pascal row weights, smoother than uniform O(w)
Weighted Median Robust to spikes, preserves edges O(w log w)
Gaussian Pre-normalized kernel O(w)
Savitzky-Golay Local polynomial least squares (smoothing 0th, derivatives d ≥ 1) O(w) after precompute

w = 2r + 1 where r is the kernel radius.


Performance Characteristics

  • Time : Dominated by selected filters; enabling all includes one sorting per sample (median).
  • Memory : 5 output arrays × n doubles (40n bytes) if all enabled.
  • Parallel : Gains most when median disabled or window moderate (sorting cost can reduce scaling).
  • CSV Export : Streaming + buffered StringBuilder; partitioning to prevent Excel row overflow.

API Reference

Enum: BoundaryMode

public enum BoundaryMode
{
    Symmetric,   // Mirror : Reflect indices across boundaries (e.g., [3, 2, 1, 0, 1, 2, 3])
    Replicate,   // Clamp : Extend edge values beyond boundaries
    ZeroPad,      // Pad with zeros : Use zero-padding for out-of-bound indices
    Adaptive
}

Class: SmoothingConductor (static)

ApplySmoothing
public static (
    double[] Rect,
    double[] Binom,
    double[] Median,
    double[] Gauss,
    double[] SG
) ApplySmoothing(
    double[] input,
    int r,
    int polyOrder,
    BoundaryMode boundaryMode,
    bool doRect,
    bool doAvg,
    bool doMed,
    bool doGauss,
    bool doSG
)

Parameters:

  • input (required) : Source sequence.
  • r : Kernel radius ≥ 0.
  • polyOrder : Used only if doSG == true. Must be < windowSize.
  • boundaryMode : See BoundaryMode.
  • doRect ... doSG : Flags enabling each smoothing.

Returns: Tuple in fixed order : (Rectangular, BinomialAverage, WeightedMedian, Gaussian, SavitzkyGolay). Disabled filters still allocate arrays (filled with 0) for positional consistency.

Exceptions:

  • ArgumentNullException (input)
  • ArgumentOutOfRangeException (r < 0)
  • From subroutines (e.g., Savitzky-Golay coefficient generation constraints).
GetValueWithBoundary
public static double GetValueWithBoundary(
    double[] data,
    int idx,
    BoundaryMode mode
)

Resolves and returns the value at a logical index using the selected boundary handling policy (mirror, clamp, or zero pad). No smoothing is performed here; this is an index resolution helper used by the filters.

ComputeGaussianCoefficients
public static double[] ComputeGaussianCoefficients(
    int length,
    double sigma
)

Constraints :

  • length ≥ 1 (typically odd to align with 2r+1 windows)
  • sigma > 0
    Returns a symmetric Gaussian weight array normalized so the sum ≈ 1.

Exceptions :

  • ArgumentException (length < 1 or sigma ≤ 0)
  • InvalidOperationException (numerical anomaly resulting in non-positive sum)
ComputeSavitzkyGolayCoefficients
public static double[] ComputeSavitzkyGolayCoefficients(
    int windowSize,
    int polyOrder
)

Constraints :

  • windowSize > 0 and odd.
  • polyOrder >= 0 && polyOrder < windowSize. Produces normalized smoothing (0th derivative) coefficients.
ValidateSmoothingParameters
public static bool ValidateSmoothingParameters(
    int dataCount,
    int r,
    int polyOrder,
    bool useSG,
    out string error
)

Checks :

  • (2r + 1) ≤ dataCount
  • If useSG, polyOrder < (2r + 1) Returns false with descriptive error block if invalid.
Validation Helper: ScoreConformanceChecker

A tuple-return wrapper around SmoothingConductor.ValidateSmoothingParameters :

var (success, error) = ScoreConformanceChecker.Validate(
    dataCount: input.Length,
    r: r,
    polyOrder: polyOrder,
    useSG: doSG
);

if (!success)
{
    // Abort early – error contains multi-line diagnostic
    Console.WriteLine(error);
    return;
}

**Rules enforced (delegated) 😗*

  • r >= 0
  • (2 * r + 1) <= dataCount
  • If useSG: polyOrder < (2 * r + 1)

Use this for cleaner guard clauses (no out string).

Note : The wrapper now enforces a non‑negative kernel radius (r >= 0) in addition to the existing rules.
Caution : Callers no longer need to pre‑check r >= 0 before invoking this validator, as the check is performed internally.

ExportCsvAsync / ExportCsvAsyncFromResults

High-level CSV generation with partitioning (honors Excel max row limit).
Two overload paths:

  1. ExportCsvAsync : Recomputes smoothing internally.
  2. ExportCsvAsyncFromResults : Accepts already-computed arrays to avoid recomputation cost.

Notable optional parameters:

  • progress (Action<int>) : Reports rough percent (resets to 0 at completion).
  • progressCheckInterval : Throttle frequency (default 1 = every line).
  • customFlushLineThreshold : Controls buffered flush size (auto if null).
ExportExcelAsync

Creates a live Excel instance (requires Microsoft Excel installed & COM available).
Populates per-filter columns (with multi-column continuation for very large arrays) and builds a composite line chart.
Releases COM RCWs after making Excel visible (workbook remains open to user).

Exceptions surfaced via showMessage callback; some internal catch blocks suppress to keep UI responsive.

Data Container : SmoothingNotation

public sealed class SmoothingNotation
{
    public bool Rectangular { get; set; }
    public bool BinomialAverage { get; set; }
    public bool BinomialMedian { get; set; }
    public bool Gaussian { get; set; }
    public bool SavitzkyGolay { get; set; }

    public bool Any =>
        Rectangular ||
        BinomialAverage ||
        BinomialMedian ||
        Gaussian ||
        SavitzkyGolay;
}

Utility flag bundle passed to export requests.

Data Container : SmoothingScore

public sealed class SmoothingScore
{
    public double[] Initial { get; set; }
    public double[] Rect { get; set; }
    public double[] BinomAvg { get; set; }
    public double[] BinomMed { get; set; }
    public double[] Gauss { get; set; }
    public double[] SavitzkyGolay { get; set; }

    public int Length => Initial?.Length ?? 0;
}

(Not currently returned by core API; available for potential aggregation wrappers.)

CSV Export Types

CsvScoreRequest
public sealed class CsvScoreRequest
{
    public string Title { get; set; }
    public string BaseFilePath { get; set; }
    public double[] InitialData { get; set; }
    public int Radius { get; set; }
    public int PolyOrder { get; set; }
    public int DerivOrder { get; set; } // 0 = smoothing, d > 0 = d-th derivative (only used when Flags.SavitzkyGolay == true)
    public BoundaryMode BoundaryMode { get; set; }
    public SmoothingNotation Flags { get; set; }

    // Optional post-processing flag for UI actions (e.g., auto-open file)
    public bool OpenAfterExport { get; set; }
}
CsvExportResult
public sealed class CsvExportResult
{
    public List<string> GeneratedFiles { get; } = new List<string>();
}
CsvScoreWriter
public static class CsvScoreWriter
{
    public static Task<CsvExportResult> ExportAsync(
        CsvScoreRequest request,
        IProgress<int> progress = null,
        CancellationToken cancellationToken = default
    )
}

Behavior :

  • Validates parameters via a checker (ScoreConformanceChecker.Validate in consuming project).
  • Splits output into parts if row limit exceeded.
  • Column order : Initial Dataset + (enabled filters in consistent descriptive naming).
  • Progress : 0 – 100 based on rows processed. Resets to 0 at completion (intentionally mirrors legacy semantics).
  • Cancellation : Cooperative via CancellationToken.ThrowIfCancellationRequested() inside loop.

Excel Export Types

ExcelScoreRequest
public sealed class ExcelScoreRequest
{
    public string DatasetTitle { get; set; }
    public double[] InitialData { get; set; }
    public int Radius { get; set; }
    public int PolyOrder { get; set; }
    public int DerivOrder { get; set; } // 0 = smoothing, d > 0 = d-th derivative (only used when Flags.SavitzkyGolay == true)
    public BoundaryMode BoundaryMode { get; set; }
    public SmoothingNotation Flags { get; set; }
}
ExcelScoreWriter
public static class ExcelScoreWriter
{
    public static Task ExportAsync(
        ExcelScoreRequest request,
        IProgress<int> progress = null
    );
}

Notes:

  • Two conditional implementations:
    • #if NET48 strong-typed reference to Excel PIA (method signature uses ExcelExportRequest in code region – naming mismatch with ExcelScoreRequest; see "Limitations & Known Inconsistencies").
    • Else : dynamic late binding (Type.GetTypeFromProgID("Excel.Application")), throws ExcelInteropNotAvailableException if unavailable.
ExcelInteropNotAvailableException

Thrown when COM activation cannot proceed (Excel missing / ProgID failure).


Error & Exception Reference (Selected)

Source Condition Exception
ApplySmoothing input == null ArgumentNullException
r < 0 ArgumentOutOfRangeException
CalcBinomialCoefficients length < 1 ArgumentException
length > 63 ArgumentOutOfRangeException
ComputeSavitzkyGolayCoefficients even window or invalid poly order ArgumentException
Matrix inversion singular / ill-conditioned InvalidOperationException
CSV export InitialData null ArgumentNullException
CSV export data length 0 InvalidOperationException
CSV export cancellation requested (token signaled) OperationCanceledException
Excel late binding Excel not installed ExcelInteropNotAvailableException
Excel export no enabled sections InvalidOperationException

Usage Examples

1. Savitzky-Golay Only

var (_, _, _, _, sg) = SmoothingConductor.ApplySmoothing(
    input: signal,
    r: 4,
    polyOrder: 3,
    boundaryMode: BoundaryMode.Replicate,
    doRect: false,
    doAvg: false,
    doMed: false,
    doGauss: false,
    doSG: true
);

2. Precompute & Export CSV Without Recalculation

int r = 3;
int poly = 2;

// Execute a range of smoothing algorithms on the input data
var (rect, avg, med, gauss, sg) = SmoothingConductor.ApplySmoothing(
    data,
    r,
    poly,
    BoundaryMode.Symmetric,
    doRect: true,
    doAvg: true,
    doMed: true,
    doGauss: true,
    doSG: true
);

// Write smoothing results to a CSV file
await SmoothingConductor.ExportCsvAsyncFromResults(
    filePath: @"C:\out\multi.csv",
    title: "Precomputed Export",
    kernelRadius: r,
    polyOrder: poly,
    boundaryMode: BoundaryMode.Symmetric,
    doRect: true,
    doAvg: true,
    doMed: true,
    doGauss: true,
    doSG: true,
    initialData: data,
    rectAvg: rect,
    binomAvg: avg,
    binomMed: med,
    gaussFilt: gauss,
    sgFilt: sg,
    progress: p => Console.WriteLine($"CSV {p}%")
);

Important : ExportCsvAsyncFromResults does not internally validate that supplied smoothing arrays match initialData.Length. All arrays must be length-aligned; otherwise an index exception will occur during streaming.

3. Excel Export (Late Binding Mode)

var req = new ExcelScoreRequest
{
    DatasetTitle = "Signal Run 42",
    InitialData = data,
    Radius = 5,
    PolyOrder = 3,
    BoundaryMode = BoundaryMode.Symmetric,
    Flags = new SmoothingNotation
    {
        Rectangular = true,
        BinomialAverage = true,
        BinomialMedian = false,
        Gaussian = true,
        SavitzkyGolay = true
    }
};

await ExcelScoreWriter.ExportAsync(
    req,
    new Progress<int>(p => Console.WriteLine($"Excel {p}%"))
);

Export Header / Label Differences

Aspect CsvScoreWriter ExcelScoreWriter SmoothingConductor ExportCsv / ExportExcel
Boundary labels Short (“Symmetric”, “Replicate”, “ZeroPad”, “Adaptive”) Short Extended (“Symmetric (Mirror)”, “Replicate (Nearest)”, “Zero Padding”, “Adaptive”)
Derivative line “Derivative Order : d” when SG & DerivOrder > 0 Same (row after Polynomial Order) Not emitted (always smoothing)
Subject / Comments rows Not written Stored as document properties only Written explicitly as worksheet rows (Subject, Comments)
Progress Semantics
Operation Completion Behavior
CsvScoreWriter.ExportAsync / ExportCsvAsync* Resets to 0 after finishing
SmoothingConductor.ExportExcelAsync Ends at 100% (no reset)
ExcelScoreWriter.ExportAsync May reach 100% during data fill then resets to 0 after chart creation

Best Practices

  • Keep radius modest (3 – 9) for interactive scenarios; large radii escalate median cost.
  • Validate parameters before UI commit using ValidateSmoothingParameters.
  • Reuse precomputed results when exporting multiple times (CSV or Excel) to avoid repeated smoothing.
  • Use BoundaryMode.Symmetric for most natural edge continuity unless edge clamping desired.
  • Consider disabling median for extremely large datasets if throughput is critical.
  • Use ScoreConformanceChecker.Validate for concise parameter guards instead of calling the out‑param form directly.

Note : ValidateSmoothingParameters now enforces a non‑negative kernel radius (r ≥ 0) in addition to existing rules. Callers no longer need to pre‑check for negative radius values before invoking the validator.


Thread Safety

  • Static methods are stateless; safe for concurrent calls.
  • Do not reuse output arrays between concurrent operations.
  • Excel export methods are inherently single-threaded due to COM constraints.

Limitations & Known Inconsistencies

Item Detail
Naming discrepancy README earlier referenced SmoothingTuner; current implementation exposes SmoothingConductor. Update code or aliases if backward compatibility needed.
Excel #if NET48 signature Strong-typed branch references ExcelExportRequest (not provided here) while public late-binding branch uses ExcelScoreRequest. Harmonize names to reduce confusion.
Weighted median performance O(n * w log w) cost may dominate for large windows; consider optional alternative (e.g., running selection algorithms) if needed.
Progress reset Exports intentionally report 0 at completion mirroring legacy UI expectations.
Localization Export uses invariant numeric format; headers partially English (intentionally stable for machine parsing).
Large matrices Savitzky-Golay inversion may throw if matrix ill-conditioned for extreme parameter combinations.
Excel boundary label variance High-level ExcelScoreWriter uses abbreviated labels; core SmoothingConductor Excel export uses extended labels.

License

MIT License. Include the full text in distribution (see root LICENSE if present).


Changelog

  • Added Savitzky–Golay derivative support :
    • New APIs : SmoothingConductor.ApplySGDerivative(...) and ComputeSavitzkyGolayCoefficients(windowSize, polyOrder, derivativeOrder, delta).
    • New DTO fields : CsvScoreRequest.DerivOrder, ExcelScoreRequest.DerivOrder (0 = smoothing).
    • CSV/Excel : if DerivOrder > 0, the SG column/series is the derivative; header shows "Derivative Order : d" (Δ = 1.0).
  • Validation : SmoothingConductor.ValidateSmoothingParameters enforces r ≥ 0.
  • CSV export : part-size computation includes the derivative header line only when applicable; progress semantics clarified.
  • Excel export : derivative header line emitted; multi-area range construction optimized to reduce COM interop churn.
  • Docs : Updated README, API_Documentation.xml, and SonataSmooth_API_Reference.md; standardized csharp code fences; fixed Windows path examples.
  • Backward compatibility : no breaking changes; existing smoothing overloads and tuple order unchanged.

Disclaimer

This library focuses on clarity and predictable numeric stability over hyper-optimized micro-ops. Benchmark with your dataset before large-scale batch deployment.


Happy smoothing.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.1.5 45 9/17/2025

- Applied symmetric trimming to Rect / Binom / Median / Gauss filters in Adaptive mode to eliminate edge phase bias, while adding NaN / Infinity handling and boundary safety checks to improve stability and accuracy.

- Added support for saving files in Excel format.

- Minor bugs fixed.