LT-305: Add sorting function to properly order Measurement Table

This commit is contained in:
Erik Ziegler 2016-11-15 15:02:38 +01:00
parent 0b77a1783a
commit d6a3172bb3
7 changed files with 150 additions and 25 deletions

View File

@ -8,6 +8,7 @@ Template.dialogNonTargetMeasurement.onCreated(() => {
const instance = Template.instance();
instance.measurementTypeId = 'nonTargets';
const timepointApi = instance.data.timepointApi;
instance.schema = new SimpleSchema({
location: FieldLesionLocation,
@ -16,10 +17,15 @@ Template.dialogNonTargetMeasurement.onCreated(() => {
// Remove the measurement from the collection
instance.removeMeasurement = () => {
instance.viewerData.measurementApi.deleteMeasurements(instance.measurementTypeId, {
const measurementApi = instance.viewerData.measurementApi;
measurementApi.deleteMeasurements(instance.measurementTypeId, {
_id: instance.data.measurementData._id
});
// Update the Overall Measurement Numbers for all Measurements
const baseline = timepointApi.baseline();
measurementApi.sortMeasurements(baseline.timepointId);
// Refresh the image with the measurement removed
cornerstone.updateImage(instance.data.element);
};

View File

@ -23,6 +23,7 @@ class MeasurementApi {
const measurementTypeId = tool.id;
this[measurementTypeId] = new Mongo.Collection(null);
this[measurementTypeId]._debugName = tool.name;
this[measurementTypeId].attachSchema(tool.schema);
});
}
@ -90,6 +91,110 @@ class MeasurementApi {
});
}
// TODO: Create a better function to combine hasDataAtTimepoint and hasNoDataAtTimepoint
// because this doesn't seem very elegant...
hasDataAtTimepoint(collection, timepointId) {
// Retrieve all the data for this Measurement type (e.g. 'targets')
// which was recorded at baseline.
const dataAtTimepoint = collection.find({timepointId});
// Obtain a list of the Measurement Numbers from the
// measurements which have data at this timepoint
const numbers = dataAtTimepoint.map(m => m.measurementNumber);
// Retrieve all the data for this Measurement type which
// match the Measurement Numbers obtained above
const filter = {
measurementNumber: {
$in: numbers
}
};
return collection.find(filter).fetch();
}
hasNoDataAtTimepoint(collection, timepointId) {
// Retrieve all the data for this Measurement type (e.g. 'targets')
// which was recorded at baseline.
const dataAtTimepoint = collection.find({timepointId});
// Obtain a list of the Measurement Numbers from the
// measurements which have data at this timepoint
const numbers = dataAtTimepoint.map(m => m.measurementNumber);
// Retrieve all the data for this Measurement type which
// match the Measurement Numbers obtained above
const filter = {
measurementNumber: {
$nin: numbers
}
};
return collection.find(filter).fetch();
}
sortMeasurements(baselineTimepointId) {
const tools = configuration.measurementTools;
const hasDataAtTimepoint = this.hasDataAtTimepoint;
const hasNoDataAtTimepoint = this.hasNoDataAtTimepoint;
const includedTools = tools.filter(tool => {
return (tool.options && tool.options.includeInCaseProgress === true);
});
let overallMeasurementNumber = 1;
// Given a Collection and a
const updateMeasurementNumberOverall = (collection, toolType) => {
return data => {
const filter = {
measurementNumber: data.measurementNumber,
toolType
}
collection.update(filter, {
$set: {
measurementNumberOverall: overallMeasurementNumber
}
});
// Increment the overall measurement number
overallMeasurementNumber += 1;
};
};
const summarizeMeasurement = (groupObject, toolType) => {
return key => {
return {
measurementNumber: parseInt(key, 10),
entries: groupObject[key],
toolType
};
};
};
// First, handle data that has a measurement at baseline
includedTools.forEach(tool => {
const collection = this[tool.id];
const toolType = tool.cornerstoneToolType;
const measurements = hasDataAtTimepoint(collection, baselineTimepointId);
const groupObject = _.groupBy(measurements, m => m.measurementNumber);
const sortedByMeasurementNumber = Object.keys(groupObject).map(summarizeMeasurement(groupObject, toolType));
sortedByMeasurementNumber.forEach(updateMeasurementNumberOverall(collection, toolType))
});
// Next, handle New Measurements (i.e. no baseline data)
// Note that this cannot be combined with the loop above due to the incrementing of the overallMeasurementNumber
includedTools.forEach(tool => {
const collection = this[tool.id];
const toolType = tool.cornerstoneToolType;
const measurements = hasNoDataAtTimepoint(collection, baselineTimepointId);
const groupObject = _.groupBy(measurements, m => m.measurementNumber);
const sortedByMeasurementNumber = Object.keys(groupObject).map(summarizeMeasurement(groupObject, toolType));
sortedByMeasurementNumber.forEach(updateMeasurementNumberOverall(collection, toolType));
});
}
deleteMeasurements(measurementTypeId, filter) {
const collection = this[measurementTypeId];

View File

@ -2,7 +2,7 @@
<div class="measurementTableRow {{#unless rowItem.location}}warning{{/unless}}{{#if responseStatus}}response-status{{/if}}" data-measurementid="{{_id}}">
<div class='measurementRowSidebar'>
<div class="measurementNumber">
{{rowItem.measurementNumber}}
{{rowItem.measurementNumberOverall}}
</div>
{{#unless rowItem.location}}
<div class="warning-icon">

View File

@ -58,14 +58,19 @@ Template.measurementTableRow.events({
const measurement = instance.data.rowItem.entries[0];
const toolType = measurement.toolType;
const measurementNumber = measurement.measurementNumber;
const api = instance.data.measurementApi;
const measurementApi = instance.data.measurementApi;
const timepointApi = instance.data.timepointApi;
// Remove all the measurements with the given type and number
api.deleteMeasurements(measurementTypeId, {
measurementApi.deleteMeasurements(measurementTypeId, {
toolType,
measurementNumber
});
// Update the Overall Measurement Numbers for all Measurements
const baseline = timepointApi.baseline();
measurementApi.sortMeasurements(baseline.timepointId);
// Repaint the images on all viewports without the removed measurements
_.each($('.imageViewerViewport'), element => cornerstone.updateImage(element));
});

View File

@ -53,13 +53,18 @@ Template.measurementTableView.helpers({
const groupObject = _.groupBy(data, entry => entry.measurementNumber);
// Reformat the data for display in the table
return Object.keys(groupObject).map(key => ({
measurementTypeId: measurementTypeId,
measurementNumber: key,
location: OHIF.measurements.getLocation(groupObject[key]),
responseStatus: false, // TODO: Get the latest timepoint and determine the response status
entries: groupObject[key]
}));
return Object.keys(groupObject).map(key => {
const anEntry = groupObject[key][0];
return {
measurementTypeId: measurementTypeId,
measurementNumber: key,
measurementNumberOverall: anEntry.measurementNumberOverall,
location: OHIF.measurements.getLocation(groupObject[key]),
responseStatus: false, // TODO: Get the latest timepoint and determine the response status
entries: groupObject[key]
};
});
},
newMeasurements(measurementType) {
@ -104,9 +109,12 @@ Template.measurementTableView.helpers({
// Reformat the data for display in the table
return Object.keys(groupObject).map(key => {
const anEntry = groupObject[key][0];
return {
measurementTypeId: measurementTypeId,
measurementNumber: key,
measurementNumberOverall: anEntry.measurementNumberOverall,
location: OHIF.measurements.getLocation(groupObject[key]),
responseStatus: false, // TODO: Get the latest timepoint and determine the response status
entries: groupObject[key]

View File

@ -5,8 +5,6 @@ import { OHIF } from 'meteor/ohif:core';
class MeasurementHandlers {
static onAdded(e, instance, eventData) {
const measurementData = eventData.measurementData;
const config = OHIF.measurements.MeasurementApi.getConfiguration();
const toolTypes = config.measurementTools.map(tool => tool.cornerstoneToolType);
@ -15,6 +13,7 @@ class MeasurementHandlers {
return;
}
const measurementData = eventData.measurementData;
const measurementToolConfiguration = config.measurementTools[index];
const measurementApi = instance.data.measurementApi;
const Collection = measurementApi[measurementToolConfiguration.id];
@ -56,9 +55,6 @@ class MeasurementHandlers {
const timepointId = timepoint.timepointId;
measurement.timepointId = timepointId;
measurement.measurementNumber = OHIF.measurements.MeasurementManager.getNewMeasurementNumber(timepointId, Collection, timepointApi);
// TODO: Fix this
measurement.measurementNumberAbsolute = measurement.measurementNumber;
}
} else {
const numCurrentMeasurementsInStudy = Collection.find({
@ -84,6 +80,10 @@ class MeasurementHandlers {
// Insert the new measurement into the collection
measurementData._id = Collection.insert(measurement);
// Update the Overall Measurement Numbers for all Measurements
const baseline = timepointApi.baseline();
measurementApi.sortMeasurements(baseline.timepointId);
}
static onModified(e, instance, eventData) {
@ -139,6 +139,10 @@ class MeasurementHandlers {
const Collection = measurementApi[measurementToolConfiguration.id];
Collection.remove(measurementData._id);
// Update the Overall Measurement Numbers for all Measurements
const baseline = timepointApi.baseline();
measurementApi.sortMeasurements(baseline.timepointId);
}
}

View File

@ -4,13 +4,10 @@ class MeasurementManager {
/**
* Returns new measurement number given a timepointId
* @param timepointId
* @param isTarget
* @returns {number} - Number of measurements in timepoint
*/
static getNewMeasurementNumber(timepointId, Collection, timepointApi) {
static getNewMeasurementNumber(timepointId, collection, timepointApi) {
// Get all current lesion measurements
const numMeasurements = Collection.find().count();
const numMeasurements = collection.find().count();
// If no measurements exist yet, start at 1
if (!numMeasurements) {
@ -21,7 +18,7 @@ class MeasurementManager {
timepointId: timepointId
});
const numMeasurementsAtTimepoint = Collection.find({
const numMeasurementsAtTimepoint = collection.find({
studyInstanceUid: {
$in: timepoint.studyInstanceUids
}
@ -36,8 +33,8 @@ class MeasurementManager {
* @param measurementData
* @returns {number} - Measurement location ID
*/
static getLocationIdIfMeasurementExists(measurementData, Collection) {
const measurement = Collection.findOne({
static getLocationIdIfMeasurementExists(measurementData, collection) {
const measurement = collection.findOne({
measurementNumber: measurementData.measurementNumber
});
@ -50,4 +47,4 @@ class MeasurementManager {
}
OHIF.measurements.MeasurementManager = MeasurementManager;
OHIF.measurements.MeasurementManager = MeasurementManager;