Move towards NPM for Cornerstone dependencies

This commit is contained in:
Erik Ziegler 2017-06-08 15:16:48 +02:00
parent 6c98c6a589
commit ddef3c4710
59 changed files with 2435 additions and 29162 deletions

View File

@ -14,3 +14,5 @@ notices-for-facebook-graph-api-2
1.3.5-remove-old-dev-bundle-link 1.3.5-remove-old-dev-bundle-link
1.4.0-remove-old-dev-bundle-link 1.4.0-remove-old-dev-bundle-link
1.4.1-add-shell-server-package 1.4.1-add-shell-server-package
1.4.3-split-account-service-packages
1.5-add-dynamic-import-package

View File

@ -6,16 +6,25 @@
npm-bcrypt@0.9.2 npm-bcrypt@0.9.2
meteor-base@1.0.4 # Packages every Meteor app needs to have meteor-base@1.1.0 # Packages every Meteor app needs to have
mobile-experience@1.0.4 # Packages for a great mobile UX mobile-experience@1.0.4 # Packages for a great mobile UX
mongo@1.1.14 # The database Meteor supports right now mongo@1.1.18 # The database Meteor supports right now
blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views
session@1.1.7 # Client-side reactive dictionary for your app session@1.1.7 # Client-side reactive dictionary for your app
jquery@1.11.10 # Helpful client-side library jquery@1.11.10 # Helpful client-side library
tracker@1.1.1 # Meteor's client-side reactive programming library tracker@1.1.3 # Meteor's client-side reactive programming library
standard-minifier-css
standard-minifier-js
http@1.2.12
promise@0.8.9
stylus@2.513.9
random@1.0.10
reactive-var@1.0.11
reactive-dict@1.1.9
check@1.2.5
email@1.2.1
es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers. es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers.
ecmascript@0.6.1 # Enable ECMAScript2015+ syntax in app code ecmascript@0.8.0 # Enable ECMAScript2015+ syntax in app code
clinical:active-entry clinical:active-entry
clinical:theming clinical:theming
@ -23,50 +32,44 @@ clinical:fonts
clinical:hipaa-audit-log clinical:hipaa-audit-log
clinical:hipaa-logger clinical:hipaa-logger
aldeed:simple-schema # Third party package to deal with schemas
# OHIF Packages # OHIF Packages
ohif:polyfill ohif:polyfill
ohif:design ohif:design
ohif:core ohif:core
ohif:user
ohif:header ohif:header
ohif:select-tree
ohif:cornerstone ohif:cornerstone
ohif:viewerbase ohif:viewerbase
ohif:study-list ohif:study-list
ohif:dicom-services ohif:dicom-services
ohif:hanging-protocols ohif:hanging-protocols
ohif:user-management
ohif:lesiontracker
ohif:metadata ohif:metadata
accounts-base@1.2.14 # Necessary for Lesion Trakcer
accounts-password@1.3.3 ohif:lesiontracker
ian:accounts-ui-bootstrap-3 ohif:user
twbs:bootstrap ohif:user-management
http@1.2.10 ohif:select-tree
arsnebula:reactive-promise
promise@0.8.8
stylus@2.513.8
fortawesome:fontawesome
random@1.0.10
reactive-var@1.0.11
reactive-dict@1.1.8
practicalmeteor:loglevel
momentjs:moment@2.15.1
anti:gagarin@=0.4.11 accounts-base@1.3.0
check@1.2.4 accounts-password@1.3.6
twbs:bootstrap
fortawesome:fontawesome
momentjs:moment@2.15.1
aldeed:simple-schema # Third party package to deal with schemas
aldeed:template-extension@4.0.0 aldeed:template-extension@4.0.0
aldeed:collection2
zuuk:stale-session zuuk:stale-session
<<<<<<< 3d081fe297551d37cd9691a7c60be1f743b9e600
email@1.1.18 email@1.1.18
peppelg:bootstrap-3-modal peppelg:bootstrap-3-modal
simple:reactive-method simple:reactive-method
fastclick@1.0.13 fastclick@1.0.13
standard-minifier-css@1.3.2 standard-minifier-css@1.3.2
standard-minifier-js@1.2.1 standard-minifier-js@1.2.1
=======
gilbertwat:bootstrap3-daterangepicker
>>>>>>> Move towards NPM for Cornerstone dependencies
johdirr:meteor-git-rev johdirr:meteor-git-rev
u2622:persistent-session@0.4.4 u2622:persistent-session@0.4.4
shell-server@0.2.1 shell-server@0.2.3
aldeed:collection2

View File

@ -1 +1 @@
METEOR@1.4.2.3 METEOR@1.5

View File

@ -1,5 +1,5 @@
accounts-base@1.2.14 accounts-base@1.3.0
accounts-password@1.3.3 accounts-password@1.3.6
aldeed:collection2@2.10.0 aldeed:collection2@2.10.0
aldeed:collection2-core@1.2.0 aldeed:collection2-core@1.2.0
aldeed:schema-deny@1.1.0 aldeed:schema-deny@1.1.0
@ -8,41 +8,44 @@ aldeed:simple-schema@1.5.3
aldeed:template-extension@4.0.0 aldeed:template-extension@4.0.0
allow-deny@1.0.5 allow-deny@1.0.5
amplify@1.0.0 amplify@1.0.0
anti:gagarin@0.4.11
anti:i18n@0.4.3
arsnebula:reactive-promise@0.9.1
autoupdate@1.3.12 autoupdate@1.3.12
babel-compiler@6.13.0 babel-compiler@6.19.1
babel-runtime@1.0.1 babel-runtime@1.0.1
base64@1.0.10 base64@1.0.10
binary-heap@1.0.10 binary-heap@1.0.10
blaze@2.2.0 blaze@2.3.2
blaze-html-templates@1.0.5 blaze-html-templates@1.0.5
blaze-tools@1.0.10 blaze-tools@1.0.10
boilerplate-generator@1.0.11 boilerplate-generator@1.1.0
caching-compiler@1.1.9 caching-compiler@1.1.9
caching-html-compiler@1.0.7 caching-html-compiler@1.0.7
callback-hook@1.0.10 callback-hook@1.0.10
check@1.2.4 check@1.2.5
clinical:active-entry@1.5.16 clinical:active-entry@1.5.16
clinical:auto-resizing@0.2.0 clinical:auto-resizing@0.2.0
clinical:fonts@1.1.4 clinical:fonts@1.1.4
clinical:hipaa-audit-log@2.4.2 clinical:hipaa-audit-log@2.4.2
clinical:hipaa-logger@1.0.1 clinical:hipaa-logger@1.0.1
clinical:theming@0.4.10 clinical:theming@0.4.10
<<<<<<< 3d081fe297551d37cd9691a7c60be1f743b9e600
coffeescript@1.11.1_4 coffeescript@1.11.1_4
dangrossman:bootstrap-daterangepicker@2.1.13 dangrossman:bootstrap-daterangepicker@2.1.13
=======
>>>>>>> Move towards NPM for Cornerstone dependencies
ddp@1.2.5 ddp@1.2.5
ddp-client@1.3.2 ddp-client@1.3.4
ddp-common@1.2.8 ddp-common@1.2.8
ddp-rate-limiter@1.0.6 ddp-rate-limiter@1.0.7
ddp-server@1.3.12 ddp-server@1.3.14
deps@1.0.12 deps@1.0.12
diff-sequence@1.0.7 diff-sequence@1.0.7
ecmascript@0.6.1 dynamic-import@0.1.0
ecmascript-runtime@0.3.15 ecmascript@0.8.0
ecmascript-runtime@0.4.1
ecmascript-runtime-client@0.4.1
ecmascript-runtime-server@0.4.1
ejson@1.0.13 ejson@1.0.13
email@1.1.18 email@1.2.1
es5-shim@4.6.15 es5-shim@4.6.15
fastclick@1.0.13 fastclick@1.0.13
fortawesome:fontawesome@4.7.0 fortawesome:fontawesome@4.7.0
@ -51,8 +54,7 @@ grove:less@0.2.0
hot-code-push@1.0.4 hot-code-push@1.0.4
html-tools@1.0.11 html-tools@1.0.11
htmljs@1.0.11 htmljs@1.0.11
http@1.2.10 http@1.2.12
ian:accounts-ui-bootstrap-3@1.2.89
id-map@1.0.9 id-map@1.0.9
iron:controller@1.0.12 iron:controller@1.0.12
iron:core@1.0.11 iron:core@1.0.11
@ -64,30 +66,35 @@ iron:router@1.0.13
iron:url@1.0.11 iron:url@1.0.11
johdirr:meteor-git-rev@0.0.4 johdirr:meteor-git-rev@0.0.4
jquery@1.11.10 jquery@1.11.10
launch-screen@1.1.0 launch-screen@1.1.1
livedata@1.0.18 livedata@1.0.18
localstorage@1.0.12 localstorage@1.1.0
logging@1.1.16 logging@1.1.17
mdg:validation-error@0.5.1 mdg:validation-error@0.5.1
meteor@1.6.0 meteor@1.6.1
meteor-base@1.0.4 meteor-base@1.1.0
meteor-platform@1.2.6 meteor-platform@1.2.6
minifier-css@1.2.15 minifier-css@1.2.16
minifier-js@1.2.15 minifier-js@2.1.0
minimongo@1.0.19 minimongo@1.2.0
mobile-experience@1.0.4 mobile-experience@1.0.4
mobile-status-bar@1.0.13 mobile-status-bar@1.0.14
modules@0.7.7 modules@0.9.0
modules-runtime@0.7.7 modules-runtime@0.8.0
momentjs:moment@2.16.0 momentjs:moment@2.16.0
mongo@1.1.14 mongo@1.1.18
mongo-id@1.0.6 mongo-id@1.0.6
mrt:moment@2.8.1 mrt:moment@2.8.1
natestrauser:select2@4.0.3 natestrauser:select2@4.0.3
npm-bcrypt@0.9.2 npm-bcrypt@0.9.2
<<<<<<< 3d081fe297551d37cd9691a7c60be1f743b9e600
npm-mongo@2.2.11_2 npm-mongo@2.2.11_2
observe-sequence@1.0.14 observe-sequence@1.0.14
ohif:commands@0.0.1 ohif:commands@0.0.1
=======
npm-mongo@2.2.24
observe-sequence@1.0.16
>>>>>>> Move towards NPM for Cornerstone dependencies
ohif:core@0.0.1 ohif:core@0.0.1
ohif:cornerstone@0.0.1 ohif:cornerstone@0.0.1
ohif:design@0.0.1 ohif:design@0.0.1
@ -109,14 +116,11 @@ ohif:user-management@0.0.1
ohif:viewerbase@0.0.1 ohif:viewerbase@0.0.1
ohif:wadoproxy@0.0.1 ohif:wadoproxy@0.0.1
ordered-dict@1.0.9 ordered-dict@1.0.9
peppelg:bootstrap-3-modal@1.0.4 promise@0.8.9
practicalmeteor:chai@2.1.0_1
practicalmeteor:loglevel@1.2.0_2
promise@0.8.8
raix:eventemitter@0.1.3 raix:eventemitter@0.1.3
random@1.0.10 random@1.0.10
rate-limit@1.0.6 rate-limit@1.0.8
reactive-dict@1.1.8 reactive-dict@1.1.9
reactive-var@1.0.11 reactive-var@1.0.11
reload@1.1.11 reload@1.1.11
retry@1.0.9 retry@1.0.9
@ -124,29 +128,28 @@ routepolicy@1.0.12
service-configuration@1.0.11 service-configuration@1.0.11
session@1.1.7 session@1.1.7
sha@1.0.9 sha@1.0.9
shell-server@0.2.1 shell-server@0.2.3
silentcicero:jszip@0.0.4 silentcicero:jszip@0.0.4
simple:reactive-method@1.0.2 spacebars@1.0.15
spacebars@1.0.13 spacebars-compiler@1.1.2
spacebars-compiler@1.0.13
srp@1.0.10 srp@1.0.10
standard-app-packages@1.0.9 standard-app-packages@1.0.9
standard-minifier-css@1.3.2 standard-minifier-css@1.3.4
standard-minifier-js@1.2.1 standard-minifier-js@2.1.0
stylus@2.513.8 stylus@2.513.9
templating@1.2.15 templating@1.2.15
templating-compiler@1.2.15 templating-compiler@1.2.15
templating-runtime@1.2.15 templating-runtime@1.2.15
templating-tools@1.0.5 templating-tools@1.1.1
tracker@1.1.1 tracker@1.1.3
twbs:bootstrap@3.3.6 twbs:bootstrap@3.3.6
typ:accounts-ldap@1.0.1 typ:accounts-ldap@1.0.1
typ:ldapjs@0.7.3 typ:ldapjs@0.7.3
u2622:persistent-session@0.4.4 u2622:persistent-session@0.4.4
ui@1.0.12 ui@1.0.13
underscore@1.0.10 underscore@1.0.10
url@1.0.11 url@1.1.0
validatejs@0.0.1 validatejs@0.0.1
webapp@1.3.12 webapp@1.3.16
webapp-hashing@1.0.9 webapp-hashing@1.0.9
zuuk:stale-session@1.0.8 zuuk:stale-session@1.0.8

View File

@ -1,3 +1,3 @@
// Create application logger using loglevel import loglevel from 'loglevel';
// https://atmospherejs.com/spacejamio/loglevel log = loglevel.getLogger('OHIFViewer');
log = loglevel.createAppLogger('LesionTracker', defaultLevel = 'info'); log.setLevel('info');

View File

