LT-92: Adding checks for measurements length

This commit is contained in:
Bruno Alves de Faria 2017-01-13 10:57:06 -02:00
parent a6cea542b7
commit e3b8dd001a
2 changed files with 80 additions and 24 deletions

View File

@ -11,23 +11,16 @@ export class RecistChecker extends BaseChecker {
constructor() {
super();
this.criterias.push(new MaxTargetsCriteria(5));
this.criterias.push(new MaxTargetPerOrganCriteria(2));
this.criterias.push(new MeasurementsLengthCriteria({}));
this.criterias.push(new ModalityCriteria(this.getModalityCriteriaOptions()));
this.criterias.push(new NonTargetResponseCriteria());
this.criterias.push(new TargetTypeCriteria());
}
const addCriteria = criteria => this.criterias.push(criteria);
check(data) {
const nonconformity = [];
this.criterias.forEach(criteria => {
const criteriaResult = criteria.check(data);
if (!criteriaResult.passed) {
nonconformity.push(criteriaResult);
}
});
return nonconformity;
addCriteria(new MaxTargetsCriteria(5));
addCriteria(new MaxTargetPerOrganCriteria(2));
addCriteria(new ModalityCriteria(this.getModalityCriteriaOptions()));
addCriteria(new NonTargetResponseCriteria());
addCriteria(new TargetTypeCriteria());
addCriteria(new MeasurementsLengthCriteria(this.getExtranodalLengthCriteriaOptions()));
addCriteria(new MeasurementsLengthCriteria(this.getExtranodalXrayLengthCriteriaOptions()));
addCriteria(new MeasurementsLengthCriteria(this.getNodalLengthCriteriaOptions()));
}
getModalityCriteriaOptions() {
@ -37,4 +30,37 @@ export class RecistChecker extends BaseChecker {
};
}
getExtranodalLengthCriteriaOptions() {
return {
longAxis: 10,
longAxisSliceThicknessMultiplier: 2,
modalityIn: ['CT', 'MR'],
locationNotIn: ['Lymph Node'],
message: 'Extranodal lesions must be >= 10mm long axis AND ' +
'>= double the acquisition slice thickness by CT and MR'
};
}
getExtranodalXrayLengthCriteriaOptions() {
return {
shortAxis: 20,
longAxis: 20,
modalityIn: ['PX', 'XA'],
locationNotIn: ['Lymph Node'],
message: 'Extranodal lesions must be >= 20mm on chest x-ray ' +
'(although x-rays rarely used for clinical trial assessment)'
};
}
getNodalLengthCriteriaOptions() {
return {
shortAxis: 15,
shortAxisSliceThicknessMultiplier: 2,
modalityIn: ['CT', 'MR'],
locationIn: ['Lymph Node'],
message: 'Nodal lesions must be >= 15mm short axis AND ' +
'>= double the acquisition slice thickness by CT and MR'
};
}
}

View File

@ -4,20 +4,50 @@ export class MeasurementsLengthCriteria extends BaseCriteria {
constructor(options) {
super();
options = {
shortAxis: 10,
longAxis: 10,
shortAxisSliceThicknessMultiplier: 2,
longAxisSliceThicknessMultiplier: 2,
modalitiesIn: ['CT', 'MR'],
locationNotIn: ['Lymph Node']
};
this.options = options;
}
check(data) {
let message;
let measurements = [];
const { options } = this;
const longMultiplier = options.longAxisSliceThicknessMultiplier;
const shortMultiplier = options.shortAxisSliceThicknessMultiplier;
data.targets.forEach(item => {
const { measurement, metadata } = item;
const { location, longestDiameter, shortestDiameter } = measurement;
const { sliceThickness } = metadata;
const modality = metadata.modality.toUpperCase();
// Stop here if the measurement does not match the modality and location filters
if (options.locationIn && options.locationIn.indexOf(location) === -1) return;
if (options.modalityIn && options.modalityIn.indexOf(modality) === -1) return;
if (options.locationNotIn && options.locationNotIn.indexOf(location) > -1) return;
if (options.modalityNotIn && options.modalityNotIn.indexOf(modality) > -1) return;
// Check the measurement length
const failed = (
(options.longAxis && longestDiameter < options.longAxis) ||
(options.shortAxis && shortestDiameter < options.shortAxis) || (
longMultiplier && !isNaN(sliceThickness) &&
longestDiameter < (longMultiplier * sliceThickness)
) || (
shortMultiplier && !isNaN(sliceThickness) &&
shortestDiameter < (shortMultiplier * sliceThickness)
)
);
// Mark this measurement as invalid if some of the checks have failed
if (failed) {
measurements.push(measurement);
}
});
// Use the options' message if some measurement is invalid
if (measurements.length) {
message = options.message;
}
return this.respond(message, measurements);
}