Skip to main content

Asset health scoring

At a glance

Effort: ~20–30 minutes · You'll build: a composite 0–100 health index from several signals, with a healthy/watch/critical classification · Stack: the SDK plus a little arithmetic — no model training.

A machine rarely fails on one signal. Vibration is creeping up, the bearing runs a little hot, oil pressure sags at load — each is fine alone, but together they tell a story. A health score rolls those signals into one comparable number so an operator can rank a whole fleet at a glance and a dashboard can show green/amber/red. It's the lightweight cousin of predictive maintenance: no model to train, just a transparent, tunable index.

New to machine learning?

No background needed. Skim the gentle primer for the ideas in plain language — model, feature, training, and the algorithm itself — and use Generate sample data for a sandbox to run this against.

Need data to run this?

This reads several pump signals. Generate a sandbox first — section A ingests pump_07_bearing_temp_c, pump_07_oil_pressure_kpa and a stand-in pump_07_vibration_anomaly (or run predictive maintenance to produce the real one).

1. Pull the latest value of each signal​

Take the most recent reading (or short average) of each contributing series for the asset.

import intellistream_datahub_sdk, pandas as pd

client = intellistream_datahub_sdk.DataHubClient.from_env()

def latest(external_id):
rf = intellistream_datahub_sdk.RetrieveFilter(
ts=external_id,
start=pd.Timestamp.now(tz="UTC") - pd.Timedelta(minutes=15),
end=pd.Timestamp.now(tz="UTC"),
aggregates=["avg"], granularity="15m")
pts = client.timeseries.retrieve_datapoints(rf)[0].get_datapoints()
return float(pts[-1].average)

signals = {
"vibration": latest("pump_07_vibration_anomaly"), # 0..~1, from the anomaly model
"bearing_temp": latest("pump_07_bearing_temp_c"),
"oil_pressure": latest("pump_07_oil_pressure_kpa"),
}

2. Normalise each signal to a "badness" in 0–1​

Every signal lives on its own scale, so map each to a common 0 (fine) → 1 (alarm) range against its healthy and limit values. A reading at or below healthy scores 0; at or above the limit scores 1; in between, it ramps linearly.

def badness(value, healthy, limit):
if limit == healthy:
return 0.0
return max(0.0, min(1.0, (value - healthy) / (limit - healthy)))

LIMITS = { # (healthy, limit) per signal
"vibration": (0.05, 0.30),
"bearing_temp": (60.0, 90.0),
"oil_pressure": (350.0, 250.0), # inverted: lower is worse
}
parts = {k: badness(v, *LIMITS[k]) for k, v in signals.items()}

3. Weight, combine, and classify​

Weight the signals by how much each matters for this asset class, combine into a 0–100 score (100 = perfect health), and bucket it.

WEIGHTS = {"vibration": 0.5, "bearing_temp": 0.3, "oil_pressure": 0.2}

badness_total = sum(parts[k] * WEIGHTS[k] for k in parts)
score = round(100 * (1 - badness_total), 1)

band = "healthy" if score >= 80 else "watch" if score >= 60 else "critical"

4. Publish the score and flag the bad ones​

Write the score back as its own series — now you can chart, rank and subscribe to asset health like any other signal — and raise an event when an asset drops to critical.

client.timeseries.create([intellistream_datahub_sdk.TimeSeries(
external_id="pump_07_health_score", name="Pump 07 health score", unit="score", value_type="float")])
client.timeseries.insert_from_lists(
timestamps=[pd.Timestamp.now(tz="UTC")], values=[score], ts="pump_07_health_score")

if band == "critical":
client.events.create([intellistream_datahub_sdk.Event(
external_id=f"health_critical_pump_07_{int(pd.Timestamp.now().timestamp())}",
type="health_critical", status="open",
event_time=pd.Timestamp.now(tz="UTC"),
metadata={"asset": "pump_07", "score": str(score),
"worst_signal": max(parts, key=parts.get)})])

Run it across the fleet on a schedule and you have a single ranked health view — worst_signal in the metadata tells maintenance why each asset is red.

Where to take it further​

  • Feed it the model. Swap the hand-set vibration limits for the anomaly score as a direct input.
  • Trend the score. A falling health score over days is itself a predictor — forecast it like any other series.
  • Roll up the graph. Average child scores up a site graph for a line- or plant-level health number.

Further reading​

See also​