@ -30,15 +30,21 @@ Router.route('/', function() {
Router.go('studylist', {}, { replaceState: true }); Router.go('studylist', {}, { replaceState: true });
}, { name: 'home' }); }, { name: 'home' });
Router.route('/studylist', function() { Router.route('/studylist', {
// Retrieve the timepoints data to display in studylist name: 'studylist',
const promise = OHIF.studylist.timepointApi.retrieveTimepoints({}).then(() => { onBeforeAction: function() {
this.render('app', { data: { template: 'studylist' } }); const next = this.next;
});
// Show loading state while preparing the studylist data // Retrieve the timepoints data to display in studylist
OHIF.ui.showDialog('dialogLoading', { promise }); const promise = OHIF.studylist.timepointApi.retrieveTimepoints({});
}, { name: 'studylist' }); promise.then(() => {
next()
});
},
render: function() {
this.render('app', { data: { template: 'studylist' } });
}
});
Router.route('/viewer/timepoints/:timepointId', function() { Router.route('/viewer/timepoints/:timepointId', function() {
const timepointId = this.params.timepointId; const timepointId = this.params.timepointId;

View File

@ -11,6 +11,7 @@
"dependencies": { "dependencies": {
"babel-runtime": "^6.20.0", "babel-runtime": "^6.20.0",
"bcrypt": "^0.8.7", "bcrypt": "^0.8.7",
"loglevel": "^1.4.1",
"meteor-node-stubs": "^0.2.3" "meteor-node-stubs": "^0.2.3"
}, },
"devDependencies": { "devDependencies": {

View File

@ -1,16 +0,0 @@
// 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(() => {
if (Meteor.settings.dropCollections === true) {
console.warn('Dropping all global Collections!');
Object.keys(global).forEach((key) => {
const object = global[key];
if (object instanceof Meteor.Collection) {
if (!(/^server|currentServer$/).test(object._name)) {
console.warn(`Dropping: ${object._debugName || object._name}`);
object.remove({});
}
}
});
}
});

View File

@ -14,3 +14,5 @@ notices-for-facebook-graph-api-2
1.3.5-remove-old-dev-bundle-link 1.3.5-remove-old-dev-bundle-link
1.4.0-remove-old-dev-bundle-link 1.4.0-remove-old-dev-bundle-link
1.4.1-add-shell-server-package 1.4.1-add-shell-server-package
1.4.3-split-account-service-packages
1.5-add-dynamic-import-package

View File

@ -4,6 +4,30 @@
# 'meteor add' and 'meteor remove' will edit this file for you, # 'meteor add' and 'meteor remove' will edit this file for you,
# but you can also edit it by hand. # but you can also edit it by hand.
http@1.2.12
promise@0.8.9
stylus@2.513.9
meteor-base@1.1.0
mobile-experience@1.0.4
mongo@1.1.18
blaze-html-templates@1.0.4
session@1.1.7
jquery@1.11.10
tracker@1.1.3
logging@1.1.17
reload@1.1.11
random@1.0.10
ejson@1.0.13
spacebars@1.0.12
check@1.2.5
ecmascript@0.8.0
es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers.
reactive-var@1.0.11
reactive-dict@1.1.9
standard-minifier-css@1.3.4
standard-minifier-js@2.1.0
# OHIF Packages # OHIF Packages
ohif:polyfill ohif:polyfill
ohif:design ohif:design
@ -16,39 +40,14 @@ ohif:viewerbase
ohif:study-list ohif:study-list
ohif:dicom-services ohif:dicom-services
ohif:hanging-protocols ohif:hanging-protocols
# ohif:user-management
ohif:metadata ohif:metadata
twbs:bootstrap twbs:bootstrap
http@1.2.10
arsnebula:reactive-promise
promise@0.8.8
stylus@2.513.8
fortawesome:fontawesome fortawesome:fontawesome
meteor-base@1.0.4 momentjs:moment@2.15.1
mobile-experience@1.0.4
mongo@1.1.14
blaze-html-templates@1.0.4
session@1.1.7
jquery@1.11.10
tracker@1.1.1
logging@1.1.16
reload@1.1.11
random@1.0.10
ejson@1.0.13
spacebars@1.0.12
check@1.2.4
aldeed:simple-schema # Third party package to deal with schemas aldeed:simple-schema # Third party package to deal with schemas
ecmascript@0.6.1 aldeed:template-extension
reactive-var@1.0.11 gilbertwat:bootstrap3-daterangepicker
practicalmeteor:loglevel
reactive-dict@1.1.8
fastclick@1.0.13
standard-minifier-css@1.3.2
standard-minifier-js@1.2.1
johdirr:meteor-git-rev johdirr:meteor-git-rev
u2622:persistent-session@0.4.4 u2622:persistent-session@0.4.4
aldeed:template-extension shell-server@0.2.3
peppelg:bootstrap-3-modal
shell-server@0.2.1

View File

@ -1 +1 @@
METEOR@1.4.2.3 METEOR@1.5

View File

@ -1,45 +1,52 @@
accounts-base@1.2.14 accounts-base@1.3.0
aldeed:collection2@2.10.0 aldeed:collection2@2.10.0
aldeed:collection2-core@1.2.0 aldeed:collection2-core@1.2.0
aldeed:schema-deny@1.1.0 aldeed:schema-deny@1.1.0
aldeed:schema-index@1.1.1 aldeed:schema-index@1.1.1
aldeed:simple-schema@1.5.3 aldeed:simple-schema@1.5.3
aldeed:template-extension@4.0.0 aldeed:template-extension@4.1.0
allow-deny@1.0.5 allow-deny@1.0.5
amplify@1.0.0 amplify@1.0.0
arsnebula:reactive-promise@0.9.1
autoupdate@1.3.12 autoupdate@1.3.12
babel-compiler@6.13.0 babel-compiler@6.19.2
babel-runtime@1.0.1 babel-runtime@1.0.1
base64@1.0.10 base64@1.0.10
binary-heap@1.0.10 binary-heap@1.0.10
blaze@2.2.0 blaze@2.3.2
blaze-html-templates@1.0.5 blaze-html-templates@1.1.2
blaze-tools@1.0.10 blaze-tools@1.0.10
boilerplate-generator@1.0.11 boilerplate-generator@1.1.0
caching-compiler@1.1.9 caching-compiler@1.1.9
caching-html-compiler@1.0.7 caching-html-compiler@1.1.2
callback-hook@1.0.10 callback-hook@1.0.10
<<<<<<< 3d081fe297551d37cd9691a7c60be1f743b9e600
check@1.2.4 check@1.2.4
coffeescript@1.11.1_4 coffeescript@1.11.1_4
dangrossman:bootstrap-daterangepicker@2.1.13 dangrossman:bootstrap-daterangepicker@2.1.13
=======
check@1.2.5
>>>>>>> Move towards NPM for Cornerstone dependencies
ddp@1.2.5 ddp@1.2.5
ddp-client@1.3.2 ddp-client@1.3.4
ddp-common@1.2.8 ddp-common@1.2.8
ddp-rate-limiter@1.0.6 ddp-rate-limiter@1.0.7
ddp-server@1.3.12 ddp-server@1.3.14
deps@1.0.12 deps@1.0.12
diff-sequence@1.0.7 diff-sequence@1.0.7
ecmascript@0.6.1 dynamic-import@0.1.1
ecmascript-runtime@0.3.15 ecmascript@0.8.0
ecmascript-runtime@0.4.1
ecmascript-runtime-client@0.4.2
ecmascript-runtime-server@0.4.1
ejson@1.0.13 ejson@1.0.13
es5-shim@4.6.15
fastclick@1.0.13 fastclick@1.0.13
fortawesome:fontawesome@4.7.0 fortawesome:fontawesome@4.7.0
geojson-utils@1.0.10 geojson-utils@1.0.10
hot-code-push@1.0.4 hot-code-push@1.0.4
html-tools@1.0.11 html-tools@1.0.11
htmljs@1.0.11 htmljs@1.0.11
http@1.2.10 http@1.2.12
id-map@1.0.9 id-map@1.0.9
iron:controller@1.0.12 iron:controller@1.0.12
iron:core@1.0.11 iron:core@1.0.11
@ -51,28 +58,33 @@ iron:router@1.0.13
iron:url@1.0.11 iron:url@1.0.11
johdirr:meteor-git-rev@0.0.4 johdirr:meteor-git-rev@0.0.4
jquery@1.11.10 jquery@1.11.10
launch-screen@1.1.0 launch-screen@1.1.1
livedata@1.0.18 livedata@1.0.18
localstorage@1.0.12 localstorage@1.1.0
logging@1.1.16 logging@1.1.17
mdg:validation-error@0.5.1 mdg:validation-error@0.5.1
meteor@1.6.0 meteor@1.6.1
meteor-base@1.0.4 meteor-base@1.1.0
meteor-platform@1.2.6 meteor-platform@1.2.6
minifier-css@1.2.15 minifier-css@1.2.16
minifier-js@1.2.15 minifier-js@2.1.0
minimongo@1.0.19 minimongo@1.2.1
mobile-experience@1.0.4 mobile-experience@1.0.4
mobile-status-bar@1.0.13 mobile-status-bar@1.0.14
modules@0.7.7 modules@0.9.1
modules-runtime@0.7.7 modules-runtime@0.8.0
momentjs:moment@2.16.0 momentjs:moment@2.16.0
mongo@1.1.14 mongo@1.1.18
mongo-id@1.0.6 mongo-id@1.0.6
natestrauser:select2@4.0.3 natestrauser:select2@4.0.3
<<<<<<< 3d081fe297551d37cd9691a7c60be1f743b9e600
npm-mongo@2.2.11_2 npm-mongo@2.2.11_2
observe-sequence@1.0.14 observe-sequence@1.0.14
ohif:commands@0.0.1 ohif:commands@0.0.1
=======
npm-mongo@2.2.24
observe-sequence@1.0.16
>>>>>>> Move towards NPM for Cornerstone dependencies
ohif:core@0.0.1 ohif:core@0.0.1
ohif:cornerstone@0.0.1 ohif:cornerstone@0.0.1
ohif:design@0.0.1 ohif:design@0.0.1
@ -89,38 +101,35 @@ ohif:themes-common@0.0.1
ohif:viewerbase@0.0.1 ohif:viewerbase@0.0.1
ohif:wadoproxy@0.0.1 ohif:wadoproxy@0.0.1
ordered-dict@1.0.9 ordered-dict@1.0.9
peppelg:bootstrap-3-modal@1.0.4 promise@0.8.9
practicalmeteor:chai@2.1.0_1
practicalmeteor:loglevel@1.2.0_2
promise@0.8.8
raix:eventemitter@0.1.3 raix:eventemitter@0.1.3
random@1.0.10 random@1.0.10
rate-limit@1.0.6 rate-limit@1.0.8
reactive-dict@1.1.8 reactive-dict@1.1.9
reactive-var@1.0.11 reactive-var@1.0.11
reload@1.1.11 reload@1.1.11
retry@1.0.9 retry@1.0.9
routepolicy@1.0.12 routepolicy@1.0.12
service-configuration@1.0.11 service-configuration@1.0.11
session@1.1.7 session@1.1.7
shell-server@0.2.1 shell-server@0.2.3
silentcicero:jszip@0.0.4 silentcicero:jszip@0.0.4
spacebars@1.0.13 spacebars@1.0.15
spacebars-compiler@1.0.13 spacebars-compiler@1.1.2
standard-app-packages@1.0.9 standard-app-packages@1.0.9
standard-minifier-css@1.3.2 standard-minifier-css@1.3.4
standard-minifier-js@1.2.1 standard-minifier-js@2.1.0
stylus@2.513.8 stylus@2.513.9
templating@1.2.15 templating@1.3.2
templating-compiler@1.2.15 templating-compiler@1.3.2
templating-runtime@1.2.15 templating-runtime@1.3.2
templating-tools@1.0.5 templating-tools@1.1.2
tracker@1.1.1 tracker@1.1.3
twbs:bootstrap@3.3.6 twbs:bootstrap@3.3.6
u2622:persistent-session@0.4.4 u2622:persistent-session@0.4.4
ui@1.0.12 ui@1.0.13
underscore@1.0.10 underscore@1.0.10
url@1.0.11 url@1.1.0
validatejs@0.0.1 validatejs@0.0.1
webapp@1.3.12 webapp@1.3.16
webapp-hashing@1.0.9 webapp-hashing@1.0.9

View File

@ -1,3 +1,3 @@
// Create application logger using loglevel import loglevel from 'loglevel';
// https://atmospherejs.com/spacejamio/loglevel log = loglevel.getLogger('OHIFViewer');
log = loglevel.createAppLogger('OHIFViewer', defaultLevel = 'info'); log.setLevel('info');

View File

@ -4,7 +4,8 @@
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {
"babel-runtime": "^6.22.0" "babel-runtime": "^6.22.0",
"loglevel": "^1.4.1"
}, },
"devDependencies": {}, "devDependencies": {},
"scripts": { "scripts": {

View File

@ -9,6 +9,6 @@ Template.dialogLoading.onRendered(() => {
$modal.modal({ $modal.modal({
backdrop: 'static', backdrop: 'static',
keyboard: false, keyboard: false,
modal: true show: true
}); });
}); });

View File

@ -8,7 +8,7 @@ Template.dialogSimple.onCreated(() => {
instance.close = () => { instance.close = () => {
const $modal = instance.$('.modal'); const $modal = instance.$('.modal');
$modal.on('hidden.bs.modal', () => instance.data.promiseResolve()).modal('hide'); $modal.one('hidden.bs.modal', () => instance.data.promiseResolve()).modal('hide');
}; };
// Automatically close the modal if a timeout value was given // Automatically close the modal if a timeout value was given

View File

@ -12,7 +12,7 @@ Template.unsavedChangesDialog.onRendered(function() {
const instance = Template.instance(); const instance = Template.instance();
const $modal = instance.$('.modal.unsavedChangesDialog'); const $modal = instance.$('.modal.unsavedChangesDialog');
// Routine which effectivelly displays the BS modal... // Routine which effectively displays the BS modal...
instance.displayModal = () => { instance.displayModal = () => {
// Make modal options extensible... // Make modal options extensible...
@ -22,7 +22,7 @@ Template.unsavedChangesDialog.onRendered(function() {
}, instance.data.modalOptions); }, instance.data.modalOptions);
// Set handler for "hidden" event... Simply remove the view! // Set handler for "hidden" event... Simply remove the view!
$modal.on('hidden.bs.modal', () => { $modal.one('hidden.bs.modal', () => {
Blaze.remove(instance.view); Blaze.remove(instance.view);
}); });

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
import { Cornerstone } from '../namespace'; import { OHIF } from '../namespace';
import { MetadataProvider } from './lib/classes/MetadataProvider'; import { MetadataProvider } from './lib/classes/MetadataProvider';
Cornerstone.metadataProvider = new MetadataProvider(); OHIF.cornerstone.metadataProvider = new MetadataProvider();

View File

@ -1,33 +0,0 @@
(function(factory) {
if (typeof define === 'function' && define.amd) {
define(['jquery', 'hammerjs'], factory);
} else if (typeof exports === 'object') {
factory(require('jquery'), require('hammerjs'));
} else {
factory(jQuery, Hammer);
}
}(function($, Hammer) {
function hammerify(el, options) {
var $el = $(el);
if(!$el.data("hammer")) {
$el.data("hammer", new Hammer($el[0], options));
}
}
$.fn.hammer = function(options) {
return this.each(function() {
hammerify(this, options);
});
};
// extend the emit method to also trigger jQuery events
Hammer.Manager.prototype.emit = (function(originalEmit) {
return function(type, data) {
originalEmit.call(this, type, data);
$(this.element).trigger({
type: type,
gesture: data
});
};
})(Hammer.Manager.prototype.emit);
}));

View File

@ -1,3 +1,4 @@
import * as cornerstoneMath from 'cornerstone-math';
import { parsingUtils } from '../parsingUtils'; import { parsingUtils } from '../parsingUtils';
const FUNCTION = 'function'; const FUNCTION = 'function';
@ -245,22 +246,17 @@ export class MetadataProvider {
} }
return { return {
frameOfReferenceUID: frameOfReferenceUID: instance.frameOfReferenceUID,
instance.frameOfReferenceUID, rows: instance.rows,
rows: columns: instance.columns,
instance.rows,
columns:
instance.columns,
rowCosines: rowCosines:
new cornerstoneMath.Vector3(parseFloat(imageOrientation[0]), parseFloat(imageOrientation[1]), parseFloat(imageOrientation[2])), new cornerstoneMath.Vector3(parseFloat(imageOrientation[0]), parseFloat(imageOrientation[1]), parseFloat(imageOrientation[2])),
columnCosines: columnCosines:
new cornerstoneMath.Vector3(parseFloat(imageOrientation[3]), parseFloat(imageOrientation[4]), parseFloat(imageOrientation[5])), new cornerstoneMath.Vector3(parseFloat(imageOrientation[3]), parseFloat(imageOrientation[4]), parseFloat(imageOrientation[5])),
imagePositionPatient: imagePositionPatient:
new cornerstoneMath.Vector3(parseFloat(imagePosition[0]), parseFloat(imagePosition[1]), parseFloat(imagePosition[2])), new cornerstoneMath.Vector3(parseFloat(imagePosition[0]), parseFloat(imagePosition[1]), parseFloat(imagePosition[2])),
rowPixelSpacing: rowPixelSpacing,
rowPixelSpacing, columnPixelSpacing,
columnPixelSpacing:
columnPixelSpacing,
}; };
} }
@ -318,7 +314,7 @@ export class MetadataProvider {
} }
/** /**
* Get a bound reference to the privider function. * Get a bound reference to the provider function.
*/ */
getProvider() { getProvider() {
let provider = this._provider; let provider = this._provider;

View File

@ -1,6 +1,4 @@
/** import * as dicomParser from 'dicom-parser';
* Globals: dicomParser
*/
/** /**
* A small set of utilities to help parsing DICOM element values. * A small set of utilities to help parsing DICOM element values.

View File

@ -2,7 +2,7 @@
* Import namespace... * Import namespace...
*/ */
import { OHIF, Cornerstone } from './namespace.js'; import { OHIF } from './namespace.js';
/** /**
* Import scripts that will populate the Cornerstone namespace as a side effect only import. This is effectively the public API... * Import scripts that will populate the Cornerstone namespace as a side effect only import. This is effectively the public API...
@ -10,4 +10,20 @@ import { OHIF, Cornerstone } from './namespace.js';
import './client/'; // which is actually: import './client/index.js'; import './client/'; // which is actually: import './client/index.js';
export { OHIF, Cornerstone }; import * as cornerstone from 'cornerstone-core';
import * as cornerstoneTools from 'cornerstone-tools';
import * as cornerstoneMath from 'cornerstone-math';
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';
import * as dicomParser from 'dicom-parser';
debugger;
export {
cornerstone,
cornerstoneTools,
cornerstoneMath,
cornerstoneWADOImageLoader,
dicomParser
};
export { OHIF };

View File

@ -22,4 +22,4 @@ OHIF.cornerstone = Cornerstone;
* Export relevant objects * Export relevant objects
*/ */
export { OHIF, Cornerstone }; export { OHIF };

View File

@ -4,45 +4,31 @@ Package.describe({
version: '0.0.1' version: '0.0.1'
}); });
Npm.depends({
'hammerjs': '2.0.8',
'jquery-hammerjs': '2.0.0',
'cornerstone-core': '0.11.0',
'cornerstone-tools': '0.8.9',
'cornerstone-math': '0.1.6',
'dicom-parser': '1.7.5',
'cornerstone-wado-image-loader': '0.14.6'
});
Package.onUse(function(api) { Package.onUse(function(api) {
api.versionsFrom('1.4'); api.versionsFrom('1.5');
api.use('ecmascript'); api.use('ecmascript');
api.use('jquery'); api.use('jquery');
api.use('ohif:core'); api.use('ohif:core');
api.addFiles('client/cornerstone.js', 'client', {
bare: true
});
api.addFiles('client/cornerstoneMath.js', 'client', {
bare: true
});
api.addFiles('client/cornerstoneTools.js', 'client', {
bare: true
});
api.addFiles('client/cornerstoneWADOImageLoader.js', 'client', {
bare: true
});
api.addFiles('client/dicomParser.js', 'client', {
bare: true
});
api.addFiles('client/hammer.js', 'client', {
bare: true
});
api.addFiles('client/jquery.hammer.js', 'client', {
bare: true
});
api.addAssets('public/js/cornerstoneWADOImageLoaderCodecs.es5.js', 'client'); api.addAssets('public/js/cornerstoneWADOImageLoaderCodecs.es5.js', 'client');
api.addAssets('public/js/cornerstoneWADOImageLoaderWebWorker.es5.js', 'client'); api.addAssets('public/js/cornerstoneWADOImageLoaderWebWorker.es5.js', 'client');
api.mainModule('main.js', 'client');
api.export('cornerstone', 'client'); api.export('cornerstone', 'client');
api.export('cornerstoneMath', 'client'); api.export('cornerstoneMath', 'client');
api.export('cornerstoneTools', 'client'); api.export('cornerstoneTools', 'client');
api.export('cornerstoneWADOImageLoader', 'client'); api.export('cornerstoneWADOImageLoader', 'client');
api.export('dicomParser', 'client'); api.export('dicomParser', 'client');
api.mainModule('main.js', 'client');
}); });

View File

@ -5,8 +5,6 @@ import { retrieveMeasurements, storeMeasurements, retrieveTimepoints, storeTimep
import { validateMeasurements } from './dataValidation'; import { validateMeasurements } from './dataValidation';
import { FieldLesionLocation, FieldLesionLocationResponse } from 'meteor/ohif:lesiontracker/both/schema/fields'; import { FieldLesionLocation, FieldLesionLocationResponse } from 'meteor/ohif:lesiontracker/both/schema/fields';
console.log('OHIF-LesionTracker: Defining Configuration for Measurements');
const newMeasurementTool = { const newMeasurementTool = {
id: 'newLesions', id: 'newLesions',
name: 'New Lesions' name: 'New Lesions'

View File

@ -1,417 +1,412 @@
import { OHIF } from 'meteor/ohif:core'; import { OHIF } from 'meteor/ohif:core';
import { Viewerbase } from 'meteor/ohif:viewerbase'; import { Viewerbase } from 'meteor/ohif:viewerbase';
(function($, cornerstone, cornerstoneMath, cornerstoneTools) { import { cornerstone, cornerstoneMath, cornerstoneTools } from 'meteor/ohif:cornerstone';
'use strict'; const toolType = 'nonTarget';
const toolType = 'nonTarget'; const toolDefaultStates = Viewerbase.toolManager.getToolDefaultStates();
const shadowConfig = toolDefaultStates.shadowConfig;
const textBoxConfig = toolDefaultStates.textBoxConfig;
const toolDefaultStates = Viewerbase.toolManager.getToolDefaultStates(); const configuration = {
const shadowConfig = toolDefaultStates.shadowConfig; getMeasurementLocationCallback,
const textBoxConfig = toolDefaultStates.textBoxConfig; changeMeasurementLocationCallback,
drawHandles: false,
drawHandlesOnHover: true,
arrowFirst: true,
textBox: textBoxConfig,
...shadowConfig,
};
const configuration = { // Used to cancel tool placement
getMeasurementLocationCallback: getMeasurementLocationCallback, const keys = {
changeMeasurementLocationCallback: changeMeasurementLocationCallback, ESC: 27
drawHandles: false, };
drawHandlesOnHover: true,
arrowFirst: true,
textBox: textBoxConfig,
...shadowConfig,
const getPosition = eventData => {
const event = eventData.event;
return {
x: event.clientX,
y: event.clientY
}; };
};
// Used to cancel tool placement // Define a callback to get your text annotation
const keys = { // This could be used, e.g. to open a modal
ESC: 27 function getMeasurementLocationCallback(measurementData, eventData) {
}; if (OHIF.lesiontracker.removeMeasurementIfInvalid(measurementData, eventData)) {
return;
const getPosition = eventData => {
const event = eventData.event;
return {
x: event.clientX,
y: event.clientY
};
};
// Define a callback to get your text annotation
// This could be used, e.g. to open a modal
function getMeasurementLocationCallback(measurementData, eventData) {
if (OHIF.lesiontracker.removeMeasurementIfInvalid(measurementData, eventData)) {
return;
}
delete measurementData.isCreating;
OHIF.ui.showDialog('dialogNonTargetMeasurement', {
position: getPosition(eventData),
title: 'Select Lesion Location',
element: eventData.element,
measurementData
});
} }
function changeMeasurementLocationCallback(measurementData, eventData) { delete measurementData.isCreating;
if (OHIF.lesiontracker.removeMeasurementIfInvalid(measurementData, eventData)) {
return;
}
OHIF.ui.showDialog('dialogNonTargetMeasurement', { OHIF.ui.showDialog('dialogNonTargetMeasurement', {
position: getPosition(eventData), position: getPosition(eventData),
title: 'Change Lesion Location', title: 'Select Lesion Location',
element: eventData.element, element: eventData.element,
measurementData, measurementData
edit: true });
}); }
function changeMeasurementLocationCallback(measurementData, eventData) {
if (OHIF.lesiontracker.removeMeasurementIfInvalid(measurementData, eventData)) {
return;
} }
/// --- Mouse Tool --- /// OHIF.ui.showDialog('dialogNonTargetMeasurement', {
///////// BEGIN ACTIVE TOOL /////// position: getPosition(eventData),
function addNewMeasurement(mouseEventData) { title: 'Change Lesion Location',
const element = mouseEventData.element; element: eventData.element,
measurementData,
edit: true
});
}
function doneCallback() { /// --- Mouse Tool --- ///
measurementData.active = true; ///////// BEGIN ACTIVE TOOL ///////
cornerstone.updateImage(element); function addNewMeasurement(mouseEventData) {
} const element = mouseEventData.element;
const measurementData = createNewMeasurement(mouseEventData);
measurementData.viewport = cornerstone.getViewport(element);
const eventData = {
mouseButtonMask: mouseEventData.which
};
const config = cornerstoneTools.nonTarget.getConfiguration();
// associate this data with this imageId so we can render it and manipulate it
cornerstoneTools.addToolState(mouseEventData.element, toolType, measurementData);
// since we are dragging to another place to drop the end point, we can just activate
// the end point and let the moveHandle move it for us.
$(element).off('CornerstoneToolsMouseMove', cornerstoneTools.nonTarget.mouseMoveCallback);
$(element).off('CornerstoneToolsMouseDown', cornerstoneTools.nonTarget.mouseDownCallback);
$(element).off('CornerstoneToolsMouseDownActivate', cornerstoneTools.nonTarget.mouseDownActivateCallback);
$(element).off('CornerstoneToolsMouseDoubleClick', doubleClickCallback);
// Add a flag for using Esc to cancel tool placement
let cancelled = false;
function cancelCallback(e) {
// If the Esc key was pressed, set the flag to true
if (e.which === keys.ESC) {
cancelled = true;
cornerstoneTools.removeToolState(mouseEventData.element, toolType, measurementData);
}
// Don't propagate this keydown event so it can't interfere
// with anything outside of this tool
return false;
}
// Bind a one-time event listener for the Esc key
$(element).one('keydown', cancelCallback);
function doneCallback() {
measurementData.active = true;
cornerstone.updateImage(element); cornerstone.updateImage(element);
cornerstoneTools.moveNewHandle(mouseEventData, toolType, measurementData, measurementData.handles.end, function() {
if (cancelled || cornerstoneTools.anyHandlesOutsideImage(mouseEventData, measurementData.handles)) {
// delete the measurement
cornerstoneTools.removeToolState(mouseEventData.element, toolType, measurementData);
} else {
config.getMeasurementLocationCallback(measurementData, mouseEventData, doneCallback);
}
// Unbind the Esc keydown hook
$(element).off('keydown', cancelCallback);
$(element).on('CornerstoneToolsMouseMove', eventData, cornerstoneTools.nonTarget.mouseMoveCallback);
$(element).on('CornerstoneToolsMouseDown', eventData, cornerstoneTools.nonTarget.mouseDownCallback);
$(element).on('CornerstoneToolsMouseDownActivate', eventData, cornerstoneTools.nonTarget.mouseDownActivateCallback);
$(element).on('CornerstoneToolsMouseDoubleClick', eventData, doubleClickCallback);
cornerstone.updateImage(mouseEventData.element);
});
} }
function createNewMeasurement(mouseEventData) { const measurementData = createNewMeasurement(mouseEventData);
var imageId = mouseEventData.image.imageId; measurementData.viewport = cornerstone.getViewport(element);
// Get studyInstanceUid const eventData = {
var study = cornerstoneTools.metaData.get('study', imageId); mouseButtonMask: mouseEventData.which
var studyInstanceUid = study.studyInstanceUid; };
var patientId = study.patientId;
// Get seriesInstanceUid const config = cornerstoneTools.nonTarget.getConfiguration();
var series = cornerstoneTools.metaData.get('series', imageId);
var seriesInstanceUid = series.seriesInstanceUid;
// create the measurement data for this tool with the end handle activated // associate this data with this imageId so we can render it and manipulate it
var measurementData = { cornerstoneTools.addToolState(mouseEventData.element, toolType, measurementData);
isCreating: true,
visible: true, // since we are dragging to another place to drop the end point, we can just activate
active: true, // the end point and let the moveHandle move it for us.
handles: { $(element).off('CornerstoneToolsMouseMove', cornerstoneTools.nonTarget.mouseMoveCallback);
start: { $(element).off('CornerstoneToolsMouseDown', cornerstoneTools.nonTarget.mouseDownCallback);
x: mouseEventData.currentPoints.image.x, $(element).off('CornerstoneToolsMouseDownActivate', cornerstoneTools.nonTarget.mouseDownActivateCallback);
y: mouseEventData.currentPoints.image.y, $(element).off('CornerstoneToolsMouseDoubleClick', doubleClickCallback);
allowedOutsideImage: true,
highlight: true, // Add a flag for using Esc to cancel tool placement
active: false let cancelled = false;
}, function cancelCallback(e) {
end: { // If the Esc key was pressed, set the flag to true
x: mouseEventData.currentPoints.image.x, if (e.which === keys.ESC) {
y: mouseEventData.currentPoints.image.y, cancelled = true;
allowedOutsideImage: true, cornerstoneTools.removeToolState(mouseEventData.element, toolType, measurementData);
highlight: true, }
active: false
}, // Don't propagate this keydown event so it can't interfere
textBox: { // with anything outside of this tool
x: mouseEventData.currentPoints.image.x - 50, return false;
y: mouseEventData.currentPoints.image.y - 50, }
active: false,
movesIndependently: false, // Bind a one-time event listener for the Esc key
drawnIndependently: true, $(element).one('keydown', cancelCallback);
allowedOutsideImage: true,
hasBoundingBox: true cornerstone.updateImage(element);
}
cornerstoneTools.moveNewHandle(mouseEventData, toolType, measurementData, measurementData.handles.end, function() {
if (cancelled || cornerstoneTools.anyHandlesOutsideImage(mouseEventData, measurementData.handles)) {
// delete the measurement
cornerstoneTools.removeToolState(mouseEventData.element, toolType, measurementData);
} else {
config.getMeasurementLocationCallback(measurementData, mouseEventData, doneCallback);
}
// Unbind the Esc keydown hook
$(element).off('keydown', cancelCallback);
$(element).on('CornerstoneToolsMouseMove', eventData, cornerstoneTools.nonTarget.mouseMoveCallback);
$(element).on('CornerstoneToolsMouseDown', eventData, cornerstoneTools.nonTarget.mouseDownCallback);
$(element).on('CornerstoneToolsMouseDownActivate', eventData, cornerstoneTools.nonTarget.mouseDownActivateCallback);
$(element).on('CornerstoneToolsMouseDoubleClick', eventData, doubleClickCallback);
cornerstone.updateImage(mouseEventData.element);
});
}
function createNewMeasurement(mouseEventData) {
var imageId = mouseEventData.image.imageId;
// Get studyInstanceUid
var study = cornerstoneTools.metaData.get('study', imageId);
var studyInstanceUid = study.studyInstanceUid;
var patientId = study.patientId;
// Get seriesInstanceUid
var series = cornerstoneTools.metaData.get('series', imageId);
var seriesInstanceUid = series.seriesInstanceUid;
// create the measurement data for this tool with the end handle activated
var measurementData = {
isCreating: true,
visible: true,
active: true,
handles: {
start: {
x: mouseEventData.currentPoints.image.x,
y: mouseEventData.currentPoints.image.y,
allowedOutsideImage: true,
highlight: true,
active: false
}, },
imageId: imageId, end: {
seriesInstanceUid: seriesInstanceUid, x: mouseEventData.currentPoints.image.x,
studyInstanceUid: studyInstanceUid, y: mouseEventData.currentPoints.image.y,
patientId: patientId, allowedOutsideImage: true,
response: '', highlight: true,
isTarget: false, active: false
toolType: 'nonTarget' },
}; textBox: {
x: mouseEventData.currentPoints.image.x - 50,
y: mouseEventData.currentPoints.image.y - 50,
active: false,
movesIndependently: false,
drawnIndependently: true,
allowedOutsideImage: true,
hasBoundingBox: true
}
},
imageId: imageId,
seriesInstanceUid: seriesInstanceUid,
studyInstanceUid: studyInstanceUid,
patientId: patientId,
response: '',
isTarget: false,
toolType: 'nonTarget'
};
return measurementData; return measurementData;
} }
///////// END ACTIVE TOOL /////// ///////// END ACTIVE TOOL ///////
function pointNearTool(element, data, coords) { function pointNearTool(element, data, coords) {
var lineSegment = { var lineSegment = {
start: cornerstone.pixelToCanvas(element, data.handles.start), start: cornerstone.pixelToCanvas(element, data.handles.start),
end: cornerstone.pixelToCanvas(element, data.handles.end) end: cornerstone.pixelToCanvas(element, data.handles.end)
}; };
var distanceToPoint = cornerstoneMath.lineSegment.distanceToPoint(lineSegment, coords); var distanceToPoint = cornerstoneMath.lineSegment.distanceToPoint(lineSegment, coords);
if (cornerstoneTools.pointInsideBoundingBox(data.handles.textBox, coords)) { if (cornerstoneTools.pointInsideBoundingBox(data.handles.textBox, coords)) {
return true; return true;
}
return distanceToPoint < 25;
} }
///////// BEGIN IMAGE RENDERING /////// return distanceToPoint < 25;
function onImageRendered(e, eventData) { }
var element = eventData.element;
// if we have no toolData for this element, return immediately as there is nothing to do ///////// BEGIN IMAGE RENDERING ///////
var toolData = cornerstoneTools.getToolState(element, toolType); function onImageRendered(e, eventData) {
if (!toolData) { var element = eventData.element;
return;
}
// we have tool data for this element - iterate over each one and draw it // if we have no toolData for this element, return immediately as there is nothing to do
var context = eventData.canvasContext.canvas.getContext('2d'); var toolData = cornerstoneTools.getToolState(element, toolType);
context.setTransform(1, 0, 0, 1, 0, 0); if (!toolData) {
return;
var color;
var lineWidth = cornerstoneTools.toolStyle.getToolWidth();
var config = cornerstoneTools.nonTarget.getConfiguration();
for (var i = 0; i < toolData.data.length; i++) {
var data = toolData.data[i];
context.save();
// configurable shadow from CornerstoneTools
if (config && config.shadow) {
context.shadowColor = config.shadowColor || '#000000';
context.shadowOffsetX = config.shadowOffsetX || 1;
context.shadowOffsetY = config.shadowOffsetY || 1;
}
if (data.active) {
color = cornerstoneTools.toolColors.getActiveColor();
} else {
color = cornerstoneTools.toolColors.getToolColor();
}
// Draw the arrow
var handleStartCanvas = cornerstone.pixelToCanvas(element, data.handles.start);
var handleEndCanvas = cornerstone.pixelToCanvas(element, data.handles.end);
var canvasTextLocation = cornerstone.pixelToCanvas(element, data.handles.textBox);
cornerstoneTools.drawArrow(context, handleEndCanvas, handleStartCanvas, color, lineWidth);
if (config.drawHandles) {
cornerstoneTools.drawHandles(context, eventData, data.handles, color);
} else if (config.drawHandlesOnHover && data.handles.start.active) {
cornerstoneTools.drawHandles(context, eventData, [ data.handles.start ], color);
} else if (config.drawHandlesOnHover && data.handles.end.active) {
cornerstoneTools.drawHandles(context, eventData, [ data.handles.end ], color);
}
// Draw the text
if (data.measurementNumber) {
var textLine = `Non-Target ${data.measurementNumber}`;
var boundingBox = cornerstoneTools.drawTextBox(context, textLine, canvasTextLocation.x, canvasTextLocation.y, color, config.textBox);
data.handles.textBox.boundingBox = boundingBox;
OHIF.cornerstone.repositionTextBox(eventData, data, config.textBox);
// Draw linked line as dashed
var link = {
start: {},
end: {}
};
var midpointCanvas = {
x: (handleStartCanvas.x + handleEndCanvas.x) / 2,
y: (handleStartCanvas.y + handleEndCanvas.y) / 2,
};
var points = [ handleStartCanvas, handleEndCanvas, midpointCanvas ];
link.end.x = canvasTextLocation.x;
link.end.y = canvasTextLocation.y;
link.start = cornerstoneMath.point.findClosestPoint(points, link.end);
var boundingBoxPoints = [ {
// Top middle point of bounding box
x: boundingBox.left + boundingBox.width / 2,
y: boundingBox.top
}, {
// Left middle point of bounding box
x: boundingBox.left,
y: boundingBox.top + boundingBox.height / 2
}, {
// Bottom middle point of bounding box
x: boundingBox.left + boundingBox.width / 2,
y: boundingBox.top + boundingBox.height
}, {
// Right middle point of bounding box
x: boundingBox.left + boundingBox.width,
y: boundingBox.top + boundingBox.height / 2
},
];
link.end = cornerstoneMath.point.findClosestPoint(boundingBoxPoints, link.start);
context.beginPath();
context.strokeStyle = color;
context.lineWidth = lineWidth;
context.setLineDash([ 2, 3 ]);
context.moveTo(link.start.x, link.start.y);
context.lineTo(link.end.x, link.end.y);
context.stroke();
}
context.restore();
}
} }
// ---- Touch tool ---- // 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);
///////// BEGIN ACTIVE TOOL /////// var color;
function addNewMeasurementTouch(touchEventData) { var lineWidth = cornerstoneTools.toolStyle.getToolWidth();
var element = touchEventData.element; var config = cornerstoneTools.nonTarget.getConfiguration();
function doneCallback() { for (var i = 0; i < toolData.data.length; i++) {
measurementData.active = true; var data = toolData.data[i];
cornerstone.updateImage(element);
context.save();
// configurable shadow from CornerstoneTools
if (config && config.shadow) {
context.shadowColor = config.shadowColor || '#000000';
context.shadowOffsetX = config.shadowOffsetX || 1;
context.shadowOffsetY = config.shadowOffsetY || 1;
} }
var measurementData = createNewMeasurement(touchEventData); if (data.active) {
cornerstoneTools.addToolState(element, toolType, measurementData); color = cornerstoneTools.toolColors.getActiveColor();
$(element).off('CornerstoneToolsTouchDrag', cornerstoneTools.nonTargetTouch.touchMoveHandle); } else {
$(element).off('CornerstoneToolsDragStartActive', cornerstoneTools.nonTargetTouch.touchDownActivateCallback); color = cornerstoneTools.toolColors.getToolColor();
$(element).off('CornerstoneToolsTap', cornerstoneTools.nonTargetTouch.tapCallback); }
var config = cornerstoneTools.nonTarget.getConfiguration();
// Draw the arrow
var handleStartCanvas = cornerstone.pixelToCanvas(element, data.handles.start);
var handleEndCanvas = cornerstone.pixelToCanvas(element, data.handles.end);
var canvasTextLocation = cornerstone.pixelToCanvas(element, data.handles.textBox);
cornerstoneTools.drawArrow(context, handleEndCanvas, handleStartCanvas, color, lineWidth);
if (config.drawHandles) {
cornerstoneTools.drawHandles(context, eventData, data.handles, color);
} else if (config.drawHandlesOnHover && data.handles.start.active) {
cornerstoneTools.drawHandles(context, eventData, [ data.handles.start ], color);
} else if (config.drawHandlesOnHover && data.handles.end.active) {
cornerstoneTools.drawHandles(context, eventData, [ data.handles.end ], color);
}
// Draw the text
if (data.measurementNumber) {
var textLine = `Non-Target ${data.measurementNumber}`;
var boundingBox = cornerstoneTools.drawTextBox(context, textLine, canvasTextLocation.x, canvasTextLocation.y, color, config.textBox);
data.handles.textBox.boundingBox = boundingBox;
OHIF.cornerstone.repositionTextBox(eventData, data, config.textBox);
// Draw linked line as dashed
var link = {
start: {},
end: {}
};
var midpointCanvas = {
x: (handleStartCanvas.x + handleEndCanvas.x) / 2,
y: (handleStartCanvas.y + handleEndCanvas.y) / 2,
};
var points = [ handleStartCanvas, handleEndCanvas, midpointCanvas ];
link.end.x = canvasTextLocation.x;
link.end.y = canvasTextLocation.y;
link.start = cornerstoneMath.point.findClosestPoint(points, link.end);
var boundingBoxPoints = [ {
// Top middle point of bounding box
x: boundingBox.left + boundingBox.width / 2,
y: boundingBox.top
}, {
// Left middle point of bounding box
x: boundingBox.left,
y: boundingBox.top + boundingBox.height / 2
}, {
// Bottom middle point of bounding box
x: boundingBox.left + boundingBox.width / 2,
y: boundingBox.top + boundingBox.height
}, {
// Right middle point of bounding box
x: boundingBox.left + boundingBox.width,
y: boundingBox.top + boundingBox.height / 2
},
];
link.end = cornerstoneMath.point.findClosestPoint(boundingBoxPoints, link.start);
context.beginPath();
context.strokeStyle = color;
context.lineWidth = lineWidth;
context.setLineDash([ 2, 3 ]);
context.moveTo(link.start.x, link.start.y);
context.lineTo(link.end.x, link.end.y);
context.stroke();
}
context.restore();
}
}
// ---- Touch tool ----
///////// BEGIN ACTIVE TOOL ///////
function addNewMeasurementTouch(touchEventData) {
var element = touchEventData.element;
function doneCallback() {
measurementData.active = true;
cornerstone.updateImage(element);
}
var measurementData = createNewMeasurement(touchEventData);
cornerstoneTools.addToolState(element, toolType, measurementData);
$(element).off('CornerstoneToolsTouchDrag', cornerstoneTools.nonTargetTouch.touchMoveHandle);
$(element).off('CornerstoneToolsDragStartActive', cornerstoneTools.nonTargetTouch.touchDownActivateCallback);
$(element).off('CornerstoneToolsTap', cornerstoneTools.nonTargetTouch.tapCallback);
var config = cornerstoneTools.nonTarget.getConfiguration();
cornerstone.updateImage(element);
cornerstoneTools.moveNewHandleTouch(touchEventData, toolType, measurementData, measurementData.handles.end, function() {
cornerstone.updateImage(element); cornerstone.updateImage(element);
cornerstoneTools.moveNewHandleTouch(touchEventData, toolType, measurementData, measurementData.handles.end, function() { if (cornerstoneTools.anyHandlesOutsideImage(touchEventData, measurementData.handles)) {
cornerstone.updateImage(element); // delete the measurement
cornerstoneTools.removeToolState(element, toolType, measurementData);
if (cornerstoneTools.anyHandlesOutsideImage(touchEventData, measurementData.handles)) {
// delete the measurement
cornerstoneTools.removeToolState(element, toolType, measurementData);
}
config.getMeasurementLocationCallback(measurementData, touchEventData, doneCallback);
$(element).on('CornerstoneToolsTouchDrag', cornerstoneTools.nonTargetTouch.touchMoveHandle);
$(element).on('CornerstoneToolsDragStartActive', cornerstoneTools.nonTargetTouch.touchDownActivateCallback);
$(element).on('CornerstoneToolsTap', cornerstoneTools.nonTargetTouch.tapCallback);
});
}
function doubleClickCallback(e, eventData) {
var element = eventData.element;
var data;
function doneCallback(data, deleteTool) {
if (deleteTool === true) {
cornerstoneTools.removeToolState(element, toolType, data);
cornerstone.updateImage(element);
return;
}
data.active = false;
cornerstone.updateImage(element);
} }
if (e.data && e.data.mouseButtonMask && !cornerstoneTools.isMouseButtonEnabled(eventData.which, e.data.mouseButtonMask)) { config.getMeasurementLocationCallback(measurementData, touchEventData, doneCallback);
return false;
}
var config = cornerstoneTools.nonTarget.getConfiguration(); $(element).on('CornerstoneToolsTouchDrag', cornerstoneTools.nonTargetTouch.touchMoveHandle);
$(element).on('CornerstoneToolsDragStartActive', cornerstoneTools.nonTargetTouch.touchDownActivateCallback);
$(element).on('CornerstoneToolsTap', cornerstoneTools.nonTargetTouch.tapCallback);
});
}
var coords = eventData.currentPoints.canvas; function doubleClickCallback(e, eventData) {
var toolData = cornerstoneTools.getToolState(element, toolType); var element = eventData.element;
var data;
// now check to see if there is a handle we can move function doneCallback(data, deleteTool) {
if (!toolData) { if (deleteTool === true) {
cornerstoneTools.removeToolState(element, toolType, data);
cornerstone.updateImage(element);
return; return;
} }
for (var i = 0; i < toolData.data.length; i++) { data.active = false;
data = toolData.data[i]; cornerstone.updateImage(element);
if (pointNearTool(element, data, coords)) {
data.active = true;
cornerstone.updateImage(element);
// Allow relabelling via a callback
config.changeMeasurementLocationCallback(data, eventData, doneCallback);
e.stopImmediatePropagation();
return false;
}
}
} }
cornerstoneTools.nonTarget = cornerstoneTools.mouseButtonTool({ if (e.data && e.data.mouseButtonMask && !cornerstoneTools.isMouseButtonEnabled(eventData.which, e.data.mouseButtonMask)) {
addNewMeasurement: addNewMeasurement, return false;
createNewMeasurement: createNewMeasurement, }
onImageRendered: onImageRendered,
pointNearTool: pointNearTool,
toolType: toolType,
mouseDoubleClickCallback: doubleClickCallback
});
cornerstoneTools.nonTarget.setConfiguration(configuration); var config = cornerstoneTools.nonTarget.getConfiguration();
cornerstoneTools.nonTargetTouch = cornerstoneTools.touchTool({ var coords = eventData.currentPoints.canvas;
addNewMeasurement: addNewMeasurementTouch, var toolData = cornerstoneTools.getToolState(element, toolType);
createNewMeasurement: createNewMeasurement,
onImageRendered: onImageRendered,
pointNearTool: pointNearTool,
toolType: toolType
// pressCallback: doubleClickCallback
});
})($, cornerstone, cornerstoneMath, cornerstoneTools); // now check to see if there is a handle we can move
if (!toolData) {
return;
}
for (var i = 0; i < toolData.data.length; i++) {
data = toolData.data[i];
if (pointNearTool(element, data, coords)) {
data.active = true;
cornerstone.updateImage(element);
// Allow relabelling via a callback
config.changeMeasurementLocationCallback(data, eventData, doneCallback);
e.stopImmediatePropagation();
return false;
}
}
}
cornerstoneTools.nonTarget = cornerstoneTools.mouseButtonTool({
addNewMeasurement,
createNewMeasurement,
onImageRendered,
pointNearTool,
toolType,
mouseDoubleClickCallback: doubleClickCallback
});
cornerstoneTools.nonTarget.setConfiguration(configuration);
cornerstoneTools.nonTargetTouch = cornerstoneTools.touchTool({
addNewMeasurement: addNewMeasurementTouch,
createNewMeasurement,
onImageRendered,
pointNearTool,
toolType
// pressCallback: doubleClickCallback
});

View File

@ -1,424 +1,420 @@
import { Viewerbase } from 'meteor/ohif:viewerbase'; import { Viewerbase } from 'meteor/ohif:viewerbase';
import { cornerstone, cornerstoneMath, cornerstoneTools } from 'meteor/ohif:cornerstone';
(function($, cornerstone, cornerstoneMath, cornerstoneTools) { var responseByToolType = [{
"toolType": "targetCR",
"toolResponse": "CR"
}, {
"toolType": "targetUN",
"toolResponse": "UN"
}, {
"toolType": "targetEX",
"toolResponse": "EX"
}];
'use strict'; const toolDefaultStates = Viewerbase.toolManager.getToolDefaultStates();
var responseByToolType = [{ const textBoxConfig = toolDefaultStates.textBoxConfig;
"toolType": "targetCR",
"toolResponse": "CR"
}, {
"toolType": "targetUN",
"toolResponse": "UN"
}, {
"toolType": "targetEX",
"toolResponse": "EX"
}];
const toolDefaultStates = Viewerbase.toolManager.getToolDefaultStates(); var configuration = {
const textBoxConfig = toolDefaultStates.textBoxConfig; getMeasurementLocationCallback,
changeMeasurementLocationCallback,
drawHandles: false,
drawHandlesOnHover: false,
arrowFirst: true,
textBox: textBoxConfig
};
var configuration = { // Used to cancel tool placement
getMeasurementLocationCallback: getMeasurementLocationCallback, var keys = {
changeMeasurementLocationCallback: changeMeasurementLocationCallback, ESC: 27
drawHandles: false, };
drawHandlesOnHover: false,
arrowFirst: true, // Define a callback to get your text annotation
textBox: textBoxConfig // This could be used, e.g. to open a modal
function getMeasurementLocationCallback(measurementData, eventData, doneCallback) {
doneCallback(prompt('Enter your lesion location:'));
}
function changeMeasurementLocationCallback(measurementData, eventData, doneCallback) {
doneCallback(prompt('Change your lesion location:'));
}
function createQualitativeTargetTool(toolType) {
var toolInterface = {
toolType: toolType
}; };
// Used to cancel tool placement var response;
var keys = {
ESC: 27
};
// Define a callback to get your text annotation responseByToolType.forEach(function(tool) {
// This could be used, e.g. to open a modal if (tool.toolType === toolInterface.toolType) {
function getMeasurementLocationCallback(measurementData, eventData, doneCallback) { response = tool.toolResponse;
doneCallback(prompt('Enter your lesion location:')); }
});
/// --- Mouse Tool --- ///
///////// BEGIN ACTIVE TOOL ///////
function addNewMeasurement(mouseEventData) {
var element = mouseEventData.element;
function doneCallback() {
measurementData.active = true;
cornerstone.updateImage(element);
}
var measurementData = createNewMeasurement(mouseEventData);
var eventData = {
mouseButtonMask: mouseEventData.which
};
var config = cornerstoneTools[toolType].getConfiguration();
// associate this data with this imageId so we can render it and manipulate it
cornerstoneTools.addToolState(mouseEventData.element, toolType, measurementData);
// since we are dragging to another place to drop the end point, we can just activate
// the end point and let the moveHandle move it for us.
$(element).off('CornerstoneToolsMouseMove', cornerstoneTools[toolType].mouseMoveCallback);
$(element).off('CornerstoneToolsMouseDown', cornerstoneTools[toolType].mouseDownCallback);
$(element).off('CornerstoneToolsMouseDownActivate', cornerstoneTools[toolType].mouseDownActivateCallback);
$(element).off('CornerstoneToolsMouseDoubleClick', doubleClickCallback);
// Add a flag for using Esc to cancel tool placement
var cancelled = false;
function cancelCallback(e) {
// If the Esc key was pressed, set the flag to true
if (e.which === keys.ESC) {
cancelled = true;
cornerstoneTools.removeToolState(mouseEventData.element, toolType, measurementData);
}
// Don't propagate this keydown event so it can't interfere
// with anything outside of this tool
return false;
}
// Bind a one-time event listener for the Esc key
$(element).one('keydown', cancelCallback);
cornerstone.updateImage(element);
cornerstoneTools.moveNewHandle(mouseEventData, toolType, measurementData, measurementData.handles.end, function() {
if (cancelled || cornerstoneTools.anyHandlesOutsideImage(mouseEventData, measurementData.handles)) {
// delete the measurement
cornerstoneTools.removeToolState(mouseEventData.element, toolType, measurementData);
} else {
config.getMeasurementLocationCallback(measurementData, mouseEventData, doneCallback);
}
// Unbind the Esc keydown hook
$(element).off('keydown', cancelCallback);
$(element).on('CornerstoneToolsMouseMove', eventData, cornerstoneTools[toolType].mouseMoveCallback);
$(element).on('CornerstoneToolsMouseDown', eventData, cornerstoneTools[toolType].mouseDownCallback);
$(element).on('CornerstoneToolsMouseDownActivate', eventData, cornerstoneTools[toolType].mouseDownActivateCallback);
$(element).on('CornerstoneToolsMouseDoubleClick', eventData, doubleClickCallback);
$(element).off('keydown', cancelCallback);
cornerstone.updateImage(mouseEventData.element);
});
} }
function changeMeasurementLocationCallback(measurementData, eventData, doneCallback) { function createNewMeasurement(mouseEventData) {
doneCallback(prompt('Change your lesion location:')); var imageId = mouseEventData.image.imageId;
}
// Get studyInstanceUid
var study = cornerstoneTools.metaData.get('study', imageId);
var studyInstanceUid = study.studyInstanceUid;
var patientId = study.patientId;
function createQualitativeTargetTool(toolType) { // Get seriesInstanceUid
var toolInterface = { var series = cornerstoneTools.metaData.get('series', imageId);
var seriesInstanceUid = series.seriesInstanceUid;
// create the measurement data for this tool with the end handle activated
var measurementData = {
visible: true,
active: true,
handles: {
start: {
x: mouseEventData.currentPoints.image.x,
y: mouseEventData.currentPoints.image.y,
allowedOutsideImage: true,
highlight: true,
active: false
},
end: {
x: mouseEventData.currentPoints.image.x,
y: mouseEventData.currentPoints.image.y,
allowedOutsideImage: true,
highlight: true,
active: false
},
textBox: {
x: mouseEventData.currentPoints.image.x - 50,
y: mouseEventData.currentPoints.image.y - 50,
active: false,
movesIndependently: false,
drawnIndependently: true,
allowedOutsideImage: true,
hasBoundingBox: true
}
},
imageId: imageId,
seriesInstanceUid: seriesInstanceUid,
studyInstanceUid: studyInstanceUid,
patientId: patientId,
response: response,
isTarget: true,
toolType: toolType toolType: toolType
}; };
var response; return measurementData;
}
///////// END ACTIVE TOOL ///////
responseByToolType.forEach(function(tool) { function pointNearTool(element, data, coords) {
if (tool.toolType === toolInterface.toolType) { var lineSegment = {
response = tool.toolResponse; start: cornerstone.pixelToCanvas(element, data.handles.start),
} end: cornerstone.pixelToCanvas(element, data.handles.end)
}); };
var distanceToPoint = cornerstoneMath.lineSegment.distanceToPoint(lineSegment, coords);
/// --- Mouse Tool --- /// if (cornerstoneTools.pointInsideBoundingBox(data.handles.textBox, coords)) {
///////// BEGIN ACTIVE TOOL /////// return true;
function addNewMeasurement(mouseEventData) {
var element = mouseEventData.element;
function doneCallback() {
measurementData.active = true;
cornerstone.updateImage(element);
}
var measurementData = createNewMeasurement(mouseEventData);
var eventData = {
mouseButtonMask: mouseEventData.which
};
var config = cornerstoneTools[toolType].getConfiguration();
// associate this data with this imageId so we can render it and manipulate it
cornerstoneTools.addToolState(mouseEventData.element, toolType, measurementData);
// since we are dragging to another place to drop the end point, we can just activate
// the end point and let the moveHandle move it for us.
$(element).off('CornerstoneToolsMouseMove', cornerstoneTools[toolType].mouseMoveCallback);
$(element).off('CornerstoneToolsMouseDown', cornerstoneTools[toolType].mouseDownCallback);
$(element).off('CornerstoneToolsMouseDownActivate', cornerstoneTools[toolType].mouseDownActivateCallback);
$(element).off('CornerstoneToolsMouseDoubleClick', doubleClickCallback);
// Add a flag for using Esc to cancel tool placement
var cancelled = false;
function cancelCallback(e) {
// If the Esc key was pressed, set the flag to true
if (e.which === keys.ESC) {
cancelled = true;
cornerstoneTools.removeToolState(mouseEventData.element, toolType, measurementData);
}
// Don't propagate this keydown event so it can't interfere
// with anything outside of this tool
return false;
}
// Bind a one-time event listener for the Esc key
$(element).one('keydown', cancelCallback);
cornerstone.updateImage(element);
cornerstoneTools.moveNewHandle(mouseEventData, toolType, measurementData, measurementData.handles.end, function() {
if (cancelled || cornerstoneTools.anyHandlesOutsideImage(mouseEventData, measurementData.handles)) {
// delete the measurement
cornerstoneTools.removeToolState(mouseEventData.element, toolType, measurementData);
} else {
config.getMeasurementLocationCallback(measurementData, mouseEventData, doneCallback);
}
// Unbind the Esc keydown hook
$(element).off('keydown', cancelCallback);
$(element).on('CornerstoneToolsMouseMove', eventData, cornerstoneTools[toolType].mouseMoveCallback);
$(element).on('CornerstoneToolsMouseDown', eventData, cornerstoneTools[toolType].mouseDownCallback);
$(element).on('CornerstoneToolsMouseDownActivate', eventData, cornerstoneTools[toolType].mouseDownActivateCallback);
$(element).on('CornerstoneToolsMouseDoubleClick', eventData, doubleClickCallback);
$(element).off('keydown', cancelCallback);
cornerstone.updateImage(mouseEventData.element);
});
} }
function createNewMeasurement(mouseEventData) { return distanceToPoint < 25;
var imageId = mouseEventData.image.imageId;
// Get studyInstanceUid
var study = cornerstoneTools.metaData.get('study', imageId);
var studyInstanceUid = study.studyInstanceUid;
var patientId = study.patientId;
// Get seriesInstanceUid
var series = cornerstoneTools.metaData.get('series', imageId);
var seriesInstanceUid = series.seriesInstanceUid;
// create the measurement data for this tool with the end handle activated
var measurementData = {
visible: true,
active: true,
handles: {
start: {
x: mouseEventData.currentPoints.image.x,
y: mouseEventData.currentPoints.image.y,
allowedOutsideImage: true,
highlight: true,
active: false
},
end: {
x: mouseEventData.currentPoints.image.x,
y: mouseEventData.currentPoints.image.y,
allowedOutsideImage: true,
highlight: true,
active: false
},
textBox: {
x: mouseEventData.currentPoints.image.x - 50,
y: mouseEventData.currentPoints.image.y - 50,
active: false,
movesIndependently: false,
drawnIndependently: true,
allowedOutsideImage: true,
hasBoundingBox: true
}
},
imageId: imageId,
seriesInstanceUid: seriesInstanceUid,
studyInstanceUid: studyInstanceUid,
patientId: patientId,
response: response,
isTarget: true,
toolType: toolType
};
return measurementData;
}
///////// END ACTIVE TOOL ///////
function pointNearTool(element, data, coords) {
var lineSegment = {
start: cornerstone.pixelToCanvas(element, data.handles.start),
end: cornerstone.pixelToCanvas(element, data.handles.end)
};
var distanceToPoint = cornerstoneMath.lineSegment.distanceToPoint(lineSegment, coords);
if (cornerstoneTools.pointInsideBoundingBox(data.handles.textBox, coords)) {
return true;
}
return distanceToPoint < 25;
}
function drawDottedArrow(context, start, end, color, lineWidth) {
//variables to be used when creating the arrow
var headLength = 10;
var angle = Math.atan2(end.y - start.y, end.x - start.x);
//starting path of the arrow from the start square to the end square and drawing the stroke
context.beginPath();
context.moveTo(start.x, start.y);
context.lineTo(end.x, end.y);
context.strokeStyle = color;
context.lineWidth = lineWidth;
//context.setLineDash([ 2, 3 ]);
context.stroke();
//starting a new path from the head of the arrow to one of the sides of the point
context.beginPath();
context.moveTo(end.x, end.y);
context.lineTo(end.x - headLength * Math.cos(angle - Math.PI / 7), end.y - headLength * Math.sin(angle - Math.PI / 7));
//path from the side point of the arrow, to the other side point
context.lineTo(end.x - headLength * Math.cos(angle + Math.PI / 7), end.y - headLength * Math.sin(angle + Math.PI / 7));
//path from the side point back to the tip of the arrow, and then again to the opposite side point
context.lineTo(end.x, end.y);
context.lineTo(end.x - headLength * Math.cos(angle - Math.PI / 7), end.y - headLength * Math.sin(angle - Math.PI / 7));
//draws the paths created above
context.strokeStyle = color;
context.lineWidth = lineWidth;
context.stroke();
context.fillStyle = color;
context.fill();
}
///////// BEGIN IMAGE RENDERING ///////
function onImageRendered(e, eventData) {
var element = eventData.element;
// if we have no toolData for this element, return immediately as there is nothing to do
var toolData = cornerstoneTools.getToolState(element, toolType);
if (!toolData) {
return;
}
// 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);
var color;
var lineWidth = cornerstoneTools.toolStyle.getToolWidth();
var config = cornerstoneTools[toolType].getConfiguration();
for (var i = 0; i < toolData.data.length; i++) {
var data = toolData.data[i];
context.save();
// configurable shadow from CornerstoneTools
if (config && config.shadow) {
context.shadowColor = config.shadowColor || '#000000';
context.shadowOffsetX = config.shadowOffsetX || 1;
context.shadowOffsetY = config.shadowOffsetY || 1;
}
if (data.active) {
color = cornerstoneTools.toolColors.getActiveColor();
} else {
color = cornerstoneTools.toolColors.getToolColor();
}
// Draw the arrow
var handleStartCanvas = cornerstone.pixelToCanvas(element, data.handles.start);
var handleEndCanvas = cornerstone.pixelToCanvas(element, data.handles.end);
var canvasTextLocation = cornerstone.pixelToCanvas(element, data.handles.textBox);
drawDottedArrow(context, handleEndCanvas, handleStartCanvas, color, lineWidth);
if (config.drawHandles) {
cornerstoneTools.drawHandles(context, eventData, data.handles, color);
} else if (config.drawHandlesOnHover && data.handles.start.active) {
cornerstoneTools.drawHandles(context, eventData, [data.handles.start], color);
} else if (config.drawHandlesOnHover && data.handles.end.active) {
cornerstoneTools.drawHandles(context, eventData, [data.handles.end], color);
}
// Draw the text
if (data.measurementNumber) {
// Draw linked line as dashed
var mid = {
x: (handleStartCanvas.x + handleEndCanvas.x) / 2,
y: (handleStartCanvas.y + handleEndCanvas.y) / 2
};
context.beginPath();
context.strokeStyle = color;
context.lineWidth = lineWidth;
context.setLineDash([2, 3]);
context.moveTo(mid.x, mid.y);
context.lineTo(canvasTextLocation.x + 20, canvasTextLocation.y + 20);
context.stroke();
var textLine = `Target ${data.measurementNumber}`;
var boundingBox = cornerstoneTools.drawTextBox(context, textLine, canvasTextLocation.x, canvasTextLocation.y, color, config.textBox);
data.handles.textBox.boundingBox = boundingBox;
}
context.restore();
}
}
// ---- Touch tool ----
///////// BEGIN ACTIVE TOOL ///////
function addNewMeasurementTouch(touchEventData) {
var element = touchEventData.element;
function doneCallback() {
measurementData.active = true;
cornerstone.updateImage(element);
}
var measurementData = createNewMeasurement(touchEventData);
cornerstoneTools.addToolState(element, toolType, measurementData);
$(element).off('CornerstoneToolsTouchDrag', cornerstoneTools[toolType + "Touch"].touchMoveHandle);
$(element).off('CornerstoneToolsDragStartActive', cornerstoneTools[toolType + "Touch"].touchDownActivateCallback);
$(element).off('CornerstoneToolsTap', cornerstoneTools[toolType + "Touch"].tapCallback);
var config = cornerstoneTools[toolType].getConfiguration();
cornerstone.updateImage(element);
cornerstoneTools.moveNewHandleTouch(touchEventData, toolType, measurementData, measurementData.handles.end, function() {
cornerstone.updateImage(element);
if (cornerstoneTools.anyHandlesOutsideImage(touchEventData, measurementData.handles)) {
// delete the measurement
cornerstoneTools.removeToolState(element, toolType, measurementData);
}
config.getMeasurementLocationCallback(measurementData, touchEventData, doneCallback);
$(element).on('CornerstoneToolsTouchDrag', cornerstoneTools[toolType + "Touch"].touchMoveHandle);
$(element).on('CornerstoneToolsDragStartActive', cornerstoneTools[toolType + "Touch"].touchDownActivateCallback);
$(element).on('CornerstoneToolsTap', cornerstoneTools[toolType + "Touch"].tapCallback);
});
}
function doubleClickCallback(e, eventData) {
var element = eventData.element;
var data;
function doneCallback(data, deleteTool) {
if (deleteTool === true) {
cornerstoneTools.removeToolState(element, toolType, data);
cornerstone.updateImage(element);
return;
}
data.active = false;
cornerstone.updateImage(element);
}
if (e.data && e.data.mouseButtonMask && !cornerstoneTools.isMouseButtonEnabled(eventData.which, e.data.mouseButtonMask)) {
return false;
}
var config = cornerstoneTools[toolType].getConfiguration();
var coords = eventData.currentPoints.canvas;
var toolData = cornerstoneTools.getToolState(element, toolType);
// now check to see if there is a handle we can move
if (!toolData) {
return;
}
for (var i = 0; i < toolData.data.length; i++) {
data = toolData.data[i];
if (pointNearTool(element, data, coords)) {
data.active = true;
cornerstone.updateImage(element);
// Allow relabelling via a callback
config.changeMeasurementLocationCallback(data, eventData, doneCallback);
e.stopImmediatePropagation();
return false;
}
}
}
toolInterface.mouse = cornerstoneTools.mouseButtonTool({
addNewMeasurement: addNewMeasurement,
createNewMeasurement: createNewMeasurement,
onImageRendered: onImageRendered,
pointNearTool: pointNearTool,
toolType: toolType,
mouseDoubleClickCallback: doubleClickCallback
});
toolInterface.touch = cornerstoneTools.touchTool({
addNewMeasurement: addNewMeasurementTouch,
createNewMeasurement: createNewMeasurement,
onImageRendered: onImageRendered,
pointNearTool: pointNearTool,
toolType: toolType
// pressCallback: doubleClickCallback
});
return toolInterface;
} }
var targetCRInterface = createQualitativeTargetTool('targetCR'); function drawDottedArrow(context, start, end, color, lineWidth) {
cornerstoneTools.targetCR = targetCRInterface.mouse; //variables to be used when creating the arrow
cornerstoneTools.targetCR.setConfiguration(configuration); var headLength = 10;
cornerstoneTools.targetCRTouch = targetCRInterface.touch;
var targetUNInterface = createQualitativeTargetTool('targetUN'); var angle = Math.atan2(end.y - start.y, end.x - start.x);
cornerstoneTools.targetUN = targetUNInterface.mouse;
cornerstoneTools.targetUN.setConfiguration(configuration);
cornerstoneTools.targetUNTouch = targetUNInterface.touch;
var targetEXInterface = createQualitativeTargetTool('targetEX'); //starting path of the arrow from the start square to the end square and drawing the stroke
cornerstoneTools.targetEX = targetEXInterface.mouse; context.beginPath();
cornerstoneTools.targetEX.setConfiguration(configuration); context.moveTo(start.x, start.y);
cornerstoneTools.targetEXTouch = targetEXInterface.touch; context.lineTo(end.x, end.y);
context.strokeStyle = color;
context.lineWidth = lineWidth;
//context.setLineDash([ 2, 3 ]);
context.stroke();
})($, cornerstone, cornerstoneMath, cornerstoneTools); //starting a new path from the head of the arrow to one of the sides of the point
context.beginPath();
context.moveTo(end.x, end.y);
context.lineTo(end.x - headLength * Math.cos(angle - Math.PI / 7), end.y - headLength * Math.sin(angle - Math.PI / 7));
//path from the side point of the arrow, to the other side point
context.lineTo(end.x - headLength * Math.cos(angle + Math.PI / 7), end.y - headLength * Math.sin(angle + Math.PI / 7));
//path from the side point back to the tip of the arrow, and then again to the opposite side point
context.lineTo(end.x, end.y);
context.lineTo(end.x - headLength * Math.cos(angle - Math.PI / 7), end.y - headLength * Math.sin(angle - Math.PI / 7));
//draws the paths created above
context.strokeStyle = color;
context.lineWidth = lineWidth;
context.stroke();
context.fillStyle = color;
context.fill();
}
///////// BEGIN IMAGE RENDERING ///////
function onImageRendered(e, eventData) {
var element = eventData.element;
// if we have no toolData for this element, return immediately as there is nothing to do
var toolData = cornerstoneTools.getToolState(element, toolType);
if (!toolData) {
return;
}
// 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);
var color;
var lineWidth = cornerstoneTools.toolStyle.getToolWidth();
var config = cornerstoneTools[toolType].getConfiguration();
for (var i = 0; i < toolData.data.length; i++) {
var data = toolData.data[i];
context.save();
// configurable shadow from CornerstoneTools
if (config && config.shadow) {
context.shadowColor = config.shadowColor || '#000000';
context.shadowOffsetX = config.shadowOffsetX || 1;
context.shadowOffsetY = config.shadowOffsetY || 1;
}
if (data.active) {
color = cornerstoneTools.toolColors.getActiveColor();
} else {
color = cornerstoneTools.toolColors.getToolColor();
}
// Draw the arrow
var handleStartCanvas = cornerstone.pixelToCanvas(element, data.handles.start);
var handleEndCanvas = cornerstone.pixelToCanvas(element, data.handles.end);
var canvasTextLocation = cornerstone.pixelToCanvas(element, data.handles.textBox);
drawDottedArrow(context, handleEndCanvas, handleStartCanvas, color, lineWidth);
if (config.drawHandles) {
cornerstoneTools.drawHandles(context, eventData, data.handles, color);
} else if (config.drawHandlesOnHover && data.handles.start.active) {
cornerstoneTools.drawHandles(context, eventData, [data.handles.start], color);
} else if (config.drawHandlesOnHover && data.handles.end.active) {
cornerstoneTools.drawHandles(context, eventData, [data.handles.end], color);
}
// Draw the text
if (data.measurementNumber) {
// Draw linked line as dashed
var mid = {
x: (handleStartCanvas.x + handleEndCanvas.x) / 2,
y: (handleStartCanvas.y + handleEndCanvas.y) / 2
};
context.beginPath();
context.strokeStyle = color;
context.lineWidth = lineWidth;
context.setLineDash([2, 3]);
context.moveTo(mid.x, mid.y);
context.lineTo(canvasTextLocation.x + 20, canvasTextLocation.y + 20);
context.stroke();
var textLine = `Target ${data.measurementNumber}`;
var boundingBox = cornerstoneTools.drawTextBox(context, textLine, canvasTextLocation.x, canvasTextLocation.y, color, config.textBox);
data.handles.textBox.boundingBox = boundingBox;
}
context.restore();
}
}
// ---- Touch tool ----
///////// BEGIN ACTIVE TOOL ///////
function addNewMeasurementTouch(touchEventData) {
var element = touchEventData.element;
function doneCallback() {
measurementData.active = true;
cornerstone.updateImage(element);
}
var measurementData = createNewMeasurement(touchEventData);
cornerstoneTools.addToolState(element, toolType, measurementData);
$(element).off('CornerstoneToolsTouchDrag', cornerstoneTools[toolType + "Touch"].touchMoveHandle);
$(element).off('CornerstoneToolsDragStartActive', cornerstoneTools[toolType + "Touch"].touchDownActivateCallback);
$(element).off('CornerstoneToolsTap', cornerstoneTools[toolType + "Touch"].tapCallback);
var config = cornerstoneTools[toolType].getConfiguration();
cornerstone.updateImage(element);
cornerstoneTools.moveNewHandleTouch(touchEventData, toolType, measurementData, measurementData.handles.end, function() {
cornerstone.updateImage(element);
if (cornerstoneTools.anyHandlesOutsideImage(touchEventData, measurementData.handles)) {
// delete the measurement
cornerstoneTools.removeToolState(element, toolType, measurementData);
}
config.getMeasurementLocationCallback(measurementData, touchEventData, doneCallback);
$(element).on('CornerstoneToolsTouchDrag', cornerstoneTools[toolType + "Touch"].touchMoveHandle);
$(element).on('CornerstoneToolsDragStartActive', cornerstoneTools[toolType + "Touch"].touchDownActivateCallback);
$(element).on('CornerstoneToolsTap', cornerstoneTools[toolType + "Touch"].tapCallback);
});
}
function doubleClickCallback(e, eventData) {
var element = eventData.element;
var data;
function doneCallback(data, deleteTool) {
if (deleteTool === true) {
cornerstoneTools.removeToolState(element, toolType, data);
cornerstone.updateImage(element);
return;
}
data.active = false;
cornerstone.updateImage(element);
}
if (e.data && e.data.mouseButtonMask && !cornerstoneTools.isMouseButtonEnabled(eventData.which, e.data.mouseButtonMask)) {
return false;
}
var config = cornerstoneTools[toolType].getConfiguration();
var coords = eventData.currentPoints.canvas;
var toolData = cornerstoneTools.getToolState(element, toolType);
// now check to see if there is a handle we can move
if (!toolData) {
return;
}
for (var i = 0; i < toolData.data.length; i++) {
data = toolData.data[i];
if (pointNearTool(element, data, coords)) {
data.active = true;
cornerstone.updateImage(element);
// Allow relabelling via a callback
config.changeMeasurementLocationCallback(data, eventData, doneCallback);
e.stopImmediatePropagation();
return false;
}
}
}
toolInterface.mouse = cornerstoneTools.mouseButtonTool({
addNewMeasurement: addNewMeasurement,
createNewMeasurement: createNewMeasurement,
onImageRendered: onImageRendered,
pointNearTool: pointNearTool,
toolType: toolType,
mouseDoubleClickCallback: doubleClickCallback
});
toolInterface.touch = cornerstoneTools.touchTool({
addNewMeasurement: addNewMeasurementTouch,
createNewMeasurement: createNewMeasurement,
onImageRendered: onImageRendered,
pointNearTool: pointNearTool,
toolType: toolType
// pressCallback: doubleClickCallback
});
return toolInterface;
}
var targetCRInterface = createQualitativeTargetTool('targetCR');
cornerstoneTools.targetCR = targetCRInterface.mouse;
cornerstoneTools.targetCR.setConfiguration(configuration);
cornerstoneTools.targetCRTouch = targetCRInterface.touch;
var targetUNInterface = createQualitativeTargetTool('targetUN');
cornerstoneTools.targetUN = targetUNInterface.mouse;
cornerstoneTools.targetUN.setConfiguration(configuration);
cornerstoneTools.targetUNTouch = targetUNInterface.touch;
var targetEXInterface = createQualitativeTargetTool('targetEX');
cornerstoneTools.targetEX = targetEXInterface.mouse;
cornerstoneTools.targetEX.setConfiguration(configuration);
cornerstoneTools.targetEXTouch = targetEXInterface.touch;

