Tabular Regression
ONNX
LiteRT
Keras
PyTorch
LiteRT
industrial
pump
digital-twin
edge-ai
onnxruntime
tensorflow
anomaly-detection
Instructions to use sankalpsthakur/forge-pump-surrogate-multiruntime with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT
How to use sankalpsthakur/forge-pump-surrogate-multiruntime with LiteRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
Publish read-only edge adapters and generic PLC tag examples
Browse files- edge/inference_onnx.py +50 -0
- edge/plc_guard.py +29 -0
- edge/tag_map.yml +33 -0
edge/inference_onnx.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Run the public pump surrogate with ONNX Runtime on CPU."""
|
| 3 |
+
|
| 4 |
+
from __future__ import annotations
|
| 5 |
+
|
| 6 |
+
import argparse
|
| 7 |
+
import json
|
| 8 |
+
from pathlib import Path
|
| 9 |
+
|
| 10 |
+
import numpy as np
|
| 11 |
+
import onnxruntime as ort
|
| 12 |
+
|
| 13 |
+
FEATURE_ORDER = (
|
| 14 |
+
"speed_fraction",
|
| 15 |
+
"static_head_m",
|
| 16 |
+
"system_k",
|
| 17 |
+
"voltage_fraction",
|
| 18 |
+
"ambient_temp_c",
|
| 19 |
+
"inlet_pressure_bar",
|
| 20 |
+
)
|
| 21 |
+
TARGET_ORDER = (
|
| 22 |
+
"flow_m3h",
|
| 23 |
+
"total_head_m",
|
| 24 |
+
"input_power_kw",
|
| 25 |
+
"winding_temp_c",
|
| 26 |
+
"npsh_margin_m",
|
| 27 |
+
"efficiency_fraction",
|
| 28 |
+
)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def predict(model_path: Path, values: list[float]) -> dict[str, float]:
|
| 32 |
+
if len(values) != len(FEATURE_ORDER):
|
| 33 |
+
raise ValueError(f"expected {len(FEATURE_ORDER)} values")
|
| 34 |
+
session = ort.InferenceSession(str(model_path), providers=["CPUExecutionProvider"])
|
| 35 |
+
output = session.run(["outputs"], {"features": np.asarray([values], dtype=np.float32)})[0][0]
|
| 36 |
+
return {name: float(value) for name, value in zip(TARGET_ORDER, output, strict=True)}
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def main() -> int:
|
| 40 |
+
parser = argparse.ArgumentParser()
|
| 41 |
+
parser.add_argument("--model", type=Path, default=Path("onnx/model.onnx"))
|
| 42 |
+
parser.add_argument("values", nargs=6, type=float, metavar="VALUE")
|
| 43 |
+
args = parser.parse_args()
|
| 44 |
+
print(json.dumps({"feature_order": FEATURE_ORDER, "prediction": predict(args.model, args.values)}, indent=2))
|
| 45 |
+
return 0
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
if __name__ == "__main__":
|
| 49 |
+
raise SystemExit(main())
|
| 50 |
+
|
edge/plc_guard.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Read-only advisory boundary around pump-surrogate predictions.
|
| 2 |
+
|
| 3 |
+
This module has no network, PLC, OPC UA, S7, or Modbus client. It cannot write
|
| 4 |
+
to a controller. Certified equipment protection and emergency shutdown logic
|
| 5 |
+
must remain in an independently engineered PLC/SIS layer.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
from __future__ import annotations
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def advisory(features: dict[str, float], prediction: dict[str, float]) -> dict[str, object]:
|
| 12 |
+
reasons: list[str] = []
|
| 13 |
+
if features["voltage_fraction"] < 0.90:
|
| 14 |
+
reasons.append("undervoltage_demo_threshold")
|
| 15 |
+
if prediction["npsh_margin_m"] < 1.0:
|
| 16 |
+
reasons.append("cavitation_margin_demo_threshold")
|
| 17 |
+
if prediction["winding_temp_c"] > 70.0:
|
| 18 |
+
reasons.append("thermal_demo_threshold")
|
| 19 |
+
if features["speed_fraction"] > 0.35 and prediction["flow_m3h"] < 0.20:
|
| 20 |
+
reasons.append("no_flow_demo_threshold")
|
| 21 |
+
if prediction["input_power_kw"] > 3.2:
|
| 22 |
+
reasons.append("overload_demo_threshold")
|
| 23 |
+
return {
|
| 24 |
+
"mode": "read_only_advisory",
|
| 25 |
+
"severity": "review" if reasons else "nominal",
|
| 26 |
+
"reasons": reasons,
|
| 27 |
+
"automatic_write_allowed": False,
|
| 28 |
+
"operator_or_safety_system_decision_required": bool(reasons),
|
| 29 |
+
}
|
edge/tag_map.yml
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
schema_version: 1
|
| 2 |
+
profile: generic_pump_demo_read_only
|
| 3 |
+
write_enabled: false
|
| 4 |
+
note: >-
|
| 5 |
+
Illustrative symbolic mappings only. Siemens is a trademark of its owner;
|
| 6 |
+
this project is not affiliated with or validated by Siemens. No PLC client
|
| 7 |
+
or controller write path is included.
|
| 8 |
+
signals:
|
| 9 |
+
speed_fraction:
|
| 10 |
+
opcua_node: "ns=2;s=PumpDemo.SpeedFraction"
|
| 11 |
+
modbus_input_register: 30001
|
| 12 |
+
s7_symbolic: "DB_PUMP_DEMO.SpeedFraction"
|
| 13 |
+
static_head_m:
|
| 14 |
+
opcua_node: "ns=2;s=PumpDemo.StaticHeadM"
|
| 15 |
+
modbus_input_register: 30003
|
| 16 |
+
s7_symbolic: "DB_PUMP_DEMO.StaticHeadM"
|
| 17 |
+
system_k:
|
| 18 |
+
opcua_node: "ns=2;s=PumpDemo.SystemK"
|
| 19 |
+
modbus_input_register: 30005
|
| 20 |
+
s7_symbolic: "DB_PUMP_DEMO.SystemK"
|
| 21 |
+
voltage_fraction:
|
| 22 |
+
opcua_node: "ns=2;s=PumpDemo.VoltageFraction"
|
| 23 |
+
modbus_input_register: 30007
|
| 24 |
+
s7_symbolic: "DB_PUMP_DEMO.VoltageFraction"
|
| 25 |
+
ambient_temp_c:
|
| 26 |
+
opcua_node: "ns=2;s=PumpDemo.AmbientTempC"
|
| 27 |
+
modbus_input_register: 30009
|
| 28 |
+
s7_symbolic: "DB_PUMP_DEMO.AmbientTempC"
|
| 29 |
+
inlet_pressure_bar:
|
| 30 |
+
opcua_node: "ns=2;s=PumpDemo.InletPressureBar"
|
| 31 |
+
modbus_input_register: 30011
|
| 32 |
+
s7_symbolic: "DB_PUMP_DEMO.InletPressureBar"
|
| 33 |
+
|