LT-305: Add sorting function to properly order Measurement Table
This commit is contained in:
parent
0b77a1783a
commit
d6a3172bb3
@ -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);
|
||||
};
|
||||
|
||||
@ -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];
|
||||
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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));
|
||||
});
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
Loading…
Reference in New Issue
Block a user