# Alarm Analysis Dashboard A drop-in Ignition Perspective dashboard that turns the **alarm journal** into actionable alarm-management metrics: alarm rate, MTTA/MTTR, flood episodes, chattering and standing alarms, a Pareto of bad actors, a day/hour heatmap, and an overall alarm-health score graded A–F against ISA-18.2 style targets. It reads the journal through `system.alarm.queryJournal` / `system.alarm.queryStatus` only. There are **no tags, no named queries, no SQL and no database connection** — if the gateway has an alarm journal profile with data in it, the dashboard works. --- ## Requirements * Ignition **8.1.20+** with the **Perspective** module. * An **alarm journal profile** that is receiving data (Gateway → Config → Alarming → Journal). Any journal store works; the resource never talks to the database directly. * No third-party modules, no Python packages, no gateway scripting configuration. ## Install 1. In the Designer, open the project you want the resource in and choose **File → Import…**, or use **Config → Projects → Import** on the Gateway web page to bring the download in as its own project. 2. Import the resource. Everything lands under namespaced folders, so nothing in an existing project is overwritten: | Resource | Location | |---|---| | Views | `Exchange/AlarmAnalysis/…` | | Style classes | `exchange/alarm-analysis/…` | | Project library | `exchange/alarmAnalysis/{alarms, calc, fmt}` | | Page | `/alarm-analysis` → `Exchange/AlarmAnalysis/Dashboard` | 3. **Save** the project. 4. Open a Perspective session and browse to **`/alarm-analysis`**. That is the whole installation. The dashboard holds all of its own state on the `Dashboard` view, so importing it does **not** add session custom properties, client tags or global variables to your project. ### If you imported into an existing project * The page URL `/alarm-analysis` is added to your project's page configuration. If that URL is already taken, change it in **Project Browser → Perspective → Page Configuration**; the view path it should point at is `Exchange/AlarmAnalysis/Dashboard`. * Nothing else in your project is touched — every resource is namespaced. ### If you want it on its own page shell Embed `Exchange/AlarmAnalysis/Dashboard` in any view or dock. It takes no parameters and sizes itself to its container (design size 1600×900). ## Using it | Tab | What it shows | |---|---| | **Overview** | Headline KPIs vs the previous equal-length period, alarm-rate chart, priority mix, top sources, and plain-language insights. | | **Analysis** | Day/hour heatmap, flood episodes, MTTA/MTTR trend, and priority distribution against the ISA 80/15/5 target. | | **Bad Actors** | Pareto of the worst offenders plus chattering, standing and fleeting alarm tables. Click a row for the per-source drill-down. | | **Journal** | Paged, filtered journal browser with CSV export and a per-event detail popup. | * The **range selector** and **Refresh** in the header set the analysis window. * The **filter bar** (Priority / Area / State / Search) applies to every tab except Overview, which deliberately stays a plant-wide summary. * **Shift Report** renders a plain-text handover summary for the previous shift, ready to copy into a log. * Clicking a source anywhere drills through to that source in **Bad Actors**; clicking a Bad Actors row opens the per-source history popup. ## Tuning All thresholds live in one place — `exchange.alarmAnalysis.calc.DEFAULTS`: | Key | Default | Meaning | |---|---|---| | `target_per_hr` | `6.0` | ISA target alarm rate per operator per hour | | `flood_per_10min` | `10` | Activations per 10 min that start a flood episode | | `chatter_per_hr` | `10.0` | Re-triggers per hour that mark a source as chattering | | `chatter_gap_s` | `120` | Median gap below which re-triggers count as chatter | | `fleeting_s` | `10` | Active duration below which an alarm counts as fleeting | | `standing_hours` | `24` | Age above which an active alarm counts as standing | | `priority_target` | `80/15/5` | ISA low/medium/high priority mix | | `health_weights` | see source | Weighting of the five health sub-scores | | `max_events` | `50000` | Hard cap on journal rows read per query | Edit the dict in the Designer's script library, or pass an override dict as the `opts` argument of any `calc` function. ## Script library | Module | Responsibility | |---|---| | `exchange.alarmAnalysis.alarms` | Talks to `system.alarm`; the only module that does I/O. Entry points used by the views: `getDashboardBundle`, `getJournalPage`, `journalCsv`, `getSourceDetail`, `getEventData`, `getShiftReportText`. | | `exchange.alarmAnalysis.calc` | Pure analytics — correlation, binning, floods, chatter, MTTA/MTTR, Pareto, health score. No Ignition API calls, so it is unit-testable. | | `exchange.alarmAnalysis.fmt` | Display formatting and the natural-language insight/shift-report text. | Every public function carries a docstring, so the Designer's autocomplete documents the API. ## Notes and limits * The journal is queried for **twice** the selected window (current plus the equal-length prior period) so every KPI can show a delta. A very wide range over a busy plant is bounded by `max_events`; when that cap is hit the header shows a *truncated* chip. * Alarm instances are correlated by journal event id when the journal supplies one, and by a per-source active/clear state machine otherwise. The mode in use is reported in `bundle.meta.correlation_mode`. * "Active now", unacked and shelved counts come from live alarm status, so they reflect the present moment rather than the selected window. * Scripts are Jython 2.7 compatible (no f-strings, no `typing`, no `statistics`). ## License Provided as-is under the terms of the Ignition Exchange.