Added data persistence for lesion measurements and timepoints
This commit is contained in:
1 parent
1facbfb0b1
commit
0af0069d69
15 files changed
+157
-73
No files matched your search
@@ -0,0 +1,2 @@
|
||||
Timepoints = new Meteor.Collection('timepoints');
|
||||
Measurements = new Meteor.Collection('measurements');
|
||||
@@ -1,5 +1,4 @@
|
||||
var activeLesionMeasurementData;
|
||||
var timepointID;
|
||||
var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneTools) {
|
||||
|
||||
"use strict";
|
||||
@@ -40,7 +39,7 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
|
||||
var measurementData = createNewMeasurement(mouseEventData);
|
||||
|
||||
var eventData = {
|
||||
mouseButtonMask: mouseEventData.which,
|
||||
mouseButtonMask: mouseEventData.which
|
||||
};
|
||||
|
||||
// associate this data with this imageId so we can render it and manipulate it
|
||||
@@ -188,10 +187,6 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
|
||||
return;
|
||||
}
|
||||
|
||||
updateLesions(toolData, eventData);
|
||||
}
|
||||
|
||||
function updateLesions(toolData, eventData) {
|
||||
// we have tool data for this element - iterate over each one and draw it
|
||||
var context = eventData.canvasContext.canvas.getContext('2d');
|
||||
context.setTransform(1, 0, 0, 1, 0, 0);
|
||||
|
||||
@@ -9,6 +9,10 @@ var measurementManagerDAL = (function() {
|
||||
// Add timepoint data to Measurements collection
|
||||
function addTimepointData(lesionData) {
|
||||
var timepoints = Timepoints.find().fetch();
|
||||
|
||||
var study = cornerstoneTools.metaData.get('study', lesionData.imageId);
|
||||
var series = cornerstoneTools.metaData.get('study', lesionData.imageId);
|
||||
|
||||
var timepointsObject = {};
|
||||
|
||||
for (var i = 0; i < timepoints.length; i++) {
|
||||
@@ -17,10 +21,12 @@ var measurementManagerDAL = (function() {
|
||||
|
||||
var timepointObject;
|
||||
if (timepointId === lesionTimepointId) {
|
||||
// Add real mesurement
|
||||
// Add real measurement
|
||||
timepointObject = {
|
||||
longestDiameter: lesionData.measurementText,
|
||||
imageId: lesionData.imageId,
|
||||
studyInstanceUid: study.instanceUid,
|
||||
seriesInstanceUid: series.instanceUid
|
||||
};
|
||||
} else {
|
||||
// Add null measurement
|
||||
@@ -33,6 +39,7 @@ var measurementManagerDAL = (function() {
|
||||
}
|
||||
|
||||
var lesionDataObject = {
|
||||
patientId: timepoints[0].patientId,
|
||||
lesionUID: uuid.v4(),
|
||||
number: Measurements.find().count() + 1,
|
||||
lesionNumber: lesionData.lesionNumber,
|
||||
@@ -47,10 +54,10 @@ var measurementManagerDAL = (function() {
|
||||
// Update timepoint data in Measurements collection
|
||||
function updateTimepointData(lesionData) {
|
||||
// Find the specific lesion to be updated
|
||||
var measurement = Measurements.find({
|
||||
var measurement = Measurements.findOne({
|
||||
lesionNumber: lesionData.lesionNumber,
|
||||
isTarget: lesionData.isTarget
|
||||
}).fetch()[0];
|
||||
});
|
||||
|
||||
// If no such lesion exists, stop here
|
||||
if (!measurement) {
|
||||
@@ -65,10 +72,7 @@ var measurementManagerDAL = (function() {
|
||||
timepoints[timepointID].longestDiameter = lesionData.measurementText;
|
||||
timepoints[timepointID].imageId = lesionData.imageId;
|
||||
|
||||
Measurements.update({
|
||||
lesionNumber: lesionData.lesionNumber,
|
||||
isTarget: lesionData.isTarget
|
||||
}, {
|
||||
Measurements.update(measurement._id, {
|
||||
$set: {
|
||||
timepoints: timepoints
|
||||
}
|
||||
@@ -81,13 +85,14 @@ var measurementManagerDAL = (function() {
|
||||
lesionNumber: lesionData.lesionNumber,
|
||||
isTarget: lesionData.isTarget
|
||||
});
|
||||
|
||||
if (timepointData) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Adds new timepoint item to tiemepoints array
|
||||
// Adds new timepoint item to timepoints array
|
||||
function addLesionData(lesionData) {
|
||||
if (hasTimepointData(lesionData)) {
|
||||
// Update data
|
||||
@@ -115,6 +120,10 @@ var measurementManagerDAL = (function() {
|
||||
var measurement = measurements[i];
|
||||
var timepoints = measurement.timepoints;
|
||||
|
||||
if (!timepoints[timepointID]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (timepoints[timepointID].longestDiameter === '') {
|
||||
return measurement.lesionNumber;
|
||||
} else {
|
||||
@@ -130,10 +139,10 @@ var measurementManagerDAL = (function() {
|
||||
return;
|
||||
}
|
||||
|
||||
var measurement = Measurements.find({
|
||||
var measurement = Measurements.findOne({
|
||||
lesionNumber: lesionData.lesionNumber,
|
||||
isTarget: lesionData.isTarget
|
||||
}).fetch()[0];
|
||||
});
|
||||
|
||||
return measurement.locationUID;
|
||||
}
|
||||
|
||||
@@ -174,20 +174,6 @@ LesionLocations.insert({
|
||||
description: ""
|
||||
});
|
||||
|
||||
var lastAddedLesionData;
|
||||
|
||||
Template.lesionLocationDialog.onRendered(function() {
|
||||
// Observe Measurements Collection Changes
|
||||
Measurements.find().observe({
|
||||
added: function(lesionData) {
|
||||
lastAddedLesionData = lesionData;
|
||||
},
|
||||
changed: function(lesionData) {
|
||||
console.log("lesionData has changed!");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Template.lesionLocationDialog.helpers({
|
||||
'lesionLocations': function() {
|
||||
return LesionLocations.find();
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
Measurements = new Meteor.Collection(null);
|
||||
Timepoints = new Meteor.Collection(null);
|
||||
|
||||
// Activate selected lesions when lesion table row is clicked
|
||||
function updateLesions(e) {
|
||||
// lesionNumber of measurement = id of row
|
||||
var lesionNumber = parseInt($(e.currentTarget).attr("id"), 10);
|
||||
|
||||
// TODO= Clarify this
|
||||
var isTarget = $(e.currentTarget).find('td').eq(2).html().trim() === 'N'?false:true;
|
||||
|
||||
// Find data for specific lesion
|
||||
var measurementData = Measurements.find({
|
||||
var measurementData = Measurements.findOne({
|
||||
lesionNumber: lesionNumber,
|
||||
isTarget: isTarget
|
||||
}).fetch()[0];
|
||||
});
|
||||
|
||||
if (!measurementData) {
|
||||
return;
|
||||
}
|
||||
|
||||
var timepoints = measurementData.timepoints;
|
||||
|
||||
@@ -19,7 +22,14 @@ function updateLesions(e) {
|
||||
// Get the timepointID related to the image viewer viewport
|
||||
// from the DOM itself. This will be changed later when a
|
||||
// real association between viewports and timepoints is created.
|
||||
var timepointID = $(element).data('timepointID');
|
||||
var enabledElement = cornerstone.getEnabledElement(element);
|
||||
var study = cornerstoneTools.metaData.get('study', enabledElement.image.imageId);
|
||||
var timepoint = Timepoints.findOne({timepointName: study.date});
|
||||
if (!timepoint) {
|
||||
return;
|
||||
}
|
||||
var timepointID = timepoint.timepointID;
|
||||
|
||||
var timepointObject = timepoints[timepointID];
|
||||
|
||||
// Defines event data
|
||||
@@ -54,28 +64,6 @@ function updateLesions(e) {
|
||||
});
|
||||
}
|
||||
|
||||
Template.lesionTable.onRendered(function() {
|
||||
// Observe ViewerStudies Collection Changes
|
||||
// Note: This may not be the best place for this
|
||||
ViewerStudies.find().observe({
|
||||
added: function(study) {
|
||||
log.info('ViewerStudies added to');
|
||||
var timepointID = uuid.v4();
|
||||
|
||||
var timepoint = Timepoints.findOne({timepointName: study.studyDate});
|
||||
if (timepoint) {
|
||||
log.warn("A timepoint with that study date already exists!");
|
||||
return;
|
||||
}
|
||||
|
||||
Timepoints.insert({
|
||||
timepointID: timepointID,
|
||||
timepointName: study.studyDate
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Template.lesionTable.helpers({
|
||||
'measurement': function() {
|
||||
return Measurements.find();
|
||||
|
||||
@@ -2,6 +2,12 @@ Template.lesionTableTimepointCell.helpers({
|
||||
'longestDiameter': function() {
|
||||
// Search Measurements by lesion and timepoint
|
||||
var lesionData = Template.parentData(1);
|
||||
if (!lesionData ||
|
||||
!lesionData.timepoints ||
|
||||
!lesionData.timepoints[this.timepointID]) {
|
||||
return;
|
||||
}
|
||||
|
||||
return lesionData.timepoints[this.timepointID].longestDiameter;
|
||||
}
|
||||
});
|
||||
@@ -1,8 +1,16 @@
|
||||
// This event sets lesion number for new lesion
|
||||
|
||||
function setLesionNumberCallback(measurementData, eventData, doneCallback) {
|
||||
// Get the current element's timepointID from the study date metadata
|
||||
var element = eventData.element;
|
||||
var enabledElement = cornerstone.getEnabledElement(element);
|
||||
var study = cornerstoneTools.metaData.get('study', enabledElement.image.imageId);
|
||||
var timepoint = Timepoints.findOne({timepointName: study.date});
|
||||
if (!timepoint) {
|
||||
return;
|
||||
}
|
||||
measurementData.timepointID = timepoint.timepointID;
|
||||
|
||||
measurementData.timepointID = $(eventData.element).data('timepointID');
|
||||
// Get a lesion number for this lesion, depending on whether or not the same lesion previously
|
||||
// exists at a different timepoint
|
||||
var lesionNumber = measurementManagerDAL.getNewLesionNumber(measurementData.timepointID, isTarget=false);
|
||||
@@ -16,7 +24,7 @@ function setLesionNumberCallback(measurementData, eventData, doneCallback) {
|
||||
// If there already exists a lesion with this specific lesion number,
|
||||
// related to the chosen location.
|
||||
|
||||
function getNonTargetLesionLocationCallback(measurementData, eventData, doneCallback) {
|
||||
function getNonTargetLesionLocationCallback(measurementData, eventData) {
|
||||
|
||||
// Get the non-target lesion location dialog
|
||||
var nonTargetlesionDialog = $("#nonTargetLesionLocationDialog");
|
||||
|
||||
@@ -83,6 +83,27 @@ Template.studyDateList.events({
|
||||
// with the value True, and insert it into the ViewerStudies Collection
|
||||
study.selected = true;
|
||||
ViewerStudies.insert(study);
|
||||
|
||||
var timepointID = uuid.v4();
|
||||
|
||||
var timepoint = Timepoints.findOne({timepointName: study.studyDate});
|
||||
if (timepoint) {
|
||||
log.warn("A timepoint with that study date already exists!");
|
||||
return;
|
||||
}
|
||||
|
||||
var testTimepoint = Timepoints.findOne({});
|
||||
if (testTimepoint && testTimepoint.patientId !== study.patientId) {
|
||||
log.warn("Timepoints collection related to the wrong subject");
|
||||
return;
|
||||
}
|
||||
|
||||
log.info('Inserting a new timepoint');
|
||||
Timepoints.insert({
|
||||
patientId: study.patientId,
|
||||
timepointID: timepointID,
|
||||
timepointName: study.studyDate
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,3 @@
|
||||
// Create package logger using loglevel
|
||||
// https://atmospherejs.com/spacejamio/loglevel
|
||||
log = loglevel.createPackageLogger('lesiontracker', defaultLevel = 'info');
|
||||
@@ -10,10 +10,13 @@ Package.onUse(function (api) {
|
||||
api.use('standard-app-packages');
|
||||
api.use('jquery');
|
||||
api.use('stylus');
|
||||
api.use('practicalmeteor:loglevel');
|
||||
|
||||
// Our custom package
|
||||
api.use('cornerstone');
|
||||
|
||||
api.addFiles('log.js', ['client', 'server']);
|
||||
|
||||
api.addFiles('compatibility/lesionTool.js', 'client', {bare: true});
|
||||
api.addFiles('compatibility/nonTargetTool.js', 'client', {bare: true});
|
||||
api.addFiles('compatibility/measurementManagerDAL.js', 'client', {bare: true});
|
||||
@@ -43,14 +46,15 @@ Package.onUse(function (api) {
|
||||
api.addFiles('components/studyDateList/studyDateList.styl', 'client');
|
||||
api.addFiles('components/studyDateList/studyDateList.js', 'client');
|
||||
|
||||
// Server functions
|
||||
api.addFiles('server/collections.js', 'server');
|
||||
|
||||
|
||||
|
||||
// Both client and server functions
|
||||
api.addFiles('both/collections.js', ['client', 'server']);
|
||||
|
||||
// Library functions
|
||||
api.addFiles('lib/uuid.js', 'client');
|
||||
|
||||
api.export('Measurements', 'client');
|
||||
api.export('Timepoints', 'client');
|
||||
|
||||
api.export('Measurements', ['client', 'server']);
|
||||
api.export('Timepoints', ['client', 'server']);
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
Meteor.publish('timepoints', function(patientId) {
|
||||
console.log('Publish timepoints');
|
||||
console.log('patientId ' + patientId);
|
||||
return Timepoints.find({patientId: patientId});
|
||||
});
|
||||
|
||||
Meteor.publish('measurements', function(patientId) {
|
||||
console.log('Publish measurements');
|
||||
console.log('patientId ' + patientId);
|
||||
return Measurements.find({patientId: patientId});
|
||||
});
|
||||
|
||||
|
||||
// Temporary fix to drop all Collections on server restart
|
||||
// http://stackoverflow.com/questions/23891631/meteor-how-can-i-drop-all-mongo-collections-and-clear-all-data-on-startup
|
||||
Meteor.startup(function(){
|
||||
var globalObject=Meteor.isClient?window:global;
|
||||
for(var property in globalObject){
|
||||
var object=globalObject[property];
|
||||
if(object instanceof Meteor.Collection){
|
||||
object.remove({});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -190,7 +190,6 @@ function thumbnailDragEndHandler(e, target) {
|
||||
}
|
||||
|
||||
Template.thumbnailEntry.onRendered(function() {
|
||||
console.log(this.data);
|
||||
var entry = this.find('.thumbnailEntry');
|
||||
$(entry).data('seriesInstanceUid', Template.parentData(0).seriesInstanceUid);
|
||||
$(entry).data('studyInstanceUid', Template.parentData(1).studyInstanceUid);
|
||||
|
||||
Reference in new issue
Block a user