2020-09-10 23:20:58 +02:00
|
|
|
# QC definition file
|
|
|
|
|
|
2020-09-10 23:36:13 +02:00
|
|
|
-
|
|
|
|
|
name: "Missing shots"
|
|
|
|
|
iterate: "sequences"
|
2020-09-14 20:45:34 +02:00
|
|
|
labels: [ "QC" ]
|
2020-09-20 17:00:52 +02:00
|
|
|
id: missing_shots
|
2020-09-10 23:36:13 +02:00
|
|
|
check: |
|
|
|
|
|
const sequence = currentItem;
|
2022-03-09 21:25:47 +01:00
|
|
|
let results;
|
|
|
|
|
if (sequence.missing_shots) {
|
|
|
|
|
results = {
|
|
|
|
|
shots: {}
|
|
|
|
|
}
|
|
|
|
|
const missing_shots = missingShotpoints.filter(i => !i.ntba);
|
|
|
|
|
for (const shot of missing_shots) {
|
|
|
|
|
results.shots[shot.point] = { remarks: "Missed shot", labels: [ "QC", "QCAcq" ] };
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
results = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
results;
|
2020-09-10 23:36:13 +02:00
|
|
|
-
|
|
|
|
|
name: "Gun QC"
|
|
|
|
|
disabled: false
|
2020-09-14 20:45:34 +02:00
|
|
|
labels: [ "QC", "QCGuns" ]
|
2020-09-10 23:36:13 +02:00
|
|
|
children:
|
2021-05-07 14:04:48 +02:00
|
|
|
-
|
|
|
|
|
name: "Sequences without gun data"
|
|
|
|
|
iterate: "sequences"
|
|
|
|
|
id: seq_no_gun_data
|
|
|
|
|
check: |
|
2022-03-09 21:25:47 +01:00
|
|
|
shotpoints.some(i => i.meta?.raw?.smsrc) || "Sequence has no gun data"
|
2020-09-10 23:36:13 +02:00
|
|
|
-
|
|
|
|
|
name: "Missing gun data"
|
2020-09-20 17:00:52 +02:00
|
|
|
id: missing_gun_data
|
2022-03-09 21:25:47 +01:00
|
|
|
ignoreAllFailed: true
|
2020-09-10 23:36:13 +02:00
|
|
|
check: |
|
2022-03-09 21:25:47 +01:00
|
|
|
!!currentItem._("raw_meta.smsrc.guns")
|
|
|
|
|
? true
|
|
|
|
|
: "Missing gun data"
|
2020-09-12 19:17:14 +02:00
|
|
|
|
|
|
|
|
-
|
|
|
|
|
name: "No fire"
|
2020-09-20 17:00:52 +02:00
|
|
|
id: no_fire
|
2020-09-12 19:17:14 +02:00
|
|
|
check: |
|
|
|
|
|
const currentShot = currentItem;
|
|
|
|
|
const gunData = currentItem._("raw_meta.smsrc");
|
2022-04-30 16:13:12 +02:00
|
|
|
(gunData && gunData.guns && gunData.guns.length != gunData.num_active)
|
|
|
|
|
? `Source ${gunData.src_number}: No fire (${gunData.guns.length - gunData.num_active} guns)`
|
2020-09-12 19:17:14 +02:00
|
|
|
: true;
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
|
name: "Pressure errors"
|
2020-09-20 17:00:52 +02:00
|
|
|
id: pressure_errors
|
2020-09-12 19:17:14 +02:00
|
|
|
check: |
|
2020-09-12 19:54:01 +02:00
|
|
|
const pressure=11;
|
2020-09-12 19:17:14 +02:00
|
|
|
const gunData = currentItem._("raw_meta.smsrc");
|
2020-09-12 19:54:01 +02:00
|
|
|
const results = gunData &&
|
|
|
|
|
gunData
|
|
|
|
|
.guns
|
|
|
|
|
.filter(gun => ((gun[2] == gunData.src_number) && (gun[pressure]/parameters.gunPressureNominal - 1) > parameters.gunPressureToleranceRatio))
|
|
|
|
|
.map(gun =>
|
2022-04-30 17:37:38 +02:00
|
|
|
`source ${gun[2]}, string ${gun[0]}, gun ${gun[1]}, pressure: ${gun[pressure]} / ${parameters.gunPressureNominal} = ${(Math.abs(gun[pressure]/parameters.gunPressureNominal - 1)*100).toFixed(2)}% > ${(parameters.gunPressureToleranceRatio*100).toFixed(2)}%`
|
2022-03-09 21:25:47 +01:00
|
|
|
).join(" \n");
|
2020-09-12 19:54:01 +02:00
|
|
|
results && results.length
|
|
|
|
|
? results
|
|
|
|
|
: true
|
2020-09-12 19:17:14 +02:00
|
|
|
|
2020-09-10 23:36:13 +02:00
|
|
|
-
|
|
|
|
|
name: "Single gun / cluster"
|
|
|
|
|
children:
|
|
|
|
|
-
|
|
|
|
|
name: "Source depth"
|
2020-09-20 17:00:52 +02:00
|
|
|
id: source_depth
|
2020-09-10 23:36:13 +02:00
|
|
|
check: |
|
|
|
|
|
const currentShot = currentItem;
|
|
|
|
|
let _result_;
|
|
|
|
|
_depth=10;
|
|
|
|
|
const gunData = currentShot._("raw_meta.smsrc.guns");
|
|
|
|
|
if (!gunData) {
|
|
|
|
|
// We check for missing data elsewhere, so don't fail this test
|
|
|
|
|
_result_ = true
|
|
|
|
|
} else if (gunData.every(gun => Math.abs(gun[_depth]-parameters.gunDepth) <= parameters.gunDepthTolerance)) {
|
|
|
|
|
_result_ = true;
|
|
|
|
|
} else {
|
|
|
|
|
const bad_guns = gunData.filter(gun => Math.abs(gun[_depth]-parameters.gunDepth) > parameters.gunDepthTolerance).map(gun => {
|
|
|
|
|
return `source ${gun[2]}, string ${gun[0]}, gun ${gun[1]}, depth: ${gun[10]}`;
|
|
|
|
|
});
|
|
|
|
|
_result_ = `Depth error: ${bad_guns.join("; ")}`;
|
|
|
|
|
}
|
|
|
|
|
_result_
|
2020-09-12 19:17:14 +02:00
|
|
|
|
|
|
|
|
-
|
|
|
|
|
name: "Synchronisation (error)"
|
2020-09-20 17:00:52 +02:00
|
|
|
id: sync_error
|
2020-09-12 19:17:14 +02:00
|
|
|
check: |
|
|
|
|
|
const currentShot = currentItem;
|
|
|
|
|
const gunData = currentShot._("raw_meta.smsrc");
|
|
|
|
|
let result = [];
|
|
|
|
|
if (gunData && gunData.num_nofire == 0) {
|
|
|
|
|
|
|
|
|
|
// These are the indices into the gun array for the different
|
|
|
|
|
// values of interest.
|
|
|
|
|
const subarray = 0;
|
|
|
|
|
const aimpoint = 7;
|
|
|
|
|
const firetime = 8;
|
|
|
|
|
|
|
|
|
|
// We only care about the source which actually fired (or was supposed to)
|
|
|
|
|
const sourceFired = gunData.guns.filter(g => g[2] == gunData.src_number);
|
|
|
|
|
|
|
|
|
|
// Let us check if the average delta for each string is within spec
|
|
|
|
|
let subarrayAverages = [];
|
|
|
|
|
sourceFired.forEach(g => {
|
|
|
|
|
const idx = g[subarray]-1;
|
|
|
|
|
const delta = g[firetime]-g[aimpoint];
|
|
|
|
|
if (!subarrayAverages[idx]) {
|
|
|
|
|
subarrayAverages[idx] = [];
|
|
|
|
|
}
|
|
|
|
|
subarrayAverages[idx].push(delta);
|
|
|
|
|
});
|
|
|
|
|
subarrayAverages = subarrayAverages.map(s => s.reduce( (a, b) => a+b, 0 ) / s.length);
|
|
|
|
|
|
|
|
|
|
subarrayAverages.forEach((value, idx) => {
|
|
|
|
|
if (value > parameters.gunTimingSubarrayAverage) {
|
|
|
|
|
result.push(`Average delta error: string ${idx+1}: ${value.toFixed(2)} > ${parameters.gunTimingSubarrayAverage}`);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Let us see about individual guns
|
|
|
|
|
sourceFired
|
|
|
|
|
.filter(gun => Math.abs(gun[firetime]-gun[aimpoint]) > parameters.gunTiming)
|
|
|
|
|
.forEach(gun => {
|
|
|
|
|
const value = Math.abs(gun[firetime]-gun[aimpoint]);
|
|
|
|
|
result.push(`Delta error: source ${gun[2]}, string ${gun[0]}, gun ${gun[1]}: ${value.toFixed(2)} > ${parameters.gunTiming}`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if (result.length) {
|
|
|
|
|
result.join("; ");
|
|
|
|
|
} else {
|
|
|
|
|
// Either there were no error or gun data was missing, which we take care of elsewhere
|
|
|
|
|
true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-12 21:22:34 +02:00
|
|
|
-
|
|
|
|
|
name: "Synchronisation (warning)"
|
2020-09-20 17:00:52 +02:00
|
|
|
id: sync_warn
|
2020-09-12 21:22:34 +02:00
|
|
|
check: |
|
|
|
|
|
const currentShot = currentItem;
|
|
|
|
|
const gunData = currentShot._("raw_meta.smsrc");
|
|
|
|
|
let result = [];
|
|
|
|
|
if (gunData && gunData.num_nofire == 0) {
|
|
|
|
|
|
|
|
|
|
// These are the indices into the gun array for the different
|
|
|
|
|
// values of interest.
|
|
|
|
|
const subarray = 0;
|
|
|
|
|
const aimpoint = 7;
|
|
|
|
|
const firetime = 8;
|
|
|
|
|
|
|
|
|
|
// We only care about the source which actually fired (or was supposed to)
|
|
|
|
|
const sourceFired = gunData.guns.filter(g => g[2] == gunData.src_number);
|
|
|
|
|
|
|
|
|
|
sourceFired
|
|
|
|
|
.filter(gun => Math.abs(gun[firetime]-gun[aimpoint]) >= parameters.gunTimingWarning && Math.abs(gun[firetime]-gun[aimpoint]) <= parameters.gunTiming)
|
|
|
|
|
.forEach(gun => {
|
|
|
|
|
const value = Math.abs(gun[firetime]-gun[aimpoint]);
|
2022-05-03 17:27:34 +02:00
|
|
|
result.push(`Delta warning: source ${gun[2]}, string ${gun[0]}, gun ${gun[1]}: ${parameters.gunTimingWarning} ≤ ${value.toFixed(2)} ≤ ${parameters.gunTiming}`);
|
2020-09-12 21:22:34 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if (result.length) {
|
|
|
|
|
result.join("; ");
|
|
|
|
|
} else {
|
|
|
|
|
// Either there were no error or gun data was missing, which we take care of elsewhere
|
|
|
|
|
true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-10 23:36:13 +02:00
|
|
|
-
|
|
|
|
|
name: "Autofire"
|
2020-09-20 17:00:52 +02:00
|
|
|
id: autofire
|
2020-09-10 23:36:13 +02:00
|
|
|
check: |
|
|
|
|
|
const currentShot = currentItem;
|
|
|
|
|
let _result_;
|
|
|
|
|
_autofire=5;
|
|
|
|
|
const gunData = currentShot._("raw_meta.smsrc.guns");
|
|
|
|
|
if (!gunData) {
|
|
|
|
|
// We check for missing data elsewhere, so don't fail this test
|
|
|
|
|
_result_ = true;
|
|
|
|
|
} else if (gunData.every(gun => gun[_autofire] == false)) {
|
|
|
|
|
_result_ = true;
|
|
|
|
|
} else {
|
|
|
|
|
const bad_guns = gunData.filter(gun => gun[_autofire]).map(gun => {
|
|
|
|
|
return `source ${gun[2]}, string ${gun[0]}, gun ${gun[1]}, depth: ${gun[10]}`;
|
|
|
|
|
});
|
2020-09-12 19:17:14 +02:00
|
|
|
_result_ = `Depth error: ${bad_guns.join(";\n")}`;
|
2020-09-10 23:36:13 +02:00
|
|
|
}
|
|
|
|
|
_result_
|
2020-09-10 23:20:58 +02:00
|
|
|
|
2020-09-10 23:36:13 +02:00
|
|
|
-
|
|
|
|
|
name: "Centre of source preplot deviation (single shots)"
|
2020-09-14 20:45:34 +02:00
|
|
|
labels: [ "QC", "QCNav" ]
|
2020-09-10 23:36:13 +02:00
|
|
|
disabled: false
|
|
|
|
|
children:
|
|
|
|
|
-
|
|
|
|
|
name: "Crossline"
|
2020-09-20 17:00:52 +02:00
|
|
|
id: crossline
|
2020-09-10 23:36:13 +02:00
|
|
|
check: |
|
|
|
|
|
const currentShot = currentItem;
|
|
|
|
|
Math.abs(currentShot.error_i) <= parameters.crosslineError
|
2022-03-09 21:25:47 +01:00
|
|
|
|| `Crossline error (${currentShot.type}): ${currentShot.error_i.toFixed(2)} > ${parameters.crosslineError}`
|
2020-09-10 23:20:58 +02:00
|
|
|
|
2020-09-12 19:56:00 +02:00
|
|
|
-
|
|
|
|
|
name: "Inline"
|
2020-09-20 17:00:52 +02:00
|
|
|
id: inline
|
2020-09-12 19:56:00 +02:00
|
|
|
check: |
|
|
|
|
|
const currentShot = currentItem;
|
|
|
|
|
Math.abs(currentShot.error_j) <= parameters.inlineError
|
2022-03-09 21:25:47 +01:00
|
|
|
|| `Inline error (${currentShot.type}): ${currentShot.error_j.toFixed(2)} > ${parameters.inlineError}`
|
2020-09-12 19:56:00 +02:00
|
|
|
|
2020-09-10 23:36:13 +02:00
|
|
|
-
|
|
|
|
|
name: "Centre of source preplot deviation (moving average)"
|
2020-09-14 20:45:34 +02:00
|
|
|
labels: [ "QC", "QCNav" ]
|
2020-09-10 23:36:13 +02:00
|
|
|
children:
|
|
|
|
|
-
|
|
|
|
|
name: "Crossline"
|
|
|
|
|
iterate: "sequences"
|
|
|
|
|
parameters: [ "crosslineErrorAverage" ]
|
2020-09-20 17:00:52 +02:00
|
|
|
id: crossline_average
|
2020-09-10 23:36:13 +02:00
|
|
|
check: |
|
|
|
|
|
const currentSequence = currentItem;
|
2022-03-09 21:25:47 +01:00
|
|
|
//const i_err = shotpoints.filter(s => s.error_i != null).map(a => a.error_i);
|
|
|
|
|
const i_err = shotpoints.map(i =>
|
|
|
|
|
(i.errorfinal?.coordinates ?? i.errorraw?.coordinates)[0]
|
|
|
|
|
)
|
|
|
|
|
.filter(i => !isNaN(i));
|
|
|
|
|
|
2020-09-10 23:36:13 +02:00
|
|
|
if (i_err.length) {
|
|
|
|
|
const avg = i_err.reduce( (a, b) => a+b)/i_err.length;
|
|
|
|
|
avg <= parameters.crosslineErrorAverage ||
|
2022-03-09 21:25:47 +01:00
|
|
|
`Average crossline error: ${avg.toFixed(2)} > ${parameters.crosslineErrorAverage}`
|
2020-09-10 23:36:13 +02:00
|
|
|
} else {
|
|
|
|
|
`Sequence ${currentSequence.sequence} has no shots within preplot`
|
|
|
|
|
}
|
2020-09-10 23:20:58 +02:00
|
|
|
|
2020-09-10 23:36:13 +02:00
|
|
|
-
|
|
|
|
|
name: "Inline"
|
|
|
|
|
iterate: "sequences"
|
|
|
|
|
parameters: [ "inlineErrorRunningAverageShots" ]
|
2020-09-20 17:00:52 +02:00
|
|
|
id: inline_average
|
2020-09-10 23:36:13 +02:00
|
|
|
check: |
|
|
|
|
|
const currentSequence = currentItem;
|
|
|
|
|
const n = parameters.inlineErrorRunningAverageShots; // For brevity
|
2022-03-09 21:25:47 +01:00
|
|
|
const results = shotpoints.slice(n/2, -n/2).map( (shot, index) => {
|
|
|
|
|
const shots = shotpoints.slice(index, index+n).map(i =>
|
|
|
|
|
(i.errorfinal?.coordinates ?? i.errorraw?.coordinates)[1]
|
|
|
|
|
).filter(i => i !== null);
|
2020-09-10 23:36:13 +02:00
|
|
|
if (!shots.length) {
|
|
|
|
|
// We are outside the preplot
|
|
|
|
|
// Nothing to see here, move along
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
const mean = shots.reduce( (a, b) => a+b ) / shots.length;
|
2022-03-09 21:25:47 +01:00
|
|
|
return Math.abs(mean) <= parameters.inlineErrorRunningAverageValue || [
|
|
|
|
|
shot.point,
|
|
|
|
|
{
|
|
|
|
|
remarks: `Running average inline error: ${mean.toFixed(2)} > ${parameters.inlineErrorRunningAverageValue}`,
|
|
|
|
|
labels: [ "QC", "QCNav" ]
|
|
|
|
|
}
|
|
|
|
|
]
|
2020-09-10 23:36:13 +02:00
|
|
|
}).filter(i => i !== true);
|
|
|
|
|
|
|
|
|
|
results.length == 0 || results.join("\n");
|
2022-03-09 21:25:47 +01:00
|
|
|
results.length == 0 || {
|
|
|
|
|
remarks: "Sequence exceeds inline error running average limit",
|
|
|
|
|
shots: Object.fromEntries(results)
|
|
|
|
|
}
|