LT-334: Prevent Lesion Tracker dropping measurements when storing a new case. Removed test PET SUV application since it's unnecessary
This commit is contained in:
1 parent
d6a3172bb3
commit
3d29a7e299
41 files changed
+22
-1598
No files matched your search
@@ -20,13 +20,13 @@ export const retrieveMeasurements = (filter) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const storeMeasurements = (measurementData) => {
|
||||
export const storeMeasurements = (measurementData, timepointIds) => {
|
||||
console.log('storeMeasurements');
|
||||
|
||||
// Here is where we should do any required data transformation and API calls
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
Meteor.call('storeMeasurements', measurementData, (error, response) => {
|
||||
Meteor.call('storeMeasurements', measurementData, timepointIds, (error, response) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
|
||||
@@ -97,7 +97,7 @@ Meteor.methods({
|
||||
return Timepoints.find(filter || {}).fetch();
|
||||
},
|
||||
|
||||
storeMeasurements(measurementData) {
|
||||
storeMeasurements(measurementData, filter = {}) {
|
||||
OHIF.log.info('Storing Measurements on the Server');
|
||||
OHIF.log.info(JSON.stringify(measurementData, null, 2));
|
||||
|
||||
@@ -106,7 +106,7 @@ Meteor.methods({
|
||||
return;
|
||||
}
|
||||
|
||||
MeasurementCollections[toolId].remove({});
|
||||
MeasurementCollections[toolId].remove(filter);
|
||||
|
||||
const measurements = measurementData[toolId];
|
||||
measurements.forEach(measurement => {
|
||||
|
||||
@@ -58,7 +58,7 @@ class MeasurementApi {
|
||||
});
|
||||
}
|
||||
|
||||
storeMeasurements(timepointId) {
|
||||
storeMeasurements(timepoints) {
|
||||
const storeFn = configuration.dataExchange.store;
|
||||
if (!_.isFunction(storeFn)) {
|
||||
return;
|
||||
@@ -70,7 +70,16 @@ class MeasurementApi {
|
||||
measurementData[measurementTypeId] = this[measurementTypeId].find().fetch();
|
||||
});
|
||||
|
||||
storeFn(measurementData).then(() => {
|
||||
const timepointIds = timepoints.map(t => t.timepointId);
|
||||
const patientId = timepoints[0].patientId;
|
||||
const filter = {
|
||||
patientId,
|
||||
timepointId: {
|
||||
$in: timepointIds
|
||||
}
|
||||
};
|
||||
|
||||
storeFn(measurementData, filter).then(() => {
|
||||
OHIF.log.info('Measurement storage completed');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ Template.caseProgress.helpers({
|
||||
});
|
||||
|
||||
Template.caseProgress.events({
|
||||
'click .js-finish-case'(event) {
|
||||
'click .js-finish-case'(event, instance) {
|
||||
const $this = $(event.currentTarget);
|
||||
|
||||
// Stop here if the tool is disabled
|
||||
@@ -132,8 +132,12 @@ Template.caseProgress.events({
|
||||
return;
|
||||
}
|
||||
|
||||
const instance = Template.instance();
|
||||
switchToTab('studylistTab');
|
||||
instance.data.measurementApi.storeMeasurements();
|
||||
|
||||
const timepointApi = instance.data.timepointApi;
|
||||
const timepoints = timepointApi.all();
|
||||
OHIF.log.info('Saving Measurements for timepoints:')
|
||||
OHIF.log.info(timepoints);
|
||||
instance.data.measurementApi.storeMeasurements(timepoints);
|
||||
}
|
||||
});
|
||||
@@ -1,17 +0,0 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
import { measurementTools } from './measurementTools';
|
||||
import { retrieveMeasurements, storeMeasurements } from './dataExchange';
|
||||
import { validateMeasurements } from './dataValidation';
|
||||
|
||||
console.log('OHIF-PET SUV: Defining Configuration for Measurements');
|
||||
OHIF.measurements.MeasurementApi.setConfiguration({
|
||||
measurementTools: measurementTools,
|
||||
dataExchange: {
|
||||
retrieve: retrieveMeasurements,
|
||||
store: storeMeasurements
|
||||
},
|
||||
dataValidation: {
|
||||
validation: validateMeasurements
|
||||
}
|
||||
});
|
||||
@@ -1,37 +0,0 @@
|
||||
import { measurementTools } from './measurementTools';
|
||||
|
||||
export const retrieveMeasurements = () => {
|
||||
console.log('retrieveMeasurements');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
Meteor.call("retrieveMeasurements", (error, response) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
console.log(response);
|
||||
|
||||
/*measurementTools.forEach(tool => {
|
||||
console.log('Retrieving tool: ' + tool.id);
|
||||
});*/
|
||||
|
||||
resolve(response);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const storeMeasurements = (measurementData) => {
|
||||
console.log('storeMeasurements');
|
||||
|
||||
// Here is where we should do any required data transformation and API calls
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
Meteor.call("storeMeasurements", measurementData, (error, response) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(response);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
import { ellipse } from './ellipse';
|
||||
|
||||
export const validateMeasurements = () => {
|
||||
console.log('validateMeasurements');
|
||||
};
|
||||
@@ -1,103 +0,0 @@
|
||||
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
|
||||
import { MeasurementSchemaTypes } from 'meteor/ohif:measurements/both/schema/measurements';
|
||||
|
||||
const CornerstoneHandleSchema = MeasurementSchemaTypes.CornerstoneHandleSchema;
|
||||
|
||||
const EllipseHandlesSchema = new SimpleSchema({
|
||||
start: {
|
||||
type: CornerstoneHandleSchema,
|
||||
label: 'Start'
|
||||
},
|
||||
end: {
|
||||
type: CornerstoneHandleSchema,
|
||||
label: 'End'
|
||||
},
|
||||
textBox: {
|
||||
type: CornerstoneHandleSchema,
|
||||
label: 'Text Box'
|
||||
},
|
||||
});
|
||||
|
||||
const MeanStdDevSchema = new SimpleSchema({
|
||||
count: {
|
||||
type: Number,
|
||||
label: 'Count'
|
||||
},
|
||||
mean: {
|
||||
type: Number,
|
||||
label: 'Mean',
|
||||
decimal: true
|
||||
},
|
||||
variance: {
|
||||
type: Number,
|
||||
label: 'Variance',
|
||||
decimal: true
|
||||
},
|
||||
stdDev: {
|
||||
type: Number,
|
||||
label: 'Variance',
|
||||
decimal: true
|
||||
}
|
||||
});
|
||||
|
||||
const MeanStdDevSUVSchema = new SimpleSchema({
|
||||
mean: {
|
||||
type: Number,
|
||||
label: 'Mean SUV',
|
||||
decimal: true
|
||||
},
|
||||
stdDev: {
|
||||
type: Number,
|
||||
label: 'St. Dev SUV',
|
||||
decimal: true
|
||||
}
|
||||
});
|
||||
|
||||
const EllipseSchema = new SimpleSchema([MeasurementSchemaTypes.CornerstoneToolMeasurement, {
|
||||
handles: {
|
||||
type: EllipseHandlesSchema,
|
||||
label: 'Handles'
|
||||
},
|
||||
meanStdDev: {
|
||||
type: MeanStdDevSchema,
|
||||
label: 'Mean St.Dev',
|
||||
optional: true
|
||||
},
|
||||
meanStdDevSUV: {
|
||||
type: MeanStdDevSUVSchema,
|
||||
label: 'Mean St.Dev SUV',
|
||||
optional: true
|
||||
},
|
||||
area: {
|
||||
type: Number,
|
||||
decimal: true,
|
||||
optional: true
|
||||
}
|
||||
}]);
|
||||
|
||||
function numberWithCommas(x) {
|
||||
// http://stackoverflow.com/questions/2901102/how-to-print-a-number-with-commas-as-thousands-separators-in-javascript
|
||||
var parts = x.toString().split('.');
|
||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
return parts.join('.');
|
||||
}
|
||||
|
||||
function displayFunction(data) {
|
||||
if (!data.area ||
|
||||
!data.meanStdDev ||
|
||||
data.meanStdDev.mean === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
return numberWithCommas(data.meanStdDev.mean.toFixed(2));
|
||||
}
|
||||
|
||||
export const ellipse = {
|
||||
id: 'ellipse',
|
||||
name: 'Mean',
|
||||
cornerstoneToolType: 'ellipticalRoi',
|
||||
showInMeasurementTable: true,
|
||||
includeInCaseProgress: true,
|
||||
schema: EllipseSchema,
|
||||
displayFunction: displayFunction
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
import { ellipse } from './ellipse';
|
||||
|
||||
export const measurementTools = [
|
||||
ellipse
|
||||
];
|
||||
@@ -1,36 +0,0 @@
|
||||
Package.describe({
|
||||
name: 'ohif:petsuv',
|
||||
summary: 'OHIF PET SUV Measurement Tools',
|
||||
version: '0.0.1'
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
|
||||
api.use('ecmascript');
|
||||
api.use('standard-app-packages');
|
||||
api.use('jquery');
|
||||
api.use('stylus');
|
||||
api.use('random');
|
||||
|
||||
api.use('validatejs');
|
||||
|
||||
// Template overriding
|
||||
api.use('aldeed:template-extension@4.0.0');
|
||||
|
||||
// Our custom packages
|
||||
api.use('design');
|
||||
api.use('ohif:core');
|
||||
api.use('ohif:study-list');
|
||||
api.use('ohif:cornerstone');
|
||||
api.use('ohif:measurements');
|
||||
|
||||
api.addFiles('both/configuration/ellipse.js', [ 'client', 'server' ]);
|
||||
api.addFiles('both/configuration/measurementTools.js', [ 'client', 'server' ]);
|
||||
|
||||
api.addFiles('both/configuration/dataExchange.js', [ 'client', 'server' ]);
|
||||
api.addFiles('both/configuration/dataValidation.js', [ 'client', 'server' ]);
|
||||
api.addFiles('both/configuration/configuration.js', [ 'client', 'server' ]);
|
||||
|
||||
api.addFiles('server/methods.js', 'server');
|
||||
});
|
||||
@@ -1,65 +0,0 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { Mongo } from 'meteor/mongo';
|
||||
import { measurementTools } from 'meteor/ohif:petsuv/both/configuration/measurementTools';
|
||||
|
||||
let MeasurementCollections = {};
|
||||
measurementTools.forEach(tool => {
|
||||
MeasurementCollections[tool.id] = new Mongo.Collection(tool.id);
|
||||
});
|
||||
|
||||
|
||||
|
||||
Timepoints = new Mongo.Collection('timepoints');
|
||||
|
||||
// Drop our collections for testing purposes
|
||||
Meteor.startup(() => {
|
||||
Timepoints.remove({});
|
||||
measurementTools.forEach(tool => {
|
||||
MeasurementCollections[tool.id].remove({});
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
// TODO: Make storage use update instead of clearing the entire collection and
|
||||
// re-inserting everything.
|
||||
Meteor.methods({
|
||||
storeTimepoints(timepoints) {
|
||||
console.log('Storing Timepoints on the Server')
|
||||
console.log(JSON.stringify(timepoints, null, 2));
|
||||
Timepoints.remove({});
|
||||
timepoints.forEach(timepoint => {
|
||||
delete timepoint._id;
|
||||
Timepoints.insert(timepoint);
|
||||
});
|
||||
},
|
||||
|
||||
retrieveTimepoints() {
|
||||
console.log('Retrieving Timepoints from the Server');
|
||||
return Timepoints.find().fetch();
|
||||
},
|
||||
|
||||
storeMeasurements(measurementData) {
|
||||
console.log('Storing Measurements on the Server')
|
||||
console.log(JSON.stringify(measurementData, null, 2));
|
||||
|
||||
Object.keys(measurementData).forEach(toolId => {
|
||||
MeasurementCollections[toolId].remove({});
|
||||
|
||||
const measurements = measurementData[toolId];
|
||||
measurements.forEach(measurement => {
|
||||
MeasurementCollections[toolId].insert(measurement);
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
retrieveMeasurements() {
|
||||
console.log('Retrieving Measurements from the Server');
|
||||
let measurementData = {};
|
||||
|
||||
measurementTools.forEach(tool => {
|
||||
measurementData[tool.id] = MeasurementCollections[tool.id].find().fetch();
|
||||
});
|
||||
|
||||
return measurementData;
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user