Integration

SPC analysis results are plain .NET objects. They can be mapped to a charting library, serialized to JSON and stored, returned from a web-API endpoint, or cached between requests. This page describes the common integration patterns: plotting, service integration, JSON round-trip, and the trade-off between persisting results and recomputing them on demand.

UI and Plotting Integration

Any charting library that can draw line series and reference lines is sufficient to visualize a control chart. The mapping from the SPC result model to chart primitives is always the same:

Result property

Chart primitive

Values

Primary line-with-markers series. The x-axis is the sequential point index (or a timestamp array your application maintains separately).

CenterLine

Solid horizontal reference line at the scalar value.

UpperControlLimit / LowerControlLimit

Dashed horizontal lines for equal-subgroup-size charts. For variable-size P and U charts, plot the UpperControlLimits and LowerControlLimits vectors as step-function series instead.

RuleViolation collection

Shaded bands using WindowStart and WindowLength; distinct marker at TriggerIndex. See Result Model and Rendering Semantics for the exact coordinate calculation.

C#
double[] data = {
    10.5, 11.2, 10.8, 11.5, 10.3, 11.8, 10.1, 11.4,
    10.9, 11.1, 10.6, 11.3, 10.7, 11.0, 10.4
};
IndividualsMovingRangeChartSet chart =
    new IndividualsMovingRangeChartSet(Vector.Create(data));
chart.Analyze();

FixedLimitSeries iSeries = chart.IndividualsSeries;

// Build a plotting model (pseudocode — use your own charting library)
// var model = new ChartModel();
// model.AddSeries("Individuals", iSeries.Values);
// model.AddConstantLine("CL",  iSeries.CenterLine,  lineStyle: Solid);
// model.AddConstantLine("UCL", iSeries.UpperControlLimit, lineStyle: Dashed);
// model.AddConstantLine("LCL", iSeries.LowerControlLimit, lineStyle: Dashed);
Console.WriteLine($"Ready to render {iSeries.Values.Count} points.");

  Note

The SPC library does not depend on or reference any charting library. The result objects are pure data; rendering is entirely the caller's responsibility.

Service and API Integration

Because fitted chart objects contain only immutable vectors and values, scalar doubles, and nested plain objects, they serialize cleanly without circular references or opaque handles. Typical patterns in a service layer are:

  • REST API response DTO — map a ControlChart or its ControlSeries payload directly to a JSON response body. The default System.Text.Json serializer handles the public properties without additional configuration.

  • SignalR / WebSocket push — for Phase II monitoring, serialize a deployed chart and store it; when new observations arrive, call Apply(Vector<Double>) and push the serialized fitted result to connected clients.

  • Background job output — serialize the result to a message-queue payload; a downstream consumer deserializes it for display without needing access to the raw data.

  Caution

Result objects do not hold a reference to the original input data. If you need to allow the end user to re-run the analysis with different settings, persist the input data separately alongside the result.

JSON Serialization

Result types in the SPC API are designed to round-trip through standard .NET JSON serializers. ControlChart and all ControlSeries subtypes expose only public properties with public getters, making them compatible with both System.Text.Json.JsonSerializer and Newtonsoft.Json.JsonConvert without custom converters.

C#
double[] data = {
    10.5, 11.2, 10.8, 11.5, 10.3, 11.8, 10.1, 11.4,
    10.9, 11.1, 10.6, 11.3, 10.7, 11.0, 10.4
};

IndividualsMovingRangeChartSet chart =
    new IndividualsMovingRangeChartSet(Vector.Create(data));
chart.Analyze();

// Deploy the chart to freeze parameters, then serialize
IndividualsMovingRangeChartSet deployed = chart.Deploy();
string json = deployed.ToJson();
Console.WriteLine($"JSON length: {json.Length} chars");

To deserialize a stored result:

C#
// Deserialize a previously stored deployed chart
string json = "/* previously serialized JSON */";

IndividualsMovingRangeChartSet restored =
    IndividualsMovingRangeChartSet.FromJson(json);

Console.WriteLine(
    $"Restored CL = {restored.IndividualsSeries.CenterLine:F4}");

  Important

Polymorphic deserialization of ControlSeries requires a type discriminator in your JSON schema. The recommended approach is to store the concrete type name alongside the payload in your persistence layer and then deserialize to the exact concrete type (e.g., IndividualsMovingRangeChartSet, PChart) rather than to the abstract base.

Persisting vs. Recomputing

SPC results are immutable and self-contained. Once computed, a fitted chart object fully describes the state of the control chart at the time the analysis was run. No re-analysis is required to render the chart or evaluate rules later.

Strategy

When to use

Trade-offs

Persist result

The chart will be viewed many times, the computation is expensive (large data set), or the raw data is not retained long-term.

Instant retrieval; storage cost proportional to Values.Length; requires re-persist when settings change.

Recompute on demand

Data is already cached, computations are cheap (small data sets), or settings change frequently.

No storage overhead; always up to date; adds latency on each request.

Persist result + raw data

Users may need to change the rule set, sigma estimator, or specification limits without importing data again.

Maximum flexibility; highest storage cost; requires invalidation logic when settings change.

See Also