LT-92: Integrating RECIST and measurements table
This commit is contained in:
parent
7ef0dd812b
commit
1efe611497
@ -101,10 +101,13 @@ Template.viewer.onCreated(() => {
|
|||||||
|
|
||||||
const timepointIds = timepoints.map(t => t.timepointId);
|
const timepointIds = timepoints.map(t => t.timepointId);
|
||||||
instance.data.measurementApi = new OHIF.measurements.MeasurementApi(instance.data.timepointApi);
|
instance.data.measurementApi = new OHIF.measurements.MeasurementApi(instance.data.timepointApi);
|
||||||
|
instance.data.conformanceCriteria = new OHIF.measurements.ConformanceCriteria(instance.data.measurementApi, instance.data.timepointApi);
|
||||||
|
|
||||||
console.warn('>>>>REMOVE THE LINES BELOW');
|
console.warn('>>>>REMOVE THE LINES BELOW');
|
||||||
window.measurementApi = instance.data.measurementApi;
|
window.measurementApi = instance.data.measurementApi;
|
||||||
window.timepointApi = instance.data.timepointApi;
|
window.timepointApi = instance.data.timepointApi;
|
||||||
window.conformanceCriteria = new OHIF.measurements.ConformanceCriteria(window.measurementApi, instance.data.timepointApi);
|
window.conformanceCriteria = instance.data.conformanceCriteria;
|
||||||
|
|
||||||
const measurementsPromise = instance.data.measurementApi.retrieveMeasurements(patientId, timepointIds);
|
const measurementsPromise = instance.data.measurementApi.retrieveMeasurements(patientId, timepointIds);
|
||||||
measurementsPromise.then(() => {
|
measurementsPromise.then(() => {
|
||||||
Session.set('MeasurementsReady', true);
|
Session.set('MeasurementsReady', true);
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
<template name="measurementTableRow">
|
<template name="measurementTableRow">
|
||||||
<div class="measurementTableRow {{#unless rowItem.location}}warning{{/unless}}{{#if responseStatus}}response-status{{/if}}" data-measurementid="{{_id}}">
|
<div class="measurementTableRow {{#if hasWarnings}}warning{{/if}}{{#if responseStatus}}response-status{{/if}}" data-measurementid="{{_id}}">
|
||||||
<div class='measurementRowSidebar'>
|
<div class='measurementRowSidebar'>
|
||||||
<div class="measurementNumber">
|
<div class="measurementNumber">
|
||||||
{{rowItem.measurementNumber}}
|
{{rowItem.measurementNumber}}
|
||||||
</div>
|
</div>
|
||||||
{{#unless rowItem.location}}
|
{{#if hasWarnings}}
|
||||||
<div class="warning-icon">
|
<div class="warning-icon">
|
||||||
<svg>
|
<svg>
|
||||||
<use xlink:href={{absoluteUrl "packages/ohif_viewerbase/assets/icons.svg#icon-ui-warning"}}></use>
|
<use xlink:href={{absoluteUrl "packages/ohif_viewerbase/assets/icons.svg#icon-ui-warning"}}></use>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
{{/unless}}
|
{{/if}}
|
||||||
{{#if rowItem.responseStatus}}
|
{{#if rowItem.responseStatus}}
|
||||||
<div class="response-status-icon">
|
<div class="response-status-icon">
|
||||||
{{rowItem.responseStatus}}
|
{{rowItem.responseStatus}}
|
||||||
|
|||||||
@ -22,6 +22,26 @@ const keys = {
|
|||||||
DELETE: 46
|
DELETE: 46
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Template.measurementTableRow.helpers({
|
||||||
|
hasWarnings() {
|
||||||
|
const toolsGroupsMap = this.measurementApi.toolsGroupsMap;
|
||||||
|
const nonConformities = this.conformanceCriteria.nonConformities.get();
|
||||||
|
const foundNonConformity = _.find(nonConformities, nonConformity => {
|
||||||
|
const measurement = _.find(nonConformity.measurements, measurement => {
|
||||||
|
if(toolsGroupsMap[measurement.toolType] !== this.rowItem.measurementTypeId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return measurement.measurementNumber === parseInt(this.rowItem.measurementNumber, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
return !!measurement;
|
||||||
|
});
|
||||||
|
|
||||||
|
return !!foundNonConformity;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Template.measurementTableRow.events({
|
Template.measurementTableRow.events({
|
||||||
'click .measurementRowSidebar'(event, instance) {
|
'click .measurementRowSidebar'(event, instance) {
|
||||||
const $row = instance.$('.measurementTableRow');
|
const $row = instance.$('.measurementTableRow');
|
||||||
|
|||||||
@ -9,7 +9,8 @@
|
|||||||
measurements=collection
|
measurements=collection
|
||||||
currentTimepointId=currentTimepointId
|
currentTimepointId=currentTimepointId
|
||||||
timepointApi=timepointApi
|
timepointApi=timepointApi
|
||||||
measurementApi=measurementApi}}
|
measurementApi=measurementApi
|
||||||
|
conformanceCriteria=conformanceCriteria}}
|
||||||
|
|
||||||
{{#each entry in collection}}
|
{{#each entry in collection}}
|
||||||
{{>measurementTableRow (clone this rowItem=entry)}}
|
{{>measurementTableRow (clone this rowItem=entry)}}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ class ConformanceCriteria {
|
|||||||
constructor(measurementApi, timepointApi) {
|
constructor(measurementApi, timepointApi) {
|
||||||
this.measurementApi = measurementApi;
|
this.measurementApi = measurementApi;
|
||||||
this.timepointApi = timepointApi;
|
this.timepointApi = timepointApi;
|
||||||
this.results = [];
|
this.nonConformities = new ReactiveVar();
|
||||||
|
|
||||||
const validate = _.debounce(trialCriteriaType => {
|
const validate = _.debounce(trialCriteriaType => {
|
||||||
this.validate(trialCriteriaType);
|
this.validate(trialCriteriaType);
|
||||||
@ -32,23 +32,23 @@ class ConformanceCriteria {
|
|||||||
const resultBoth = this.validateTimepoint('both', trialCriteriaType, mergedData);
|
const resultBoth = this.validateTimepoint('both', trialCriteriaType, mergedData);
|
||||||
const resultBaseline = this.validateTimepoint('baseline', trialCriteriaType, baselineData);
|
const resultBaseline = this.validateTimepoint('baseline', trialCriteriaType, baselineData);
|
||||||
const resultFollowup = this.validateTimepoint('followup', trialCriteriaType, followupData);
|
const resultFollowup = this.validateTimepoint('followup', trialCriteriaType, followupData);
|
||||||
const results = resultBaseline.concat(resultFollowup).concat(resultBoth);
|
const nonConformities = resultBaseline.concat(resultFollowup).concat(resultBoth);
|
||||||
|
|
||||||
console.warn('>>>> validate', results);
|
this.nonConformities.set(nonConformities);
|
||||||
|
|
||||||
return results;
|
return nonConformities;
|
||||||
}
|
}
|
||||||
|
|
||||||
validateTimepoint(timepointId, trialCriteriaType, data) {
|
validateTimepoint(timepointId, trialCriteriaType, data) {
|
||||||
const evaluators = this.getEvaluators(timepointId, trialCriteriaType);
|
const evaluators = this.getEvaluators(timepointId, trialCriteriaType);
|
||||||
let results = [];
|
let nonConformities = [];
|
||||||
|
|
||||||
evaluators.forEach(evaluator => {
|
evaluators.forEach(evaluator => {
|
||||||
const result = evaluator.evaluate(data);
|
const result = evaluator.evaluate(data);
|
||||||
results = results.concat(result);
|
nonConformities = nonConformities.concat(result);
|
||||||
});
|
});
|
||||||
|
|
||||||
return results;
|
return nonConformities;
|
||||||
}
|
}
|
||||||
|
|
||||||
getEvaluators(timepointId, trialCriteriaType) {
|
getEvaluators(timepointId, trialCriteriaType) {
|
||||||
|
|||||||
@ -25,6 +25,10 @@ export class CriteriaEvaluator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getCriteriaValidator() {
|
getCriteriaValidator() {
|
||||||
|
if(CriteriaEvaluator.criteriaValidator) {
|
||||||
|
return CriteriaEvaluator.criteriaValidator;
|
||||||
|
}
|
||||||
|
|
||||||
const schema = {
|
const schema = {
|
||||||
properties: {},
|
properties: {},
|
||||||
definitions: {}
|
definitions: {}
|
||||||
@ -50,18 +54,18 @@ export class CriteriaEvaluator {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return new Ajv().compile(schema);
|
return CriteriaEvaluator.criteriaValidator = new Ajv().compile(schema);
|
||||||
}
|
}
|
||||||
|
|
||||||
evaluate(data) {
|
evaluate(data) {
|
||||||
const nonconformity = [];
|
const nonConformities = [];
|
||||||
this.criteria.forEach(criterion => {
|
this.criteria.forEach(criterion => {
|
||||||
const criterionResult = criterion.evaluate(data);
|
const criterionResult = criterion.evaluate(data);
|
||||||
if (!criterionResult.passed) {
|
if (!criterionResult.passed) {
|
||||||
nonconformity.push(criterionResult);
|
nonConformities.push(criterionResult);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return nonconformity;
|
return nonConformities;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,8 +6,11 @@ export class BaseCriterion {
|
|||||||
|
|
||||||
generateResponse(message, measurements) {
|
generateResponse(message, measurements) {
|
||||||
const passed = !message;
|
const passed = !message;
|
||||||
|
const isGlobal = !measurements || !measurements.length;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
passed,
|
passed,
|
||||||
|
isGlobal,
|
||||||
message,
|
message,
|
||||||
measurements
|
measurements
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user