View File

@ -7,7 +7,6 @@ Meteor.startup(function() {
OHIF.studylist.callbacks.middleClickOnStudy = dblClickOnStudy; OHIF.studylist.callbacks.middleClickOnStudy = dblClickOnStudy;
OHIF.studylist.timepointApi = new OHIF.measurements.TimepointApi(); OHIF.studylist.timepointApi = new OHIF.measurements.TimepointApi();
OHIF.studylist.timepointApi.retrieveTimepoints({});
}); });
/** /**

View File

@ -13,8 +13,13 @@ const Timepoints = new Mongo.Collection('timepoints');
Timepoints._debugName = 'Timepoints'; Timepoints._debugName = 'Timepoints';
Timepoints.find().observe({ Timepoints.find().observe({
remove() { added(document) {
console.warn('REMOVED'); console.warn('TIMEPOINT ADDED')
console.warn(document);
},
remove(docId) {
console.warn('TIMEPOINT REMOVED');
console.warn(docId);
} }
}); });

View File

@ -1,7 +1,8 @@
import { OHIF } from 'meteor/ohif:core'; import { OHIF } from 'meteor/ohif:core';
import { loglevel } from 'meteor/practicalmeteor:loglevel'; import loglevel from 'loglevel';
const defaultLevel = Meteor.isProduction ? 'error' : 'trace'; const defaultLevel = Meteor.isProduction ? 'ERROR' : 'TRACE';
// Create package logger using loglevel // Create package logger using loglevel
OHIF.log = loglevel.createLogger('', defaultLevel); OHIF.log = loglevel.getLogger('OHIF');
OHIF.log.setLevel(defaultLevel);

View File

@ -4,15 +4,16 @@ Package.describe({
version: '0.0.1' version: '0.0.1'
}); });
Npm.depends({
loglevel: '1.4.1'
});
Package.onUse(function(api) { Package.onUse(function(api) {
api.versionsFrom('1.4'); api.versionsFrom('1.4');
api.use('ecmascript'); api.use('ecmascript');
api.use('standard-app-packages'); api.use('standard-app-packages');
// Control over logging
api.use('practicalmeteor:loglevel');
// Our custom packages // Our custom packages
api.use('ohif:core'); api.use('ohif:core');

View File

@ -5,7 +5,7 @@ import { OHIF } from 'meteor/ohif:core';
import { schema as TimepointSchema } from 'meteor/ohif:measurements/both/schema/timepoints'; import { schema as TimepointSchema } from 'meteor/ohif:measurements/both/schema/timepoints';
let configuration = {}; const configuration = {};
class TimepointApi { class TimepointApi {
static setConfiguration(config) { static setConfiguration(config) {
@ -29,19 +29,30 @@ class TimepointApi {
retrieveTimepoints(filter) { retrieveTimepoints(filter) {
const retrievalFn = configuration.dataExchange.retrieve; const retrievalFn = configuration.dataExchange.retrieve;
if (!_.isFunction(retrievalFn)) { if (!_.isFunction(retrievalFn)) {
OHIF.log.error('Timepoint retrieval function has not been configured.')
return; return;
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
retrievalFn(filter).then(timepointData => { retrievalFn(filter).then(timepointData => {
OHIF.log.info('Timepoint data retrieval'); OHIF.log.info('Timepoint data retrieval');
OHIF.log.info(timepointData);
_.each(timepointData, timepoint => { _.each(timepointData, timepoint => {
delete timepoint._id; delete timepoint._id;
this.timepoints.insert(timepoint); const query = {
timepointId: timepoint.timepointId
};
this.timepoints.update(query, {
$set: timepoint
}, {
upsert: true
});
}); });
resolve(); resolve();
}).catch(reason => {
OHIF.log.error(`Timepoint retrieval function failed: ${reason}`);
}); });
}); });
} }

View File

@ -65,6 +65,7 @@ $bodyCellHeight = 30px
&.timepointOptions &.timepointOptions
label label
font-weight: 200 font-weight: 200
cursor: pointer
input input
margin: 0 3px margin: 0 3px

View File

@ -27,7 +27,7 @@ Template.caseProgress.onCreated(() => {
promise.then(successHandler).catch(errorHandler); promise.then(successHandler).catch(errorHandler);
OHIF.ui.showDialog('dialogLoading', { OHIF.ui.showDialog('dialogLoading', {
promise, promise,
text: 'Saving measurements data' text: 'Saving measurement data'
}); });
return promise; return promise;

View File

@ -107,6 +107,7 @@ class MeasurementHandlers {
Collection._c2._simpleSchema.clean(measurement); Collection._c2._simpleSchema.clean(measurement);
// Insert the new measurement into the collection // Insert the new measurement into the collection
console.log(measurement);
Collection.update(measurementId, { Collection.update(measurementId, {
$set: measurement $set: measurement
}); });

View File

@ -1,6 +1,6 @@
Npm.depends({ Npm.depends({
ajv: '4.10.4', ajv: '4.10.4',
jspdf: '1.3.2' jspdf: '1.3.3'
}); });
Package.describe({ Package.describe({

View File

@ -138,8 +138,8 @@ function search() {
patientId: getFilter($('input#patientId').val()), patientId: getFilter($('input#patientId').val()),
accessionNumber: getFilter($('input#accessionNumber').val()), accessionNumber: getFilter($('input#accessionNumber').val()),
studyDescription: getFilter($('input#studyDescription').val()), studyDescription: getFilter($('input#studyDescription').val()),
studyDateFrom: studyDateFrom, studyDateFrom,
studyDateTo: studyDateTo, studyDateTo,
modalitiesInStudy: $('input#modality').val() ? $('input#modality').val() : '' modalitiesInStudy: $('input#modality').val() ? $('input#modality').val() : ''
}; };
@ -161,6 +161,7 @@ function search() {
Session.set('showLoadingText', false); Session.set('showLoadingText', false);
if (!studies) { if (!studies) {
OHIF.log.warn('No studies found');
return; return;
} }

View File

@ -1,6 +1,6 @@
import { Template } from 'meteor/templating'; import { Template } from 'meteor/templating';
import { Blaze } from 'meteor/blaze'; import { Blaze } from 'meteor/blaze';
import * as Hammer from 'hammerjs'; import Hammer from 'hammerjs';
import { OHIF } from 'meteor/ohif:core'; import { OHIF } from 'meteor/ohif:core';
// Clear all selected studies // Clear all selected studies

View File

@ -33,6 +33,17 @@ OHIF.studylist.retrieveStudyMetadata = studyInstanceUid => {
Meteor.call('GetStudyMetadata', studyInstanceUid, function(error, study) { Meteor.call('GetStudyMetadata', studyInstanceUid, function(error, study) {
console.timeEnd('retrieveStudyMetadata'); console.timeEnd('retrieveStudyMetadata');
if (error) {
OHIF.log.error(error);
reject(error);
return;
}
if (!study) {
reject(`GetStudyMetadata: No study data returned from server: ${studyInstanceUid}`);
return;
}
if (window.HipaaLogger && Meteor.user && Meteor.user()) { if (window.HipaaLogger && Meteor.user && Meteor.user()) {
window.HipaaLogger.logEvent({ window.HipaaLogger.logEvent({
eventType: 'viewed', eventType: 'viewed',
@ -45,16 +56,6 @@ OHIF.studylist.retrieveStudyMetadata = studyInstanceUid => {
}); });
} }
if (error) {
OHIF.log.warn(error);
reject(error);
return;
}
if (!study) {
throw new Meteor.Error('GetStudyMetadata', 'No study data returned from server');
}
// Once the data was retrieved, the series are sorted by series and instance number // Once the data was retrieved, the series are sorted by series and instance number
OHIF.viewerbase.sortStudy(study); OHIF.viewerbase.sortStudy(study);

View File

@ -5,7 +5,7 @@ Package.describe({
}); });
Npm.depends({ Npm.depends({
hammerjs: '2.0.6' hammerjs: '2.0.8'
}); });
Package.onUse(function(api) { Package.onUse(function(api) {

View File

@ -0,0 +1,5 @@
<template name="errorText">
<div class="errorTextDiv">
Error: {{ error }}
</div>
</template>

View File

@ -0,0 +1,4 @@
.errorTextDiv
font-weight: 300
padding: 30px
text-align: center

View File

@ -35,6 +35,7 @@ Template.imageThumbnail.onRendered(() => {
const element = $element.get(0); const element = $element.get(0);
instance.refreshImage = () => { instance.refreshImage = () => {
console.log('imageThumbnail refreshImage');
if (!element) { if (!element) {
return; return;
} }
@ -84,16 +85,14 @@ Template.imageThumbnail.onRendered(() => {
}); });
Template.imageThumbnail.onDestroyed(() => { Template.imageThumbnail.onDestroyed(() => {
console.log('imagethumbnail onDestroyed');
const instance = Template.instance(); const instance = Template.instance();
// Declare DOM and jQuery objects // Declare DOM and jQuery objects
const $parent = instance.$('.imageThumbnail'); const $parent = instance.$('.imageThumbnail');
const $element = $parent.find('.imageThumbnailCanvas'); const $element = $parent.find('.imageThumbnailCanvas');
const element = $element.get(0); const element = $element.get(0);
cornerstone.disable(element);
if (element) {
cornerstone.disable(element);
}
}); });
Template.imageThumbnail.helpers({ Template.imageThumbnail.helpers({

View File

@ -26,8 +26,8 @@ function createAndAddStack(stackMap, study, displaySet) {
const metaData = { const metaData = {
instance: image, // in this context, instance will be the data of the InstanceMetadata object... instance: image, // in this context, instance will be the data of the InstanceMetadata object...
series: displaySet, // TODO: Check this series: displaySet, // TODO: Check this
study: study, study,
numImages: numImages, numImages,
imageIndex: imageIndex + 1 imageIndex: imageIndex + 1
}; };
@ -40,8 +40,7 @@ function createAndAddStack(stackMap, study, displaySet) {
imageIds.push(imageId); imageIds.push(imageId);
metadataProvider.addMetadata(imageId, metaData); metadataProvider.addMetadata(imageId, metaData);
} }
} } else {
else {
imageId = getImageId(image); imageId = getImageId(image);
imageIds.push(imageId); imageIds.push(imageId);
metadataProvider.addMetadata(imageId, metaData); metadataProvider.addMetadata(imageId, metaData);
@ -50,7 +49,7 @@ function createAndAddStack(stackMap, study, displaySet) {
const stack = { const stack = {
displaySetInstanceUid: displaySet.displaySetInstanceUid, displaySetInstanceUid: displaySet.displaySetInstanceUid,
imageIds: imageIds, imageIds,
frameRate: displaySet.frameRate, frameRate: displaySet.frameRate,
isClip: displaySet.isClip isClip: displaySet.isClip
}; };
@ -61,7 +60,7 @@ function createAndAddStack(stackMap, study, displaySet) {
} }
configuration = { configuration = {
createAndAddStack: createAndAddStack createAndAddStack
}; };
/** /**

View File

@ -7,7 +7,6 @@ import { getInstanceClassDefaultViewport } from '../instanceClassSpecificViewpor
export class ResizeViewportManager { export class ResizeViewportManager {
constructor() { constructor() {
this._resizeHandler = null; this._resizeHandler = null;
OHIF.log.info('ResizeViewportManager');
} }
// Reposition Study Series Quick Switch based whether side bars are opened or not // Reposition Study Series Quick Switch based whether side bars are opened or not

View File

@ -118,12 +118,12 @@ class DICOMFileLoadingListener extends BaseLoadingListener {
this.stopListening(); this.stopListening();
$(cornerstone).on(imageLoadProgressEventName, imageLoadProgressEventHandle); $(cornerstone.events).on(imageLoadProgressEventName, imageLoadProgressEventHandle);
} }
stopListening() { stopListening() {
const imageLoadProgressEventName = this._getImageLoadProgressEventName(); const imageLoadProgressEventName = this._getImageLoadProgressEventName();
$(cornerstone).off(imageLoadProgressEventName); $(cornerstone.events).off(imageLoadProgressEventName);
} }
_imageLoadProgressEventHandle(e, eventData) { _imageLoadProgressEventHandle(e, eventData) {
@ -241,16 +241,16 @@ class StackLoadingListener extends BaseLoadingListener {
this.stopListening(); this.stopListening();
$(cornerstone).on(imageLoadedEventName, imageLoadedEventHandle); $(cornerstone.events).on(imageLoadedEventName, imageLoadedEventHandle);
$(cornerstone).on(imageCachePromiseRemovedEventName, imageCachePromiseRemovedEventHandle); $(cornerstone.events).on(imageCachePromiseRemovedEventName, imageCachePromiseRemovedEventHandle);
} }
stopListening() { stopListening() {
const imageLoadedEventName = this._getImageLoadedEventName(); const imageLoadedEventName = this._getImageLoadedEventName();
const imageCachePromiseRemovedEventName = this._getImageCachePromiseRemoveEventName(); const imageCachePromiseRemovedEventName = this._getImageCachePromiseRemoveEventName();
$(cornerstone).off(imageLoadedEventName); $(cornerstone.events).off(imageLoadedEventName);
$(cornerstone).off(imageCachePromiseRemovedEventName); $(cornerstone.events).off(imageCachePromiseRemovedEventName);
} }
_updateFrameStatus(imageId, loaded) { _updateFrameStatus(imageId, loaded) {

View File

@ -13,12 +13,12 @@ export class StudyPrefetcher {
this.prefetchDisplaySetsTimeout = 300; this.prefetchDisplaySetsTimeout = 300;
this.lastActiveViewportElement = null; this.lastActiveViewportElement = null;
$(cornerstone).on('CornerstoneImageCacheFull.StudyPrefetcher', _.bind(this.cacheFullHandler, this)); $(cornerstone.events).on('CornerstoneImageCacheFull.StudyPrefetcher', _.bind(this.cacheFullHandler, this));
} }
destroy() { destroy() {
this.stopPrefetching(); this.stopPrefetching();
$(cornerstone).off('CornerstoneImageCacheFull.StudyPrefetcher'); $(cornerstone.events).off('CornerstoneImageCacheFull.StudyPrefetcher');
} }
static getInstance() { static getInstance() {
@ -162,7 +162,7 @@ export class StudyPrefetcher {
getStudy(image) { getStudy(image) {
const studyMetadata = cornerstoneTools.metaData.get('study', image.imageId); const studyMetadata = cornerstoneTools.metaData.get('study', image.imageId);
return _.find(this.studies, study => study.studyInstanceUid === studyMetadata.studyInstanceUid); return OHIF.viewer.Studies.find(study => study.studyInstanceUid === studyMetadata.studyInstanceUid);
} }
getSeries(study, image) { getSeries(study, image) {
@ -191,6 +191,10 @@ export class StudyPrefetcher {
} }
const study = this.getStudy(image); const study = this.getStudy(image);
if (!study.seriesList || !study.seriesList.length) {
console.error(study);
}
const series = this.getSeries(study, image); const series = this.getSeries(study, image);
const instance = this.getInstance(series, image); const instance = this.getInstance(series, image);
const displaySets = study.displaySets; const displaySets = study.displaySets;

View File

@ -22,5 +22,12 @@ export const renderViewer = (context, params, layoutTemplate='app') => {
studies studies
} }
}); });
}).catch(error => {
context.render(layoutTemplate, {
data: {
template: 'errorText',
error
}
});
}); });
}; };

View File

@ -235,8 +235,8 @@ export const toolManager = {
// Whenever the CornerstoneImageLoadProgress is fired, identify which viewports // Whenever the CornerstoneImageLoadProgress is fired, identify which viewports
// the "in-progress" image is to be displayed in. Then pass the percent complete // the "in-progress" image is to be displayed in. Then pass the percent complete
// via the Meteor Session to the other templates to be displayed in the relevant viewports. // via the Meteor Session to the other templates to be displayed in the relevant viewports.
$(cornerstone).on('CornerstoneImageLoadProgress', (e, eventData) => { $(cornerstone.events).on('CornerstoneImageLoadProgress', (e, eventData) => {
const viewportIndices = this.getKeysByValue(window.ViewportLoading, eventData.imageId); viewportIndices = this.getKeysByValue(window.ViewportLoading, eventData.imageId);
viewportIndices.forEach(viewportIndex => { viewportIndices.forEach(viewportIndex => {
Session.set('CornerstoneLoadProgress' + viewportIndex, eventData.percentComplete); Session.set('CornerstoneLoadProgress' + viewportIndex, eventData.percentComplete);
}); });

View File

@ -95,6 +95,8 @@ Package.onUse(function(api) {
api.addFiles('client/components/basic/layout/layout.styl', 'client'); api.addFiles('client/components/basic/layout/layout.styl', 'client');
api.addFiles('client/components/basic/loadingText/loadingText.html', 'client'); api.addFiles('client/components/basic/loadingText/loadingText.html', 'client');
api.addFiles('client/components/basic/loadingText/loadingText.styl', 'client'); api.addFiles('client/components/basic/loadingText/loadingText.styl', 'client');
api.addFiles('client/components/basic/errorText/errorText.html', 'client');
api.addFiles('client/components/basic/errorText/errorText.styl', 'client');
api.addFiles('client/components/basic/removableBackdrop/removableBackdrop.html', 'client'); api.addFiles('client/components/basic/removableBackdrop/removableBackdrop.html', 'client');
api.addFiles('client/components/basic/removableBackdrop/removableBackdrop.styl', 'client'); api.addFiles('client/components/basic/removableBackdrop/removableBackdrop.styl', 'client');

View File

@ -90,8 +90,6 @@ ohif:viewerbase@0.0.1
ohif:wadoproxy@0.0.1 ohif:wadoproxy@0.0.1
ordered-dict@1.0.9 ordered-dict@1.0.9
peppelg:bootstrap-3-modal@1.0.4 peppelg:bootstrap-3-modal@1.0.4
practicalmeteor:chai@2.1.0_1
practicalmeteor:loglevel@1.2.0_2
promise@0.8.8 promise@0.8.8
raix:eventemitter@0.1.3 raix:eventemitter@0.1.3
random@1.0.10 random@1.0.10

View File

@ -1,164 +1,362 @@
/*! cornerstoneWebImageLoader - v0.6.0 - 2016-02-09 | (c) 2015 Chris Hafey | https://github.com/chafey/cornerstoneWebImageLoader */ /*! cornerstone-web-image-loader - 0.8.1 - 2017-06-08 | (c) 2016 Chris Hafey | https://github.com/chafey/cornerstoneWebImageLoader */
cornerstoneWebImageLoader = {}; (function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("cornerstone-core"));
else if(typeof define === 'function' && define.amd)
define("cornerstoneWebImageLoader", ["cornerstone-core"], factory);
else if(typeof exports === 'object')
exports["cornerstoneWebImageLoader"] = factory(require("cornerstone-core"));
else
root["cornerstoneWebImageLoader"] = factory(root["cornerstone"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_0__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 4);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_0__;
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = function (arrayBuffer) {
var deferred = $.Deferred();
var image = new Image();
var arrayBufferView = new Uint8Array(arrayBuffer);
var blob = new Blob([arrayBufferView]);
var urlCreator = window.URL || window.webkitURL;
var imageUrl = urlCreator.createObjectURL(blob);
image.src = imageUrl;
image.onload = function () {
deferred.resolve(image);
urlCreator.revokeObjectURL(imageUrl);
};
image.onerror = function (err) {
urlCreator.revokeObjectURL(imageUrl);
deferred.reject(err);
};
return deferred.promise();
};
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = function (image, imageId) {
// extract the attributes we need
var rows = image.naturalHeight;
var columns = image.naturalWidth;
function getPixelData() {
var imageData = getImageData();
var imageDataData = imageData.data;
var numPixels = image.naturalHeight * image.naturalWidth;
var storedPixelData = new Uint8Array(numPixels * 4);
var imageDataIndex = 0;
var storedPixelDataIndex = 0;
for (var i = 0; i < numPixels; i++) {
storedPixelData[storedPixelDataIndex++] = imageDataData[imageDataIndex++];
storedPixelData[storedPixelDataIndex++] = imageDataData[imageDataIndex++];
storedPixelData[storedPixelDataIndex++] = imageDataData[imageDataIndex++];
storedPixelData[storedPixelDataIndex++] = 255; // alpha
imageDataIndex++;
}
return storedPixelData;
}
function getImageData() {
var context = void 0;
if (lastImageIdDrawn === imageId) {
context = canvas.getContext('2d');
} else {
canvas.height = image.naturalHeight;
canvas.width = image.naturalWidth;
context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
lastImageIdDrawn = imageId;
}
return context.getImageData(0, 0, image.naturalWidth, image.naturalHeight);
}
function getCanvas() {
if (lastImageIdDrawn === imageId) {
return canvas;
}
canvas.height = image.naturalHeight;
canvas.width = image.naturalWidth;
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
lastImageIdDrawn = imageId;
return canvas;
}
function getImage() {
return image;
}
// Extract the various attributes we need
return {
imageId: imageId,
minPixelValue: 0, // calculated below
maxPixelValue: 255, // calculated below
slope: 1.0,
intercept: 0,
windowCenter: 128,
windowWidth: 255,
render: cornerstone.renderWebImage,
getPixelData: getPixelData,
getImageData: getImageData,
getCanvas: getCanvas,
getImage: getImage,
// storedPixelData: extractStoredPixels(image),
rows: rows,
columns: columns,
height: rows,
width: columns,
color: true,
columnPixelSpacing: undefined,
rowPixelSpacing: undefined,
invert: false,
sizeInBytes: rows * columns * 4 // we don't know for sure so we over estimate to be safe
};
};
var _cornerstoneCore = __webpack_require__(0);
var cornerstone = _interopRequireWildcard(_cornerstoneCore);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
var canvas = document.createElement('canvas');
var lastImageIdDrawn = '';
/**
* creates a cornerstone Image object for the specified Image and imageId
*
* @param image - An Image
* @param imageId - the imageId for this image
* @returns Cornerstone Image Object
*/
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.loadImage = loadImage;
exports.configure = configure;
var _cornerstoneCore = __webpack_require__(0);
var cornerstone = _interopRequireWildcard(_cornerstoneCore);
var _arrayBufferToImage = __webpack_require__(1);
var _arrayBufferToImage2 = _interopRequireDefault(_arrayBufferToImage);
var _createImage = __webpack_require__(2);
var _createImage2 = _interopRequireDefault(_createImage);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
// //
// This is a cornerstone image loader for web images such as PNG and JPEG // This is a cornerstone image loader for web images such as PNG and JPEG
// //
var options = {
// callback allowing customization of the xhr (e.g. adding custom auth headers, cors, etc)
beforeSend: function beforeSend() /* xhr */{}
};
(function ($, cornerstone, cornerstoneWebImageLoader) { // Loads an image given a url to an image
function loadImage(imageId) {
var deferred = $.Deferred();
"use strict"; var xhr = new XMLHttpRequest();
var canvas = document.createElement('canvas'); xhr.open('GET', imageId, true);
var lastImageIdDrawn = ""; xhr.responseType = 'arraybuffer';
options.beforeSend(xhr);
xhr.onload = function () {
var imagePromise = (0, _arrayBufferToImage2.default)(this.response);
var options = { imagePromise.then(function (image) {
// callback allowing customization of the xhr (e.g. adding custom auth headers, cors, etc) var imageObject = (0, _createImage2.default)(image, imageId);
beforeSend : function(xhr) {}
};
function createImageObject(image, imageId) deferred.resolve(imageObject);
{ }, function (error) {
// extract the attributes we need deferred.reject(error);
var rows = image.naturalHeight; });
var columns = image.naturalWidth; };
xhr.onprogress = function (oProgress) {
function getPixelData() if (oProgress.lengthComputable) {
{ // evt.loaded the bytes browser receive
var imageData = getImageData(); // evt.total the total bytes seted by the header
var imageDataData = imageData.data; //
var numPixels = image.naturalHeight * image.naturalWidth; var loaded = oProgress.loaded;
var storedPixelData = new Uint8Array(numPixels * 4); var total = oProgress.total;
var imageDataIndex = 0; var percentComplete = Math.round(loaded / total * 100);
var storedPixelDataIndex = 0;
for(var i=0; i < numPixels; i++) {
storedPixelData[storedPixelDataIndex++] = imageDataData[imageDataIndex++];
storedPixelData[storedPixelDataIndex++] = imageDataData[imageDataIndex++];
storedPixelData[storedPixelDataIndex++] = imageDataData[imageDataIndex++];
storedPixelData[storedPixelDataIndex++] = 255; // alpha
imageDataIndex++;
}
return storedPixelData;
}
function getImageData() $(cornerstone.events).trigger('CornerstoneImageLoadProgress', {
{ imageId: imageId,
var context; loaded: loaded,
if(lastImageIdDrawn !== imageId) { total: total,
canvas.height = image.naturalHeight; percentComplete: percentComplete
canvas.width = image.naturalWidth; });
context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
lastImageIdDrawn = imageId;
}
else {
context = canvas.getContext('2d');
}
return context.getImageData(0, 0, image.naturalWidth, image.naturalHeight);
}
function getCanvas()
{
if(lastImageIdDrawn === imageId) {
return canvas;
}
canvas.height = image.naturalHeight;
canvas.width = image.naturalWidth;
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
lastImageIdDrawn = imageId;
return canvas;
}
function getImage()
{
return image;
}
// Extract the various attributes we need
return {
imageId : imageId,
minPixelValue : 0, // calculated below
maxPixelValue : 255, // calculated below
slope: 1.0,
intercept: 0,
windowCenter : 128,
windowWidth : 255,
render: cornerstone.renderColorImage,
getPixelData: getPixelData,
getImageData: getImageData,
getCanvas: getCanvas,
getImage: getImage,
//storedPixelData: extractStoredPixels(image),
rows: rows,
columns: columns,
height: rows,
width: columns,
color: true,
columnPixelSpacing: undefined,
rowPixelSpacing: undefined,
invert: false,
sizeInBytes : rows * columns * 4 // we don't know for sure so we over estimate to be safe
};
} }
};
xhr.send();
// Loads an image given a url to an image return deferred.promise();
function loadImage(imageId) { }
// create a deferred object function configure(opts) {
var deferred = $.Deferred(); options = opts;
}
var image = new Image(); /***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
var xhr = new XMLHttpRequest(); "use strict";
xhr.open("GET", imageId, true);
xhr.responseType = "arraybuffer";
options.beforeSend(xhr);
xhr.onload = function() {
var arrayBufferView = new Uint8Array(this.response);
var blob = new Blob([arrayBufferView], {type: "image/jpeg"});
var urlCreator = window.URL || window.webkitURL;
var imageUrl = urlCreator.createObjectURL(blob);
image.src = imageUrl;
image.onload = function() {
var imageObject = createImageObject(image, imageId);
deferred.resolve(imageObject);
urlCreator.revokeObjectURL(imageUrl);
};
image.onerror = function() {
urlCreator.revokeObjectURL(imageUrl);
deferred.reject();
};
};
xhr.onprogress = function(oProgress) {
if (oProgress.lengthComputable) { //evt.loaded the bytes browser receive
//evt.total the total bytes seted by the header
//
var loaded = oProgress.loaded;
var total = oProgress.total;
var percentComplete = Math.round((loaded / total)*100);
$(cornerstone).trigger('CornerstoneImageLoadProgress', { Object.defineProperty(exports, "__esModule", {
imageId: imageId, value: true
loaded: loaded, });
total: total, exports.configure = exports.loadImage = exports.createImage = exports.arrayBufferToImage = undefined;
percentComplete: percentComplete
});
}
};
xhr.send();
return deferred.promise();
}
function configure(opts) { var _arrayBufferToImage = __webpack_require__(1);
options = opts;
}
// steam the http and https prefixes so we can use standard web urls directly var _arrayBufferToImage2 = _interopRequireDefault(_arrayBufferToImage);
cornerstone.registerImageLoader('http', loadImage);
cornerstone.registerImageLoader('https', loadImage); var _createImage = __webpack_require__(2);
cornerstoneWebImageLoader.configure = configure;
return cornerstone; var _createImage2 = _interopRequireDefault(_createImage);
}($, cornerstone, cornerstoneWebImageLoader));
var _loadImage = __webpack_require__(3);
var _cornerstoneCore = __webpack_require__(0);
var cornerstone = _interopRequireWildcard(_cornerstoneCore);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.arrayBufferToImage = _arrayBufferToImage2.default;
exports.createImage = _createImage2.default;
exports.loadImage = _loadImage.loadImage;
exports.configure = _loadImage.configure;
// Register the http and https prefixes so we can use standard web urls directly
cornerstone.registerImageLoader('http', _loadImage.loadImage);
cornerstone.registerImageLoader('https', _loadImage.loadImage);
/***/ })
/******/ ]);
});
//# sourceMappingURL=cornerstoneWebImageLoader.js.map