45 json[QStringLiteral(
"id")] =
id;
47 json[QStringLiteral(
"phase")] =
phase;
48 json[QStringLiteral(
"expression")] =
expression;
49 if (!
script.code.isEmpty()) {
50 json[QStringLiteral(
"script")] =
script.toJson();
52 json[QStringLiteral(
"severity")] =
severity;
54 json[QStringLiteral(
"on_fail")] =
onFail;
64 c.
id = json.value(QStringLiteral(
"id")).toString();
65 c.
description = json.value(QStringLiteral(
"description")).toString();
66 c.
phase = json.value(QStringLiteral(
"phase")).toString();
67 c.
expression = json.value(QStringLiteral(
"expression")).toString();
68 if (json.contains(QStringLiteral(
"script"))) {
71 c.
severity = json.value(QStringLiteral(
"severity")).toString();
72 c.
onFail = json.value(QStringLiteral(
"on_fail")).toString();
81 cbor.insert(QStringLiteral(
"id"),
id);
82 cbor.insert(QStringLiteral(
"description"),
description);
83 cbor.insert(QStringLiteral(
"phase"),
phase);
84 cbor.insert(QStringLiteral(
"expression"),
expression);
85 if (!
script.code.isEmpty()) {
86 cbor.insert(QStringLiteral(
"script"),
script.toCbor());
88 cbor.insert(QStringLiteral(
"severity"),
severity);
90 cbor.insert(QStringLiteral(
"on_fail"),
onFail);
100 c.
id = cbor.value(QStringLiteral(
"id")).toString();
101 c.
description = cbor.value(QStringLiteral(
"description")).toString();
102 c.
phase = cbor.value(QStringLiteral(
"phase")).toString();
103 c.
expression = cbor.value(QStringLiteral(
"expression")).toString();
104 if (cbor.contains(QStringLiteral(
"script"))) {
107 c.
severity = cbor.value(QStringLiteral(
"severity")).toString();
108 c.
onFail = cbor.value(QStringLiteral(
"on_fail")).toString();
119 json[QStringLiteral(
"check_id")] =
checkId;
120 json[QStringLiteral(
"passed")] =
passed;
121 json[QStringLiteral(
"severity")] =
severity;
122 json[QStringLiteral(
"message")] =
message;
123 json[QStringLiteral(
"actual_value")] = QJsonValue::fromVariant(
actualValue);
125 json[QStringLiteral(
"evaluated_at")] =
evaluatedAt.toString(Qt::ISODateWithMs);
135 r.
checkId = json.value(QStringLiteral(
"check_id")).toString();
136 r.
passed = json.value(QStringLiteral(
"passed")).toBool(
false);
137 r.
severity = json.value(QStringLiteral(
"severity")).toString();
138 r.
message = json.value(QStringLiteral(
"message")).toString();
139 r.
actualValue = json.value(QStringLiteral(
"actual_value")).toVariant();
140 r.
evaluatedAt = QDateTime::fromString(json.value(QStringLiteral(
"evaluated_at")).toString(), Qt::ISODateWithMs);
149 cbor.insert(QStringLiteral(
"check_id"),
checkId);
150 cbor.insert(QStringLiteral(
"passed"),
passed);
151 cbor.insert(QStringLiteral(
"severity"),
severity);
152 cbor.insert(QStringLiteral(
"message"),
message);
153 cbor.insert(QStringLiteral(
"actual_value"), QCborValue::fromVariant(
actualValue));
155 cbor.insert(QStringLiteral(
"evaluated_at"),
evaluatedAt.toString(Qt::ISODateWithMs));
165 r.
checkId = cbor.value(QStringLiteral(
"check_id")).toString();
166 r.
passed = cbor.value(QStringLiteral(
"passed")).toBool();
167 r.
severity = cbor.value(QStringLiteral(
"severity")).toString();
168 r.
message = cbor.value(QStringLiteral(
"message")).toString();
169 r.
actualValue = cbor.value(QStringLiteral(
"actual_value")).toVariant();
170 r.
evaluatedAt = QDateTime::fromString(cbor.value(QStringLiteral(
"evaluated_at")).toString(), Qt::ISODateWithMs);
185 hashObj.insert(it.key(), it.value());
187 json[QStringLiteral(
"input_hashes")] = hashObj;
193 attrObj.insert(it.key(), QJsonValue::fromVariant(it.value()));
195 json[QStringLiteral(
"resolved_attributes")] = attrObj;
201 if (!
osInfo.isEmpty()) json[QStringLiteral(
"os_info")] =
osInfo;
205 if (
startedAt.isValid()) json[QStringLiteral(
"started_at")] =
startedAt.toString(Qt::ISODateWithMs);
206 if (
finishedAt.isValid()) json[QStringLiteral(
"finished_at")] =
finishedAt.toString(Qt::ISODateWithMs);
220 const QJsonObject hashObj = json.value(QStringLiteral(
"input_hashes")).toObject();
221 for (
auto it = hashObj.constBegin(); it != hashObj.constEnd(); ++it) {
222 p.
inputHashes.insert(it.key(), it.value().toString());
225 const QJsonObject attrObj = json.value(QStringLiteral(
"resolved_attributes")).toObject();
226 for (
auto it = attrObj.constBegin(); it != attrObj.constEnd(); ++it) {
230 p.
mneCppVersion = json.value(QStringLiteral(
"mne_cpp_version")).toString();
231 p.
qtVersion = json.value(QStringLiteral(
"qt_version")).toString();
232 p.
compilerInfo = json.value(QStringLiteral(
"compiler_info")).toString();
233 p.
osInfo = json.value(QStringLiteral(
"os_info")).toString();
234 p.
hostName = json.value(QStringLiteral(
"host_name")).toString();
237 p.
startedAt = QDateTime::fromString(json.value(QStringLiteral(
"started_at")).toString(), Qt::ISODateWithMs);
238 p.
finishedAt = QDateTime::fromString(json.value(QStringLiteral(
"finished_at")).toString(), Qt::ISODateWithMs);
239 p.
wallTimeMs =
static_cast<qint64
>(json.value(QStringLiteral(
"wall_time_ms")).toDouble(0));
240 p.
peakMemoryBytes =
static_cast<qint64
>(json.value(QStringLiteral(
"peak_memory_bytes")).toDouble(0));
241 p.
randomSeed =
static_cast<qint64
>(json.value(QStringLiteral(
"random_seed")).toDouble(-1));
255 hashMap.insert(it.key(), it.value());
257 cbor.insert(QStringLiteral(
"input_hashes"), hashMap);
263 attrMap.insert(it.key(), QCborValue::fromVariant(it.value()));
265 cbor.insert(QStringLiteral(
"resolved_attributes"), attrMap);
271 if (!
osInfo.isEmpty()) cbor.insert(QStringLiteral(
"os_info"),
osInfo);
272 if (!
hostName.isEmpty()) cbor.insert(QStringLiteral(
"host_name"),
hostName);
275 if (
startedAt.isValid()) cbor.insert(QStringLiteral(
"started_at"),
startedAt.toString(Qt::ISODateWithMs));
276 if (
finishedAt.isValid()) cbor.insert(QStringLiteral(
"finished_at"),
finishedAt.toString(Qt::ISODateWithMs));
290 const QCborMap hashMap = cbor.value(QStringLiteral(
"input_hashes")).toMap();
291 for (
auto it = hashMap.constBegin(); it != hashMap.constEnd(); ++it) {
292 p.
inputHashes.insert(it.key().toString(), it.value().toString());
295 const QCborMap attrMap = cbor.value(QStringLiteral(
"resolved_attributes")).toMap();
296 for (
auto it = attrMap.constBegin(); it != attrMap.constEnd(); ++it) {
300 p.
mneCppVersion = cbor.value(QStringLiteral(
"mne_cpp_version")).toString();
301 p.
qtVersion = cbor.value(QStringLiteral(
"qt_version")).toString();
302 p.
compilerInfo = cbor.value(QStringLiteral(
"compiler_info")).toString();
303 p.
osInfo = cbor.value(QStringLiteral(
"os_info")).toString();
304 p.
hostName = cbor.value(QStringLiteral(
"host_name")).toString();
307 p.
startedAt = QDateTime::fromString(cbor.value(QStringLiteral(
"started_at")).toString(), Qt::ISODateWithMs);
308 p.
finishedAt = QDateTime::fromString(cbor.value(QStringLiteral(
"finished_at")).toString(), Qt::ISODateWithMs);
309 p.
wallTimeMs = cbor.value(QStringLiteral(
"wall_time_ms")).toInteger(0);
310 p.
peakMemoryBytes = cbor.value(QStringLiteral(
"peak_memory_bytes")).toInteger(0);
311 p.
randomSeed = cbor.value(QStringLiteral(
"random_seed")).toInteger(-1);
331 arr.append(c.toJson());
333 json[QStringLiteral(
"checks")] = arr;
339 arr.append(r.toJson());
341 json[QStringLiteral(
"pre_results")] = arr;
347 arr.append(r.toJson());
349 json[QStringLiteral(
"post_results")] = arr;
353 if (!provObj.isEmpty()) {
354 json[QStringLiteral(
"provenance")] = provObj;
366 v.
explanation = json.value(QStringLiteral(
"explanation")).toString();
368 const QJsonArray checksArr = json.value(QStringLiteral(
"checks")).toArray();
369 for (
const QJsonValue& val : checksArr) {
373 const QJsonArray preArr = json.value(QStringLiteral(
"pre_results")).toArray();
374 for (
const QJsonValue& val : preArr) {
378 const QJsonArray postArr = json.value(QStringLiteral(
"post_results")).toArray();
379 for (
const QJsonValue& val : postArr) {
383 if (json.contains(QStringLiteral(
"provenance"))) {
397 cbor.insert(QStringLiteral(
"explanation"),
explanation);
403 arr.append(c.toCbor());
405 cbor.insert(QStringLiteral(
"checks"), arr);
411 arr.append(r.toCbor());
413 cbor.insert(QStringLiteral(
"pre_results"), arr);
419 arr.append(r.toCbor());
421 cbor.insert(QStringLiteral(
"post_results"), arr);
425 if (!provMap.isEmpty()) {
426 cbor.insert(QStringLiteral(
"provenance"), provMap);
438 v.
explanation = cbor.value(QStringLiteral(
"explanation")).toString();
440 const QCborArray checksArr = cbor.value(QStringLiteral(
"checks")).toArray();
441 for (
const QCborValue& val : checksArr) {
445 const QCborArray preArr = cbor.value(QStringLiteral(
"pre_results")).toArray();
446 for (
const QCborValue& val : preArr) {
450 const QCborArray postArr = cbor.value(QStringLiteral(
"post_results")).toArray();
451 for (
const QCborValue& val : postArr) {
455 if (cbor.contains(QStringLiteral(
"provenance"))) {
Verification, declarative checks, evaluation results and provenance snapshot attached to every MnaNod...
MNE Analysis Container Format (mna/mnx).
static MnaScript fromJson(const QJsonObject &json)
static MnaScript fromCbor(const QCborMap &cbor)
Verification check for a graph node.
QString severity
"error" (abort), "warning" (log + continue), "info" (always continue)
QString expression
Simple evaluable expression: "rank(covariance) > 0".
QString phase
"pre" (before execution) or "post" (after execution)
QString description
Human-readable: "Covariance matrix must be positive-definite".
static MnaVerificationCheck fromCbor(const QCborMap &cbor)
QString onFail
Optional remediation hint.
static MnaVerificationCheck fromJson(const QJsonObject &json)
QString id
Unique check identifier within the node (e.g. "cov_posdef").
QJsonObject toJson() const
static MnaVerificationResult fromCbor(const QCborMap &cbor)
QString message
Formatted message: "PASS: ..." or "FAIL [error]: ...".
QString checkId
References MnaVerificationCheck::id.
QVariant actualValue
The evaluated expression result.
QJsonObject toJson() const
QString severity
Echoed from the check definition.
QDateTime evaluatedAt
When this check was evaluated.
bool passed
true if the expression evaluated to true
static MnaVerificationResult fromJson(const QJsonObject &json)
Provenance record for reproducibility.
QJsonObject toJson() const
static MnaProvenance fromCbor(const QCborMap &cbor)
QString externalToolVersion
e.g. "FreeSurfer 7.4.1", "Python 3.11.5"
QString osInfo
e.g. "macOS 15.4 arm64"
qint64 peakMemoryBytes
Peak RSS (if measurable), 0 otherwise.
QString qtVersion
e.g. "6.11.0"
QString compilerInfo
e.g. "AppleClang 16.0.0"
qint64 wallTimeMs
Wall-clock duration in milliseconds.
QString hostName
Machine name (for cluster provenance).
QVariantMap resolvedAttributes
qint64 randomSeed
-1 if not applicable
QMap< QString, QString > inputHashes
portName → SHA-256
static MnaProvenance fromJson(const QJsonObject &json)
QString mneCppVersion
e.g. "2.2.0"
Verification, explanation, and provenance for a graph node.
MnaProvenance provenance
Complete provenance snapshot (populated by executor).
QString explanation
Human-readable explanation of what this node does and why.
static MnaVerification fromJson(const QJsonObject &json)
QList< MnaVerificationCheck > checks
Declarative checks (authored by user, evaluated by executor).
QJsonObject toJson() const
QList< MnaVerificationResult > preResults
Results of pre-execution checks (populated by executor).
QList< MnaVerificationResult > postResults
Results of post-execution checks (populated by executor).
static MnaVerification fromCbor(const QCborMap &cbor)