LT-92: Integrating RECIST and measurements table

This commit is contained in:
Leonardo Campos 2017-01-16 21:20:24 -02:00 committed by Bruno Alves de Faria
parent 7ef0dd812b
commit 1efe611497
7 changed files with 47 additions and 16 deletions

View File

@ -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);

View File

@ -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}}

View File

@ -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');

View File

@ -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)}}

View File

@ -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) {

View File

@ -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;
} }
} }

View File

@ -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
}; };