58 json[QStringLiteral(
"id")] =
id;
60 json[QStringLiteral(
"phase")] =
phase;
61 json[QStringLiteral(
"expression")] =
expression;
62 if (!
script.code.isEmpty()) {
63 json[QStringLiteral(
"script")] =
script.toJson();
65 json[QStringLiteral(
"severity")] =
severity;
67 json[QStringLiteral(
"on_fail")] =
onFail;
77 c.
id = json.value(QStringLiteral(
"id")).toString();
78 c.
description = json.value(QStringLiteral(
"description")).toString();
79 c.
phase = json.value(QStringLiteral(
"phase")).toString();
80 c.
expression = json.value(QStringLiteral(
"expression")).toString();
81 if (json.contains(QStringLiteral(
"script"))) {
84 c.
severity = json.value(QStringLiteral(
"severity")).toString();
85 c.
onFail = json.value(QStringLiteral(
"on_fail")).toString();
94 cbor.insert(QStringLiteral(
"id"),
id);
95 cbor.insert(QStringLiteral(
"description"),
description);
96 cbor.insert(QStringLiteral(
"phase"),
phase);
97 cbor.insert(QStringLiteral(
"expression"),
expression);
98 if (!
script.code.isEmpty()) {
99 cbor.insert(QStringLiteral(
"script"),
script.toCbor());
101 cbor.insert(QStringLiteral(
"severity"),
severity);
103 cbor.insert(QStringLiteral(
"on_fail"),
onFail);
113 c.
id = cbor.value(QStringLiteral(
"id")).toString();
114 c.
description = cbor.value(QStringLiteral(
"description")).toString();
115 c.
phase = cbor.value(QStringLiteral(
"phase")).toString();
116 c.
expression = cbor.value(QStringLiteral(
"expression")).toString();
117 if (cbor.contains(QStringLiteral(
"script"))) {
120 c.
severity = cbor.value(QStringLiteral(
"severity")).toString();
121 c.
onFail = cbor.value(QStringLiteral(
"on_fail")).toString();
132 json[QStringLiteral(
"check_id")] =
checkId;
133 json[QStringLiteral(
"passed")] =
passed;
134 json[QStringLiteral(
"severity")] =
severity;
135 json[QStringLiteral(
"message")] =
message;
136 json[QStringLiteral(
"actual_value")] = QJsonValue::fromVariant(
actualValue);
138 json[QStringLiteral(
"evaluated_at")] =
evaluatedAt.toString(Qt::ISODateWithMs);
148 r.
checkId = json.value(QStringLiteral(
"check_id")).toString();
149 r.
passed = json.value(QStringLiteral(
"passed")).toBool(
false);
150 r.
severity = json.value(QStringLiteral(
"severity")).toString();
151 r.
message = json.value(QStringLiteral(
"message")).toString();
152 r.
actualValue = json.value(QStringLiteral(
"actual_value")).toVariant();
153 r.
evaluatedAt = QDateTime::fromString(json.value(QStringLiteral(
"evaluated_at")).toString(), Qt::ISODateWithMs);
162 cbor.insert(QStringLiteral(
"check_id"),
checkId);
163 cbor.insert(QStringLiteral(
"passed"),
passed);
164 cbor.insert(QStringLiteral(
"severity"),
severity);
165 cbor.insert(QStringLiteral(
"message"),
message);
166 cbor.insert(QStringLiteral(
"actual_value"), QCborValue::fromVariant(
actualValue));
168 cbor.insert(QStringLiteral(
"evaluated_at"),
evaluatedAt.toString(Qt::ISODateWithMs));
178 r.
checkId = cbor.value(QStringLiteral(
"check_id")).toString();
179 r.
passed = cbor.value(QStringLiteral(
"passed")).toBool();
180 r.
severity = cbor.value(QStringLiteral(
"severity")).toString();
181 r.
message = cbor.value(QStringLiteral(
"message")).toString();
182 r.
actualValue = cbor.value(QStringLiteral(
"actual_value")).toVariant();
183 r.
evaluatedAt = QDateTime::fromString(cbor.value(QStringLiteral(
"evaluated_at")).toString(), Qt::ISODateWithMs);
198 hashObj.insert(it.key(), it.value());
200 json[QStringLiteral(
"input_hashes")] = hashObj;
206 attrObj.insert(it.key(), QJsonValue::fromVariant(it.value()));
208 json[QStringLiteral(
"resolved_attributes")] = attrObj;
214 if (!
osInfo.isEmpty()) json[QStringLiteral(
"os_info")] =
osInfo;
218 if (
startedAt.isValid()) json[QStringLiteral(
"started_at")] =
startedAt.toString(Qt::ISODateWithMs);
219 if (
finishedAt.isValid()) json[QStringLiteral(
"finished_at")] =
finishedAt.toString(Qt::ISODateWithMs);
233 const QJsonObject hashObj = json.value(QStringLiteral(
"input_hashes")).toObject();
234 for (
auto it = hashObj.constBegin(); it != hashObj.constEnd(); ++it) {
235 p.
inputHashes.insert(it.key(), it.value().toString());
238 const QJsonObject attrObj = json.value(QStringLiteral(
"resolved_attributes")).toObject();
239 for (
auto it = attrObj.constBegin(); it != attrObj.constEnd(); ++it) {
243 p.
mneCppVersion = json.value(QStringLiteral(
"mne_cpp_version")).toString();
244 p.
qtVersion = json.value(QStringLiteral(
"qt_version")).toString();
245 p.
compilerInfo = json.value(QStringLiteral(
"compiler_info")).toString();
246 p.
osInfo = json.value(QStringLiteral(
"os_info")).toString();
247 p.
hostName = json.value(QStringLiteral(
"host_name")).toString();
250 p.
startedAt = QDateTime::fromString(json.value(QStringLiteral(
"started_at")).toString(), Qt::ISODateWithMs);
251 p.
finishedAt = QDateTime::fromString(json.value(QStringLiteral(
"finished_at")).toString(), Qt::ISODateWithMs);
252 p.
wallTimeMs =
static_cast<qint64
>(json.value(QStringLiteral(
"wall_time_ms")).toDouble(0));
253 p.
peakMemoryBytes =
static_cast<qint64
>(json.value(QStringLiteral(
"peak_memory_bytes")).toDouble(0));
254 p.
randomSeed =
static_cast<qint64
>(json.value(QStringLiteral(
"random_seed")).toDouble(-1));
268 hashMap.insert(it.key(), it.value());
270 cbor.insert(QStringLiteral(
"input_hashes"), hashMap);
276 attrMap.insert(it.key(), QCborValue::fromVariant(it.value()));
278 cbor.insert(QStringLiteral(
"resolved_attributes"), attrMap);
284 if (!
osInfo.isEmpty()) cbor.insert(QStringLiteral(
"os_info"),
osInfo);
285 if (!
hostName.isEmpty()) cbor.insert(QStringLiteral(
"host_name"),
hostName);
288 if (
startedAt.isValid()) cbor.insert(QStringLiteral(
"started_at"),
startedAt.toString(Qt::ISODateWithMs));
289 if (
finishedAt.isValid()) cbor.insert(QStringLiteral(
"finished_at"),
finishedAt.toString(Qt::ISODateWithMs));
303 const QCborMap hashMap = cbor.value(QStringLiteral(
"input_hashes")).toMap();
304 for (
auto it = hashMap.constBegin(); it != hashMap.constEnd(); ++it) {
305 p.
inputHashes.insert(it.key().toString(), it.value().toString());
308 const QCborMap attrMap = cbor.value(QStringLiteral(
"resolved_attributes")).toMap();
309 for (
auto it = attrMap.constBegin(); it != attrMap.constEnd(); ++it) {
313 p.
mneCppVersion = cbor.value(QStringLiteral(
"mne_cpp_version")).toString();
314 p.
qtVersion = cbor.value(QStringLiteral(
"qt_version")).toString();
315 p.
compilerInfo = cbor.value(QStringLiteral(
"compiler_info")).toString();
316 p.
osInfo = cbor.value(QStringLiteral(
"os_info")).toString();
317 p.
hostName = cbor.value(QStringLiteral(
"host_name")).toString();
320 p.
startedAt = QDateTime::fromString(cbor.value(QStringLiteral(
"started_at")).toString(), Qt::ISODateWithMs);
321 p.
finishedAt = QDateTime::fromString(cbor.value(QStringLiteral(
"finished_at")).toString(), Qt::ISODateWithMs);
322 p.
wallTimeMs = cbor.value(QStringLiteral(
"wall_time_ms")).toInteger(0);
323 p.
peakMemoryBytes = cbor.value(QStringLiteral(
"peak_memory_bytes")).toInteger(0);
324 p.
randomSeed = cbor.value(QStringLiteral(
"random_seed")).toInteger(-1);
344 arr.append(c.toJson());
346 json[QStringLiteral(
"checks")] = arr;
352 arr.append(r.toJson());
354 json[QStringLiteral(
"pre_results")] = arr;
360 arr.append(r.toJson());
362 json[QStringLiteral(
"post_results")] = arr;
366 if (!provObj.isEmpty()) {
367 json[QStringLiteral(
"provenance")] = provObj;
379 v.
explanation = json.value(QStringLiteral(
"explanation")).toString();
381 const QJsonArray checksArr = json.value(QStringLiteral(
"checks")).toArray();
382 for (
const QJsonValue& val : checksArr) {
386 const QJsonArray preArr = json.value(QStringLiteral(
"pre_results")).toArray();
387 for (
const QJsonValue& val : preArr) {
391 const QJsonArray postArr = json.value(QStringLiteral(
"post_results")).toArray();
392 for (
const QJsonValue& val : postArr) {
396 if (json.contains(QStringLiteral(
"provenance"))) {
410 cbor.insert(QStringLiteral(
"explanation"),
explanation);
416 arr.append(c.toCbor());
418 cbor.insert(QStringLiteral(
"checks"), arr);
424 arr.append(r.toCbor());
426 cbor.insert(QStringLiteral(
"pre_results"), arr);
432 arr.append(r.toCbor());
434 cbor.insert(QStringLiteral(
"post_results"), arr);
438 if (!provMap.isEmpty()) {
439 cbor.insert(QStringLiteral(
"provenance"), provMap);
451 v.
explanation = cbor.value(QStringLiteral(
"explanation")).toString();
453 const QCborArray checksArr = cbor.value(QStringLiteral(
"checks")).toArray();
454 for (
const QCborValue& val : checksArr) {
458 const QCborArray preArr = cbor.value(QStringLiteral(
"pre_results")).toArray();
459 for (
const QCborValue& val : preArr) {
463 const QCborArray postArr = cbor.value(QStringLiteral(
"post_results")).toArray();
464 for (
const QCborValue& val : postArr) {
468 if (cbor.contains(QStringLiteral(
"provenance"))) {
MnaVerification, MnaVerificationCheck, MnaVerificationResult, MnaProvenance declarations.
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)