| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585 |
- <template>
- <div class="page" data-name="home-measure">
- <div class="iimt-top-container iimt-hexpand">
- <div class="home-patient-data-grid" style="flex-direction:row; padding-bottom: 0px; height: calc(100% - 16px);">
- <div class="iimt-frame" style="width:200px; height:calc(100% - 2px); ">
- <div class="title"><span>{{js "global.tr[global.lang].measure.media"}}</span></div>
- <div class="content" style="margin-top:8px; flex-direction: column; justify-content: flex-start; overflow-y:scroll;">
- {{#each media}}
- <a href="#" @click="setMedia({{@index}})" class="flex column centerh measure-media" style="min-height:fit-content; height:auto; position:relative;">
- {{#js_if "this.metrics.fps"}}
- {{#js_if "this.filename.indexOf('.dicom')===-1"}}
- <video id="media{{@index}}" src="{{js "app.data.config.storageBaseURL+'/media/'+app.data.patient.visitID+'/'+this.filename"}}" style="max-width:calc(100% - 16px);"></video>
- {{else}}
- <video id="media{{@index}}" src="{{js "app.data.config.storageBaseURL+'/media/'+app.data.patient.visitID+'/'+this.filename.replace('.dicom','.mp4')"}}" style="max-width:calc(100% - 16px);"></video>
- {{/js_if}}
- <img src="static/images/lens.png" style="position:absolute; top:0; right:0;">
- {{else}}
- {{#js_if "this.filename.indexOf('.dicom')===-1"}}
- <img id="media{{@index}}" src="{{js "app.data.config.storageBaseURL+'/media/'+app.data.patient.visitID+'/'+this.filename"}}" style="max-width:calc(100% - 16px);">
- {{else}}
- <img id="media{{@index}}" src="{{js "app.data.config.storageBaseURL+'/media/'+app.data.patient.visitID+'/'+this.filename.replace('.dicom','.jpeg')"}}" style="max-width:calc(100% - 16px);">
- {{/js_if}}
- {{/js_if}}
- <span id="media-description{{@index}}" class="iimt-subtitle">
- {{js "eval('global.tr[global.lang].arteries.'+../area+'.'+(this.side.length?this.side+'.':'')+this.location)"}}
- </span>
- </a>
- {{/each}}
- </div>
- </div>
- <div style="display:flex; flex-shrink:1; flex-direction:column; width:calc(100% - 200px - 200px - 34px); height: 100%; flex-wrap: nowrap; margin:0 16px;">
- <div class="iimt-frame-grow" style="margin-bottom:16px; position:relative;">
- <div class="flex row centerh centerv" style="height: 32px; position:absolute; top:0px; width:100%;">
- <img src='{{js "'static/images/gender_'+this.patient.gender+'.png'"}}' style="height: 22px;"> {{patient.lastname}} {{patient.firstname}}
- </div>
- <div id="mouseCoord" style="position: absolute; top:0px; right:0px; padding-right:2px; color:gray;"></div>
- <div class="title"><span>{{js "global.tr[global.lang].measure.image"}}</span></div>
- <div class="content" style="margin-top:8px; flex-direction: column; justify-content: flex-start;">
- <span id="media-description" class="iimt-subtitle"></span>
- <div id="media-container" style="position: relative; margin-bottom: 8px;">
- <video id="measure-video" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 100;"></video>
- <canvas id="measure-canvas" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 102;" @dblclick="dblclick" @mousedown="mousedown" @mouseup="mouseup" @mouseout="mouseout" @mousemove="mousemove"></canvas>
- </div>
- </div>
- </div>
- <div class="iimt-frame-grow" style="overflow: hidden; height:75px;">
- <div class="title"><span>{{js "global.tr[global.lang].measure.measures"}}</span></div>
- <div class="content" style="margin-top:0px; flex-direction: column; justify-content: flex-start;">
- <div class="data-table">
- <table id="measure-list">
- <!--thead class="iimt-small-row">
- <tr>
- <th class="label-cell" style="width: 200px;">{{js "global.tr[global.lang].measure.type"}}</th>
- <th class="label-cell">{{js "global.tr[global.lang].measure.values"}}</th>
- </tr>
- </thead-->
- <tbody class="iimt-small-row" style="overflow-y: unset;">
- </tbody>
- </table>
- </div>
- </div>
- </div>
-
- </div>
- <div style="display:flex; flex-shrink:1; flex-direction:column; width:200px; height: 100%;">
- <div class="iimt-frame" style="height: 72px; margin-bottom: 16px;">
- <div class="title"><span>{{js "global.tr[global.lang].measure.tools"}}</span></div>
- <div class="content" style="margin-top:8px; flex-direction: column; justify-content: flex-start;">
- <a href="#" id="measure-calibration" class="button iimt-button disabled" style="width:calc(100% - 16px);" @click="calibrationAction">{{js "global.tr[global.lang].measure.calibration"}}</a>
- </div>
- </div>
- <div class="iimt-frame" style="height: 210px; margin-bottom: 16px;">
- <div class="title"><span>{{js "global.tr[global.lang].measure.measures"}}</span></div>
- <div class="content" style="margin-top:8px; flex-direction: column; justify-content: space-around;">
- <a href="#" id="measure-imt" class="button iimt-button disabled" style="width:calc(100% - 16px);" @click="imtAction">{{js "global.tr[global.lang].measure.imt"}}</a>
- <a href="#" id="measure-plaque" class="button iimt-button disabled" style="width:calc(100% - 16px);" @click="plaqueAction">{{js "global.tr[global.lang].measure.plaque"}}</a>
- <a href="#" id="measure-distance" class="button iimt-button disabled" style="width:calc(100% - 16px);" @click="distanceAction">{{js "global.tr[global.lang].measure.distance"}}</a>
- <a href="#" id="measure-area" class="button iimt-button disabled" style="width:calc(100% - 16px);" @click="areaAction">{{js "global.tr[global.lang].measure.area"}}</a>
- </div>
- </div>
- <div class="iimt-frame" style="margin-bottom: 16px; height:calc(100% - 74px - 212px - 78px - 50px);">
- <div class="title"><span>{{js "global.tr[global.lang].measure.segment"}}</span></div>
- <div id="media-segment" class="content" style="margin-top:8px; flex-direction: column; justify-content: flex-start;">
- </div>
- </div>
- <div class="iimt-frame" style="height: 76px;">
- <div class="title"><span>{{js "global.tr[global.lang].measure.data"}}</span></div>
- <div class="content" style="margin-top:8px; flex-direction: column; justify-content: flex-start;">
- <a href="#" @click="allMeasures" class="button iimt-button" style="width:calc(100% - 16px);">{{js "global.tr[global.lang].measure.allMeasures"}}</a>
- </div>
- </div>
-
- </div>
- </div>
- </div>
- </div>
- </template>
- <script>
- export default {
- on: {
- pageInit: function() {
- $$('.measure-media').removeClass('active');
- $$('#media0').parent().addClass('active');
- $$('#media-description').text($$('#media-description0').text());
- $$('#media0').parent().click();
- this.actionStatus = null;
- this.points = [];
- this.updateMeasureList();
- }
- },
- methods: {
- scaleIn: function(x) {
- return Math.round(x / this.zoom);
- },
- scaleOut: function(x) {
- return Math.round(x * this.zoom);
- },
- updateButtonStates: function() {
- $$('#measure-calibration').removeClass('disabled');
- $$('#measure-imt').removeClass('disabled');
- $$('#measure-plaque').removeClass('disabled');
- $$('#measure-distance').removeClass('disabled');
- $$('#measure-area').removeClass('disabled');
- if(this.media[this.currentMediaIndex].metrics.pxwidth==0 || this.media[this.currentMediaIndex].metrics.pxheight==0) {
- $$('#measure-imt').addClass('disabled');
- $$('#measure-plaque').addClass('disabled');
- $$('#measure-distance').addClass('disabled');
- $$('#measure-area').addClass('disabled');
- }
- let isDicom = (this.media[this.currentMediaIndex].filename.indexOf('.dicom')!==-1);
- if(isDicom &&
- (this.media[this.currentMediaIndex].metrics.pxwidth!=0 && this.media[this.currentMediaIndex].metrics.pxheight!=0)) {
- $$('#measure-calibration').addClass('disabled');
- }
- else {
- let onlyCalibration = true;
- for(let i=0; i<this.media[this.currentMediaIndex].measure.length; ++i) {
- if(this.media[this.currentMediaIndex].measure[i].type!='calibration') {
- onlyCalibration = false;
- }
- }
- if(!onlyCalibration) {
- $$('#measure-calibration').addClass('disabled');
- }
- }
- },
- getImageData: function() {
- // video
- if(this.videoViewer) {
- let ctx = $$('#measure-canvas')[0].getContext('2d');
- ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-
- ctx.scale(this.zoom, this.zoom);
- ctx.drawImage(this.currentMedia, 0, 0);
- this.imageData = ctx.getImageData(0, 0, this.imgWidth, this.imgHeight);
- ctx.setTransform(1, 0, 0, 1, 0, 0);
- this.update();
- return this.imageData;
- }
- // image
- return this.imageData;
- },
- setMedia: function(idx) {
- console.log('set media', this.media[idx]);
- let that = this;
- $$('.measure-media').removeClass('active');
- $$('#media'+idx).parent().addClass('active');
- $$('#media-description').text($$('#media-description'+idx).text());
- let media = $$('#media'+idx);
- let img = null;
- let container = $$('#media-container');
- let video = $$('video#measure-video');
- video[0].setAttribute('crossOrigin', '');
- let canvas = $$('canvas#measure-canvas');
- let maxW = 768;
- let maxH = 520;
- // cleanup
- if(this.videoViewer) {
- console.log('clean video viewer');
- this.videoViewer.clean();
- delete this.videoViewer;
- this.videoViewer = null;
- }
- // load
- let ctx = canvas[0].getContext('2d');
- // video
- if(this.media[idx].metrics.fps) {
- // load
- video.on('loadeddata', function() {
- that.zoom = 1.0 / (video[0].videoHeight/maxH);
- that.imgWidth = that.scaleOut(video[0].videoWidth);
- that.imgHeight = that.scaleOut(video[0].videoHeight);
- console.log('zoom', that.zoom);
- container.css({
- width: that.imgWidth+'px',
- height: that.imgHeight+'px'
- });
- canvas.css({
- width: that.imgWidth+'px',
- height: that.imgHeight+'px'
- });
- ctx.canvas.width=that.imgWidth;
- ctx.canvas.height=that.imgHeight;
- that.videoViewer = new global.VideoViewer(video, that.media[idx].metrics.fps, that.media[idx].metrics.frameCount, that.videoFrameChanged);
- that.currentMedia = video[0];
- that.update();
- video.off('loadeddata');
- });
- }
- // image
- else {
- img = new Image();
- img.setAttribute('crossOrigin', '');
- img.onload = function() {
- that.zoom = 1.0 / (img.height/maxH);
- that.imgWidth = that.scaleOut(img.width);
- that.imgHeight = that.scaleOut(img.height);
- console.log('zoom', that.zoom);
- container.css({
- width: that.imgWidth+'px',
- height: that.imgHeight+'px'
- });
- canvas.css({
- width: that.imgWidth+'px',
- height: that.imgHeight+'px'
- });
- ctx.canvas.width=that.imgWidth;
- ctx.canvas.height=that.imgHeight;
- ctx.scale(that.zoom, that.zoom);
- ctx.drawImage(img, 0, 0);
- that.imageData = ctx.getImageData(0, 0, that.imgWidth, that.imgHeight);
- ctx.setTransform(1, 0, 0, 1, 0, 0);
- that.currentMedia = img;
- that.update();
- };
- }
- this.currentMediaIndex = idx;
-
- this.calibrationHover = null;
- // DICOM
- if(this.media[idx].filename.indexOf('.dicom')!==-1) {
- //console.log('dicom', this.media[idx]);
- this.addDicomCalibration(idx);
- }
- //
- that.updateButtonStates();
- that.mouseout();
- // segment
- let path = 'area_'+this.area+'_'+(this.media[idx].side=='left'?'L':(this.media[idx].side=='right'?'R':'R'))+'_'+this.media[idx].location+'.png';
- $$('#media-segment').html('<img src="static/images/'+path+'" style="max-height:90%; max-width:90%;">');
- this.updateMeasureList();
- // load media
- if(img) {
- img.src = media.attr('src');
- }
- else {
- video.attr('src', media.attr('src'));
- }
- },
- addDicomCalibration: function(idx) {
- let hasCalibration = false;
- for(let m=0; m<this.media[idx].measure.length; ++m) {
- if(this.media[idx].measure[m].type=='calibration') {
- hasCalibration = true;
- break;
- }
- }
- if(!hasCalibration && this.media[idx].metrics.pxwith!=0 && this.media[idx].metrics.pxheight!=0) {
- this.media[idx].measure.push({
- ID: 0,
- type: 'calibration',
- computation: {
- distance: 20
- },
- fk_media: 0,
- fk_user: 0,
- points: [{
- x: this.media[idx].metrics.width-40,
- y: 50
- }, {
- x: this.media[idx].metrics.width-40,
- y: (50 + 20 / this.media[idx].metrics.pxheight)
- }]
- });
- }
- },
- updateMeasureList: function() {
- let txt = '';
- let isDicom = (this.media[this.currentMediaIndex].filename.indexOf('.dicom')!==-1);
- for (let i=0; i<this.media[this.currentMediaIndex].measure.length; ++i) {
- let style = '';
- let M = this.media[this.currentMediaIndex].measure[i];
- //console.log(M);
- let type = '';
- /*if(M.type=='calibration') type = global.tr[global.lang].measure.calibration;
- else */if(M.type=='area') type = global.tr[global.lang].measure.area;
- else if(M.type=='thickness') type = global.tr[global.lang].measure.thickness;
- else if(M.type=='diameter') type = global.tr[global.lang].measure.diameter;
- else if(M.type=='plaque_thickness') type = global.tr[global.lang].measure.plaqueThickness;
- else if(M.type=='imt') type = global.tr[global.lang].measure.imt;
- else if(M.type=='plaque') type = global.tr[global.lang].measure.plaque;
- let data = '';
- /*if(M.type=='calibration') data += parseFloat(M.computation.distance).toFixed(0)+' mm';
- else */if (M.type=='thickness' || M.type=='diameter' || M.type=='plaque_thickness') data += parseFloat(M.computation.distance).toFixed(2)+' mm';
- else if(M.type=='area') data += parseFloat(M.computation.surface).toFixed(2)+' mm²';
- else if(M.type=='imt') {
- data += global.tr[global.lang].measure.imtDist+': '+parseFloat(M.computation.distance).toFixed(2)+' mm, ';
- data += global.tr[global.lang].measure.imtMean+': '+parseFloat(M.computation.imt_mean).toFixed(3)+' mm, ';
- data += global.tr[global.lang].measure.imtStddev+': '+parseFloat(M.computation.imt_stddev).toFixed(2)+' mm, ';
- data += global.tr[global.lang].measure.imtMax+': '+parseFloat(M.computation.imt_max).toFixed(3)+' mm, ';
- data += global.tr[global.lang].measure.imtIQ+': '+parseFloat(M.computation.qualityIndex).toFixed(2)+', ';
- data += global.tr[global.lang].measure.imtPoints+': '+M.computation.numberOfPoints+', ';
- data += (M.computation.nearWall?global.tr[global.lang].measure.imtProximal:global.tr[global.lang].measure.imtDistal);
- if(M.computation.qualityIndex<=0.3 || M.computation.distance<=8) {
- style = 'style="color: red;"';
- }
- }
- else if(M.type=='plaque') {
- data += global.tr[global.lang].measure.plaqueArea+': '+parseFloat(M.computation.plaque_area).toFixed(2)+' mm², ';
- //data += global.tr[global.lang].measure.plaqueMean+': '+parseFloat(M.computation.plaque_mean_density).toFixed(0)+', ';
- data += global.tr[global.lang].measure.plaqueThkmax+': '+parseFloat(M.computation.plaque_max_thickness).toFixed(2)+' mm, ';
- data += global.tr[global.lang].measure.plaqueThkmean+': '+parseFloat(M.computation.plaque_mean_thickness).toFixed(2)+' mm, ';
- data += global.tr[global.lang].measure.plaqueLength+': '+parseFloat((M.computation.longeantPlaque[M.computation.longeantPlaque.length-1].x-M.computation.longeantPlaque[0].x)*this.media[this.currentMediaIndex].metrics.pxwidth).toFixed(2)+' mm, ';
- data += global.tr[global.lang].measure.plaquePoints+': '+parseFloat(M.computation.numberOfMeasures).toFixed(0);
- }
- if(M.type!='calibration') {
- txt += '<tr>'+
- '<td class="label-cell" style="width: 160px; padding-right: 0px;">'+type+'</td>'+
- '<td class="label-cell" '+style+'>'+data+'</td>'+
- '</tr>';
- }
- }
- $$('#measure-list tbody').html('').html(txt);
- },
- allMeasures: function() {
- let txt = '';
- for (let media=0; media<this.media.length; ++media) {
- let mediaStr = '';
- if(this.media[media].metrics.fps) {
- if(this.media[media].filename.indexOf('.dicom')===-1) {
- mediaStr = '<video style="width:192px; padding:4px;" src="'+app.data.config.storageBaseURL+'/media/'+app.data.patient.visitID+'/'+this.media[media].filename+'"></video>';
- }
- else {
- mediaStr = '<video style="width:192px; padding:4px;" src="'+app.data.config.storageBaseURL+'/media/'+app.data.patient.visitID+'/'+this.media[media].filename.replace('.dicom','.mp4')+'"></video>';
- }
- }
- else {
- if(this.media[media].filename.indexOf('.dicom')===-1) {
- mediaStr = '<img style="width:192px; padding:4px;" src="'+app.data.config.storageBaseURL+'/media/'+app.data.patient.visitID+'/'+this.media[media].filename+'">';
- }
- else {
- mediaStr = '<img style="width:192px; padding:4px;" src="'+app.data.config.storageBaseURL+'/media/'+app.data.patient.visitID+'/'+this.media[media].filename.replace('.dicom','.jpeg')+'">';
- }
- }
-
- let loc = eval('global.tr[global.lang].arteries.'+this.area+'.'+(this.media[media].side.length?this.media[media].side+'.':'')+this.media[media].location);
- console.log(loc);
- let tab = loc.split(' ');
- let locT = [];
- for(let t=0; t<tab.length; t++) {
- locT.push(tab[t].toUpperCase().charAt(0));
- }
- let calibration = '';
- for (let i=0; i<this.media[media].measure.length; ++i) {
- let M = this.media[media].measure[i];
- if(M.type=='calibration') {
- calibration = parseFloat(M.computation.distance).toFixed(0)+' mm';
- }
- }
- for (let i=0; i<this.media[media].measure.length; ++i) {
- let mHead = '';
- let mData = '';
- let M = this.media[media].measure[i];
- if(M.type=='plaque') {
- mHead = '<tr>'+
- '<th style="padding:0; font-size:10px;">'+global.tr[global.lang].measure.plaqueArea+'</th>'+
- '<th style="padding:0; font-size:10px;">'+global.tr[global.lang].measure.plaqueThkmax+'</th></tr>';
- mData += '<tr>';
- mData += '<td style="padding:0; font-size:14px;">'+parseFloat(M.computation.plaque_area).toFixed(1)+' mm²</td>';
- mData += '<td style="padding:0; font-size:14px;">'+parseFloat(M.computation.plaque_max_thickness).toFixed(2)+' mm</td>';
- mData += '</tr>';
- }
- else if(M.type=='area') {
- mHead = '<tr>'+
- '<th style="padding:0; font-size:10px;">'+global.tr[global.lang].measure.area+'</th></tr>';
- mData += '<tr>';
- mData += '<td style="padding:0; font-size:14px;">'+parseFloat(M.computation.surface).toFixed(2)+' mm²</td>';
- mData += '</tr>';
- }
- else if(M.type=='thickness') {
- mHead = '<tr>'+
- '<th style="padding:0; font-size:10px;">'+global.tr[global.lang].measure.thickness+'</th></tr>';
- mData += '<tr>';
- mData += '<td style="padding:0; font-size:14px;">'+parseFloat(M.computation.distance).toFixed(2)+' mm</td>';
- mData += '</tr>';
- }
- else if(M.type=='diameter') {
- mHead = '<tr>'+
- '<th style="padding:0; font-size:10px;">'+global.tr[global.lang].measure.diameter+'</th></tr>';
- mData += '<tr>';
- mData += '<td style="padding:0; font-size:14px;">'+parseFloat(M.computation.distance).toFixed(2)+' mm</td>';
- mData += '</tr>';
- }
- else if(M.type=='plaque_thickness') {
- mHead = '<tr>'+
- '<th style="padding:0; font-size:10px;">'+global.tr[global.lang].measure.plaque_thickness+'</th></tr>';
- mData += '<tr>';
- mData += '<td style="padding:0; font-size:14px;">'+parseFloat(M.computation.distance).toFixed(2)+' mm</td>';
- mData += '</tr>';
- }
- else if(M.type=='imt') {
- mHead = '<tr>'+
- '<th style="padding:0; font-size:10px;">'+global.tr[global.lang].measure.imtMean+'</th>'+
- '<th style="padding:0; font-size:10px;">'+global.tr[global.lang].measure.imtMax+'</th>'+
- '<th style="padding:0; font-size:10px;">'+global.tr[global.lang].measure.imtStddev+'</th>'+
- '<th style="padding:0; font-size:10px;">'+global.tr[global.lang].measure.imtIQ+'</th>'+
- '<th style="padding:0; font-size:10px;">'+global.tr[global.lang].measure.imtDist+'</th>'+
- '<th style="padding:0; font-size:10px;">'+global.tr[global.lang].measure.imtPoints+'</th></tr>';
- mData += '<tr>';
- mData += '<td style="padding:0; font-size:14px;">'+parseFloat(M.computation.imt_mean).toFixed(3)+' mm</td>';
- mData += '<td style="padding:0; font-size:14px;">'+parseFloat(M.computation.imt_max).toFixed(3)+' mm</td>';
- mData += '<td style="padding:0; font-size:14px;">'+parseFloat(M.computation.imt_stddev).toFixed(3)+' mm</td>';
- mData += '<td style="padding:0; font-size:14px;">'+parseFloat(M.computation.qualityIndex).toFixed(3)+'</td>';
- mData += '<td style="padding:0; font-size:14px;">'+parseFloat(M.computation.distance).toFixed(3)+' mm</td>';
- mData += '<td style="padding:0; font-size:14px;">'+M.computation.numberOfPoints+'</td>';
- mData += '</tr>';
- }
- if(mHead.length) {
- txt += '<tr>'+
- '<td class="" style="width: 200px; padding: 0;">'+mediaStr+'</td>'+
- '<td class="" style="width: 20px; padding: 0; font-weight: 600;">'+locT.join('<br>')+'</td>'+
- '<td class="" style="padding: 0;"><table><thead style="overflow-y:hidden;">'+mHead+'</thead><tbody style="overflow-y:hidden;">'+mData+'</tbody></table></td>'+
- '<td class="" style="width: 70px; padding: 0;">'+calibration+'</td>'+
- '</tr>';
- }
- }
- }
- let completed = '';
- if(global.app.data.user.type=='reader') {
- completed += '<div class="row" style="justify-content:center">';
- completed += '<a id="complete-timepoint" href="#" class="button button-fill color-theme-red" style="font-weight: 600;">'+global.tr[global.lang].measure.complete+'</a>';
- completed += '</div>';
- }
- // Create dynamic Popup
- app.popup.create({
- content: '<div class="popup measures">'+
- '<div class="dialog-title" style="display:flex; flex-shrink:1; justify-content:space-between;">'+global.tr[global.lang].measure.allMeasures+' <a href="#" class="link popup-close" style="color:white; padding-right:8px;">'+global.tr[global.lang].topLevel.close+'</a></div>'+
- '<div class="block" style="margin:0; height: calc(100% - 24px); overflow-y: scroll;">'+
- '<div class="data-table">'+
- '<table>'+
- '<thead class="iimt-small-row">'+
- '<tr>'+
- '<th class="" style="width: 200px; padding: 0;">Media</th>'+
- '<th class="" style="width: 20px; padding: 0;"> </th>'+
- '<th class="" style="padding: 0;">'+global.tr[global.lang].measure.measures+'</th>'+
- '<th class="" style="width: 70px; padding: 0;">'+global.tr[global.lang].measure.calibration+'</th>'+
- '</tr>'+
- '</thead>'+
- '<tbody class="iimt-small-row" style="overflow-y: unset;">'+
- txt+
- '</tbody>'+
- '</table>'+
- completed+
- '</div>'+
- '</div>'+
- '</div>',
- on: {
- opened: function () {
- let comp = $$("#complete-timepoint");
- if(comp) {
- comp.click(function() {
- app.dialog.password(global.tr[global.lang].measure.confirmPassword, null, function(password) {
- let postData = {
- password: password,
- visitID: app.data.patient.visitID,
- apiKey: ''
- };
- app.preloader.show();
- app.request.post(app.data.config.apiBaseURL + '/measure/complete/', postData, function (data) {
- console.log('measure/complete', data);
- app.preloader.hide();
- if (data.result == 'ERROR') {
- switch (data.reason) {
- case 'denied':
- app.methods.signout(global.tr[global.lang].topLevel.warning.disconnected);
- break;
- case 'bad_password':
- app.dialog.alert(global.tr[global.lang].topLevel.error.wrong_credentials);
- break;
- default:
- app.dialog.alert(global.tr[global.lang].topLevel.error.internal_error);
- break;
- }
- }
- else {
- app.popup.close();
- // return to patient
- $$('#toolbar-patient').click();
- }
- }, function (data) {
- console.log('error', data);
- }, 'json');
- });
- });
- }
- }
- }
- }).open();
- },
- videoFrameChanged: function(frame) {
- console.log(frame);
- console.log(this);
- this.update();
- },
- update: function() {
- let ctx = $$('#measure-canvas')[0].getContext('2d');
- ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
- ctx.scale(this.zoom, this.zoom);
- if(!this.videoViewer) {
- ctx.drawImage(this.currentMedia, 0, 0/*, ctx.canvas.width, ctx.canvas.height*/);
- }
- if(global.app.data.user.type=='reader' && this.anon_percent!=0) {
- ctx.fillStyle = "#000000";
- ctx.fillRect(0, 0, ctx.canvas.width/this.zoom, (ctx.canvas.height/100*this.anon_percent)/this.zoom);
- }
- console.log("actionStatus", this.actionStatus);
- console.log(this.media[this.currentMediaIndex].measure);
- // drawing calibration
- if((this.actionStatus=='calibration' && this.points.length==2) || this.actionStatus=='calibrationConfirm') {
- this.drawCalibation(ctx, this.points, null);
- }
- // drawing distance
- if(this.actionStatus=='distance' && this.points.length==2) {
- this.drawDistance(ctx, this.points, null);
- }
- // drawing area
- if(this.actionStatus=='area' && this.points.length>=2) {
- this.drawArea(ctx, this.points, null);
- }
- // drawing imt
- if(this.actionStatus=='imt' && this.points.length==2) {
- this.drawImt(ctx, this.points, null);
- }
- // drawing plaque
- if((this.actionStatus=='plaque' || this.actionStatus=='plaque2') && this.points.length>=2) {
- this.drawPlaque(ctx, this.points, null);
- }
- // known measures
- for(let i=0; i<this.media[this.currentMediaIndex].measure.length; ++i) {
- let M = this.media[this.currentMediaIndex].measure[i];
- if(M.type=='calibration') {
- if(this.actionStatus!='calibration' && this.actionStatus!='calibrationConfirm') {
- this.drawCalibation(ctx, M.points, M.computation);
- }
- }
- else if(!this.videoViewer || (this.videoViewer && M.frame==this.videoViewer.currentFrame)) {
- if(!this.actionStatus && (M.type=='thickness' || M.type=='diameter' || M.type=='plaque_thickness')) {
- this.drawDistance(ctx, M.points, M.computation);
- }
- else if(!this.actionStatus && M.type=='area') {
- this.drawArea(ctx, M.points, M.computation);
- }
- else if(!this.actionStatus && M.type=='imt') {
- this.drawImt(ctx, M.points, M.computation);
- }
- else if(!this.actionStatus && M.type=='plaque') {
- this.drawPlaque(ctx, M.points, M.computation);
- }
- }
- }
- ctx.setTransform(1, 0, 0, 1, 0, 0);
- },
- drawImt: function(ctx, points, computation) {
- if(computation) {
- for(let i=0; i<4; i++) {
- ctx.strokeStyle = '#00ff00';
- for(let p=0; p<computation.vect_adventitia.length; ++p) {
- ctx.beginPath();
- ctx.moveTo(computation.vect_adventitia[p].x , computation.vect_adventitia[p].y);
- ctx.lineTo(computation.vect_adventitia[p].x+1, computation.vect_adventitia[p].y);
- ctx.stroke();
- }
- ctx.strokeStyle = '#FFA500';
- for(let p=0; p<computation.vect_intima.length; ++p) {
- ctx.beginPath();
- ctx.moveTo(computation.vect_intima[p].x , computation.vect_intima[p].y);
- ctx.lineTo(computation.vect_intima[p].x+1, computation.vect_intima[p].y);
- ctx.stroke();
- }
- }
- /*ctx.strokeStyle = '#00ffff';
- for(let p=0; p<computation.vect_media.length; ++p) {
- ctx.beginPath();
- ctx.moveTo(computation.vect_media[p].x, computation.vect_media[p].y);
- ctx.lineTo(computation.vect_media[p].x+1, computation.vect_media[p].y);
- ctx.stroke();
- }*/
- /*let pa = computation.vect_intima[computation.vect_intima.length-1];
- let pm = computation.vect_media[computation.vect_media.length-1];
- let imt_mean = Math.round(computation.imt_mean*100)/100;
- ctx.font = '16px sans-serif';
- ctx.textAlign = 'left';
- ctx.strokeStyle = '#FFA500';
- ctx.strokeText(imt_mean+' mm', Math.max(pa.x,pm.x)+8, (pa.y+pm.y)/2+8);
- ctx.fillStyle = "#00ff00";
- ctx.fillText(imt_mean+' mm', Math.max(pa.x,pm.x)+8, (pa.y+pm.y)/2+8);*/
- }
- else {
- let pxwidth = this.media[this.currentMediaIndex].metrics.pxwidth;
- let pxheight = this.media[this.currentMediaIndex].metrics.pxheight;
- let pts=[{x:points[0].x*pxwidth, y:points[0].y*pxheight}, {x:points[1].x*pxwidth, y:points[1].y*pxheight}];
- let distance = global.improc.distance(pts[0], pts[1]);
- console.log(distance);
- for(let i=0; i<4; i++) {
- ctx.strokeStyle = distance<10?'#ff0000':'#00ff00';
- ctx.beginPath();
- ctx.moveTo(points[0].x, points[0].y);
- ctx.lineTo(points[1].x, points[1].y);
- ctx.stroke();
- ctx.fillStyle = '#FFA500';
- ctx.beginPath();
- ctx.arc(points[0].x, points[0].y, 3, 0, Math.PI * 2, true);
- ctx.fill();
- ctx.beginPath();
- ctx.arc(points[1].x, points[1].y, 3, 0, Math.PI * 2, true);
- ctx.fill();
- }
- }
- },
- drawPlaque: function(ctx, points, computation) {
- if(computation) {
- let lw = ctx.lineWidth;
- ctx.lineWidth = 2;
- for(let i=0; i<4; i++) {
- for(let p=0; p<computation.longeantPlaque.length-1; p++) {
- ctx.beginPath();
- ctx.moveTo(computation.longeantPlaque[p].x, computation.longeantPlaque[p].y);
- ctx.lineTo(computation.longeantPlaque[p+1].x, computation.longeantPlaque[p+1].y);
- ctx.strokeStyle = '#FFA500';
- ctx.stroke();
- }
- }
- ctx.lineWidth = lw;
- for(let i=0; i<4; i++) {
- for(let p=0; p<computation.ptsTrouvesFin.length-1; p++) {
- ctx.beginPath();
- ctx.moveTo(computation.ptsTrouvesFin[p].x, computation.ptsTrouvesFin[p].y);
- ctx.lineTo(computation.ptsTrouvesFin[p+1].x, computation.ptsTrouvesFin[p+1].y);
- ctx.strokeStyle = '#00ff00';
- ctx.stroke();
- }
- ctx.beginPath();
- ctx.moveTo(computation.longeantPlaque[0].x, computation.longeantPlaque[0].y);
- ctx.lineTo(computation.ptsTrouvesFin[0].x, computation.ptsTrouvesFin[0].y);
- ctx.strokeStyle = '#00ff00';
- ctx.stroke();
- ctx.beginPath();
- ctx.moveTo(computation.longeantPlaque[computation.longeantPlaque.length-1].x, computation.longeantPlaque[computation.longeantPlaque.length-1].y);
- ctx.lineTo(computation.ptsTrouvesFin[computation.ptsTrouvesFin.length-1].x, computation.ptsTrouvesFin[computation.ptsTrouvesFin.length-1].y);
- ctx.strokeStyle = '#00ff00';
- ctx.stroke();
- }
- }
- else {
- let sz = this.actionStatus=='plaque'?points.length-1:points.length-2;
- for(let i=0; i<4; i++) {
- for(let p=0; p<sz; p++) {
- ctx.beginPath();
- ctx.moveTo(points[p].x, points[p].y);
- ctx.lineTo(points[p+1].x, points[p+1].y);
- ctx.strokeStyle = '#00ff00';
- ctx.stroke();
- }
- }
- for(let i=0; i<4; i++) {
- for(let p=0; p<points.length-1; p++) {
- ctx.fillStyle = '#FFA500';
- ctx.beginPath();
- ctx.arc(points[p].x, points[p].y, 3, 0, Math.PI * 2, true);
- ctx.fill();
- ctx.beginPath();
- ctx.arc(points[p+1].x, points[p+1].y, 3, 0, Math.PI * 2, true);
- ctx.fill();
- }
- }
- }
- },
- drawCalibation: function(ctx, points, computation) {
- let isDicom = (this.media[this.currentMediaIndex].filename.indexOf('.dicom')!==-1);
- for(let i=0; i<4; i++) {
- ctx.beginPath();
- ctx.moveTo(points[0].x, points[0].y);
- ctx.lineTo(points[1].x, points[1].y);
- ctx.strokeStyle = isDicom?'#FFA500':'#00ff00';
- ctx.stroke();
- let step = 5/this.zoom;
- ctx.strokeStyle = '#FFA500';
- ctx.beginPath();
- ctx.moveTo(points[0].x-step, points[0].y);
- ctx.lineTo(points[0].x+step, points[0].y);
- ctx.stroke();
- ctx.beginPath();
- ctx.moveTo(points[1].x-step, points[1].y);
- ctx.lineTo(points[1].x+step, points[1].y);
- ctx.stroke();
- //ctx.beginPath();
- //ctx.arc(points[0].x, points[0].y, 3, 0, Math.PI * 2, true);
- //ctx.fill();
- //ctx.beginPath();
- //ctx.arc(points[1].x, points[1].y, 3, 0, Math.PI * 2, true);
- //ctx.fill();
- }
- if(computation) {
- let distance = Math.round(computation.distance);
- ctx.font = this.scaleIn(16)+'px sans-serif';
- ctx.textAlign = 'center';
- //ctx.strokeText(distance, points[0].x, points[0].y-18);
- ctx.fillStyle = isDicom?'#FFA500':'#00ff00';
- ctx.fillText(distance, points[0].x, points[0].y-18);
- }
- },
- drawDistance: function(ctx, points, computation) {
- for(let i=0; i<4; i++) {
- ctx.beginPath();
- ctx.moveTo(points[0].x, points[0].y);
- ctx.lineTo(points[1].x, points[1].y);
- ctx.strokeStyle = '#00ff00';
- ctx.stroke();
- ctx.fillStyle = '#FFA500';
- ctx.beginPath();
- ctx.arc(points[0].x, points[0].y, 3, 0, Math.PI * 2, true);
- ctx.fill();
- ctx.beginPath();
- ctx.arc(points[1].x, points[1].y, 3, 0, Math.PI * 2, true);
- ctx.fill();
- }
- let distance = 0;
- if(computation) {
- distance = Math.round(computation.distance*100)/100;
- }
- else {
- let pxwidth = this.media[this.currentMediaIndex].metrics.pxwidth;
- let pxheight = this.media[this.currentMediaIndex].metrics.pxheight;
- let pts=[{x:points[0].x*pxwidth, y:points[0].y*pxheight}, {x:points[1].x*pxwidth, y:points[1].y*pxheight}];
- distance = global.improc.distance(pts[0], pts[1]);
- distance = Math.round(distance*100)/100;
- }
- ctx.font = this.scaleIn(16)+'px sans-serif';
- ctx.textAlign = 'center';
- //ctx.strokeText(distance+' mm', points[0].x, points[0].y-18);
- ctx.fillStyle = "#00ff00";
- ctx.fillText(distance+' mm', points[0].x, points[0].y-18);
- },
- drawArea: function(ctx, points, computation) {
- for(let i=0; i<4; i++) {
- for(let p=0; p<points.length-1; p++) {
- ctx.beginPath();
- ctx.moveTo(points[p].x, points[p].y);
- ctx.lineTo(points[p+1].x, points[p+1].y);
- ctx.strokeStyle = '#00ff00';
- ctx.stroke();
- }
- }
- for(let i=0; i<4; i++) {
- ctx.beginPath();
- ctx.moveTo(points[points.length-1].x, points[points.length-1].y);
- ctx.lineTo(points[0].x, points[0].y);
- ctx.strokeStyle = '#00ff00';
- ctx.stroke();
- }
- for(let i=0; i<4; i++) {
- for(let p=0; p<points.length-1; p++) {
- ctx.fillStyle = '#FFA500';
- ctx.beginPath();
- ctx.arc(points[p].x, points[p].y, 3, 0, Math.PI * 2, true);
- ctx.fill();
- ctx.beginPath();
- ctx.arc(points[p+1].x, points[p+1].y, 3, 0, Math.PI * 2, true);
- ctx.fill();
- }
- }
- if(computation) {
- let surface = Math.round(computation.surface*100)/100;
- ctx.font = this.scaleIn(16)+'px sans-serif';
- ctx.textAlign = 'center';
- //ctx.strokeText(surface+' mm²', points[0].x, points[0].y-18);
- ctx.fillStyle = "#00ff00";
- ctx.fillText(surface+' mm²', points[0].x, points[0].y-18);
- }
- else if(points.length>=3) {
- let pxwidth = this.media[this.currentMediaIndex].metrics.pxwidth;
- let pxheight = this.media[this.currentMediaIndex].metrics.pxheight;
- let nbp = global.improc.surface(points, this.zoom);
- let surface = Math.round(nbp*pxwidth*pxheight*100)/100;
- ctx.font = this.scaleIn(16)+'px sans-serif';
- ctx.textAlign = 'center';
- //ctx.strokeText(surface+' mm²', points[0].x, points[0].y-18);
- ctx.fillStyle = "#00ff00";
- ctx.fillText(surface+' mm²', points[0].x, points[0].y-18);
- }
- },
- calibrationAction: function() {
- if(this.actionStatus=='calibration') {
- this.actionStatus=null;
- $$('#measure-calibration').removeClass('outlined');
- $$('#measure-imt').removeClass('outlined');
- $$('#measure-plaque').removeClass('outlined');
- $$('#measure-distance').removeClass('outlined');
- $$('#measure-area').removeClass('outlined');
- $$("body:hover").css({'cursor':'default'});
- }
- else if(this.actionStatus==null) {
- this.actionStatus='calibration';
- this.points = [];
- $$('#measure-calibration').addClass('outlined');
- $$("body:hover").css({'cursor':'url(\'static/images/cursor.png\') 8 8, auto'});
- }
- this.update();
- },
- imtAction: function() {
- // Specs changed later on here, so lets comment this for all measures, in case specs change back again
- //if(this.actionStatus=='imt') {
- this.actionStatus=null;
- $$('#measure-calibration').removeClass('outlined');
- $$('#measure-imt').removeClass('outlined');
- $$('#measure-plaque').removeClass('outlined');
- $$('#measure-distance').removeClass('outlined');
- $$('#measure-area').removeClass('outlined');
- $$("body:hover").css({'cursor':'default'});
- /*}
- else if(this.actionStatus==null) {*/
- this.actionStatus='imt';
- this.points = [];
- $$('#measure-imt').addClass('outlined');
- $$("body:hover").css({'cursor':'url(\'static/images/cursor.png\') 8 8, auto'});
- //}
- this.update();
- },
- plaqueAction: function() {
- //if(this.actionStatus=='plaque') {
- this.actionStatus=null;
- $$('#measure-calibration').removeClass('outlined');
- $$('#measure-imt').removeClass('outlined');
- $$('#measure-plaque').removeClass('outlined');
- $$('#measure-distance').removeClass('outlined');
- $$('#measure-area').removeClass('outlined');
- $$("body:hover").css({'cursor':'default'});
- /*}
- else if(this.actionStatus==null) {*/
- this.actionStatus='plaque';
- this.points = [];
- $$('#measure-plaque').addClass('outlined');
- $$("body:hover").css({'cursor':'url(\'static/images/cursor.png\') 8 8, auto'});
- //}
- this.update();
- },
- distanceAction: function() {
- //if(this.actionStatus=='distance') {
- this.actionStatus=null;
- $$('#measure-calibration').removeClass('outlined');
- $$('#measure-imt').removeClass('outlined');
- $$('#measure-plaque').removeClass('outlined');
- $$('#measure-distance').removeClass('outlined');
- $$('#measure-area').removeClass('outlined');
- $$("body:hover").css({'cursor':'default'});
- /*}
- else if(this.actionStatus==null) {*/
- this.actionStatus='distance';
- this.points = [];
- $$('#measure-distance').addClass('outlined');
- $$("body:hover").css({'cursor':'url(\'static/images/cursor.png\') 8 8, auto'});
- //}
- this.update();
- },
- areaAction: function() {
- //if(this.actionStatus=='area') {
- this.actionStatus=null;
- $$('#measure-calibration').removeClass('outlined');
- $$('#measure-imt').removeClass('outlined');
- $$('#measure-plaque').removeClass('outlined');
- $$('#measure-distance').removeClass('outlined');
- $$('#measure-area').removeClass('outlined');
- $$("body:hover").css({'cursor':'default'});
- /*}
- else if(this.actionStatus==null) {*/
- this.actionStatus='area';
- this.points = [];
- $$('#measure-area').addClass('outlined');
- $$("body:hover").css({'cursor':'url(\'static/images/cursor.png\') 8 8, auto'});
- //}
- this.update();
- },
- savePlaque: function(keepPlaques) {
- console.log('keepPlaques', keepPlaques);
- let that = this;
- let postData = {
- visitID: app.data.patient.visitID,
- filename: that.media[that.currentMediaIndex].filename,
- points: that.points,
- pxwidth: that.media[that.currentMediaIndex].metrics.pxwidth,
- pxheight: that.media[that.currentMediaIndex].metrics.pxheight,
- frame: (that.videoViewer?that.videoViewer.currentFrame:0),
- keepPlaques: keepPlaques,
- apiKey: ''
- };
- // save plaque
- app.preloader.show();
- app.request.post(app.data.config.apiBaseURL + '/measure/plaque/', postData, function (data) {
- console.log('measure/plaque', data);
- app.preloader.hide();
- if (data.result == 'ERROR') {
- switch (data.reason) {
- case 'denied':
- app.methods.signout(global.tr[global.lang].topLevel.warning.disconnected);
- break;
- case 'algo_failed':
- app.dialog.alert(global.tr[global.lang].topLevel.error.algo_failed);
- break;
- case 'no_credit':
- app.dialog.alert(global.tr[global.lang].topLevel.error.no_credit);
- break;
- default:
- app.dialog.alert(global.tr[global.lang].topLevel.error.internal_error);
- break;
- }
- }
- else {
- // update credits
- $$('#credit_available').text(data.credit_left);
- // add measure
- that.media[that.currentMediaIndex].measure = data.measures;
- that.addDicomCalibration(that.currentMediaIndex);
- that.updateMeasureList();
- //
- that.updateButtonStates();
- }
- // update
- that.actionStatus=null;
- that.update();
- }, function (data) {
- console.log('error', data);
- }, 'json');
- },
- mousedown: function(e) {
- if(this.media[this.currentMediaIndex].filename.indexOf('.dicom')!==-1) {
- let x = this.scaleIn(e.offsetX);
- let y = this.scaleIn(e.offsetY);
- for (let i=0; i<this.media[this.currentMediaIndex].measure.length; ++i) {
- let M = this.media[this.currentMediaIndex].measure[i];
- if(M.type == 'calibration') {
- for (let k=0; k<M.points.length; ++k) {
- let distance = global.improc.distance({x:x, y:y}, M.points[k]);
- if(distance<=5) {
- this.calibrationHover = {m:i, p:k};
- return;
- }
- }
- return;
- }
- }
- }
- },
- mouseup: function(e) {
- this.calibrationHover = null;
- let that = this;
- if(this.actionStatus=='calibration') {
- if(this.points.length==0) {
- this.points.push({
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- });
- this.points.push({
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- });
- this.update();
- }
- else if(this.points.length==2) {
- $$('#measure-calibration').removeClass('outlined');
- $$("body:hover").css({'cursor':'default'});
- this.points[1] = {
- x: this.points[1].x,
- y: this.scaleIn(e.offsetY)
- };
- // auto detect scale
- let scale = global.improc.computeScale(this.getImageData(), this.zoom, this.points[0], this.points[1]);
- console.log('computeScale', scale);
- if(scale.rep>=2) {
- this.points[0] = scale.p1;
- this.points[1] = scale.p2;
- this.actionStatus='calibrationConfirm';
- }
- else {
- this.actionStatus=null;
- }
- this.update();
- // confirm
- if(this.actionStatus=='calibrationConfirm') {
- var dlg = app.dialog.prompt(global.tr[global.lang].measure.calibrationLength, function(scale) {
- console.log('scale', scale);
- scale = parseFloat(scale);
- let distance = global.improc.distance(that.points[0], that.points[1]);
- console.log('distance', distance);
- console.log(scale/distance);
- if(scale == '' || scale === NaN || parseInt(scale) <= 0) {
- app.dialog.alert(global.tr[global.lang].measure.invalidDistance);
- // update
- that.actionStatus=null;
- that.update();
- }
- else if(!Number.isInteger(parseFloat(scale))) {
- app.dialog.alert(global.tr[global.lang].measure.integerPlease);
- // update
- that.actionStatus=null;
- that.update();
- }
- else if(parseInt(scale)<10 || parseInt(scale)>95) {
- app.dialog.alert(global.tr[global.lang].measure.invalidRange);
- // update
- that.actionStatus=null;
- that.update();
- }
- else {
- // save calibration
- let postData = {
- visitID: app.data.patient.visitID,
- filename: that.media[that.currentMediaIndex].filename,
- scale: scale/distance,
- computation: {
- distance: scale
- },
- points: that.points,
- frame: (that.videoViewer?that.videoViewer.currentFrame:0),
- apiKey: ''
- };
- app.preloader.show();
- app.request.post(app.data.config.apiBaseURL + '/measure/calibration/', postData, function (data) {
- console.log('measure/calibration', data);
- app.preloader.hide();
- if (data.result == 'ERROR') {
- switch (data.reason) {
- case 'denied':
- app.methods.signout(global.tr[global.lang].topLevel.warning.disconnected);
- break;
- default:
- app.dialog.alert(global.tr[global.lang].topLevel.error.internal_error);
- break;
- }
- }
- else {
- console.log(scale/distance);
- that.media[that.currentMediaIndex].metrics.pxwidth=scale/distance;
- that.media[that.currentMediaIndex].metrics.pxheight=scale/distance;
- // remove existing calibration
- for(let i=0; i<that.media[that.currentMediaIndex].measure.length; ++i) {
- if(that.media[that.currentMediaIndex].measure[i].type == 'calibration') {
- that.media[that.currentMediaIndex].measure.splice(i, 1);
- break;
- }
- }
- // add measure
- that.media[that.currentMediaIndex].measure.push(data.measure);
- that.updateMeasureList();
- //
- that.updateButtonStates();
- that.mouseout();
- }
- // update
- that.actionStatus=null;
- that.update();
- }, function (data) {
- console.log('error', data);
- }, 'json');
- }
- }, function() {
- // update on cancel
- that.actionStatus=null;
- that.update();
- }, '');
- console.log(dlg);
- dlg.params.cssClass = 'prompt-on-top';
- dlg.$el.css({
- 'top':(dlg.$el.height()/2)+'px'
- });
- /*dlg.on('opened', function() {
- $$(".dialog").css({
- 'top':($$(".dialog").height()/2)+'px'
- });
- });*/
- }
- }
- }
- else if(this.actionStatus=='distance') {
- if(this.points.length==0) {
- this.points.push({
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- });
- this.points.push({
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- });
- this.update();
- }
- else if(this.points.length==2) {
- $$('#measure-distance').removeClass('outlined');
- $$("body:hover").css({'cursor':'default'});
- this.points[1] = {
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- };
- // distance type
- app.dialog.create({
- title: global.tr[global.lang].measure.distanceType,
- text: null,
- buttons: [{
- text: global.tr[global.lang].measure.thickness,
- },{
- text: global.tr[global.lang].measure.diameter,
- },{
- text: global.tr[global.lang].measure.plaqueThickness,
- },{
- text: global.tr[global.lang].topLevel.cancel,
- },
- ],
- onClick: function (dialog, index) {
- let pxwidth = that.media[that.currentMediaIndex].metrics.pxwidth;
- let pxheight = that.media[that.currentMediaIndex].metrics.pxheight;
- let pts=[{x:that.points[0].x*pxwidth, y:that.points[0].y*pxheight}, {x:that.points[1].x*pxwidth, y:that.points[1].y*pxheight}];
- let distance = global.improc.distance(pts[0], pts[1]);
- let postData = {
- visitID: app.data.patient.visitID,
- filename: that.media[that.currentMediaIndex].filename,
- points: that.points,
- computation: {
- distance: distance
- },
- frame: (that.videoViewer?that.videoViewer.currentFrame:0),
- type: '',
- apiKey: ''
- };
- if(index === 0){
- postData.type='thickness';
- }
- else if(index === 1){
- postData.type='diameter';
- }
- else if(index === 2){
- postData.type='plaque_thickness';
- }
- else {
- // update
- that.actionStatus=null;
- that.update();
- return;
- }
- // save distance
- app.preloader.show();
- app.request.post(app.data.config.apiBaseURL + '/measure/distance/', postData, function (data) {
- console.log('measure/distance', data);
- app.preloader.hide();
- if (data.result == 'ERROR') {
- switch (data.reason) {
- case 'denied':
- app.methods.signout(global.tr[global.lang].topLevel.warning.disconnected);
- break;
- default:
- app.dialog.alert(global.tr[global.lang].topLevel.error.internal_error);
- break;
- }
- }
- else {
- // add measure
- that.media[that.currentMediaIndex].measure = data.measures;
- that.addDicomCalibration(that.currentMediaIndex);
- that.updateMeasureList();
- //
- that.updateButtonStates();
- }
- // update
- that.actionStatus=null;
- that.update();
- }, function (data) {
- console.log('error', data);
- }, 'json');
- },
- verticalButtons: true,
- }).open();
- }
- }
- else if(this.actionStatus=='area') {
- if(this.points.length==0) {
- this.points.push({
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- });
- this.points.push({
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- });
- this.update();
- }
- else {
- this.points.push({
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- });
- this.update();
- }
- }
- else if(this.actionStatus=='imt') {
- if(this.points.length==0) {
- this.points.push({
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- });
- this.points.push({
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- });
- this.update();
- }
- else if(this.points.length==2) {
- $$('#measure-imt').removeClass('outlined');
- $$("body:hover").css({'cursor':'default'});
- this.points[1] = {
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- };
- let that = this;
- let postData = {
- visitID: app.data.patient.visitID,
- filename: this.media[this.currentMediaIndex].filename,
- points: this.points,
- pxwidth: this.media[this.currentMediaIndex].metrics.pxwidth,
- pxheight: this.media[this.currentMediaIndex].metrics.pxheight,
- frame: (that.videoViewer?that.videoViewer.currentFrame:0),
- apiKey: ''
- };
- // save imt
- app.preloader.show();
- app.request.post(app.data.config.apiBaseURL + '/measure/imt/', postData, function (data) {
- console.log('measure/imt', data);
- app.preloader.hide();
- if (data.result == 'ERROR') {
- switch (data.reason) {
- case 'denied':
- app.methods.signout(global.tr[global.lang].topLevel.warning.disconnected);
- break;
- case 'no_credit':
- app.dialog.alert(global.tr[global.lang].topLevel.error.no_credit);
- break;
- default:
- app.dialog.alert(global.tr[global.lang].topLevel.error.internal_error);
- break;
- }
- }
- else {
- // update credits
- $$('#credit_available').text(data.credit_left);
- // add measure
- that.media[that.currentMediaIndex].measure = data.measures;
- that.addDicomCalibration(that.currentMediaIndex);
- that.updateMeasureList();
- //
- that.updateButtonStates();
- }
- // update
- that.actionStatus=null;
- that.update();
- }, function (data) {
- console.log('error', data);
- }, 'json');
- // JS version
- //let res = improc.eim(this.getImageData(), this.points[0], this.points[1]);
- //console.log(res);
- }
- }
- else if(this.actionStatus=='plaque') {
- console.log('enter add point', this.points, this.points.length);
- if(this.points.length==0) {
- console.log('add 2');
- this.points.push({
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- });
- this.points.push({
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- });
- this.update();
- }
- else {
- this.points.push({
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- });
- this.update();
- }
- console.log('leave add point', this.points, this.points.length);
- }
- else if(this.actionStatus=='plaque2') {
- $$('#measure-plaque').removeClass('outlined');
- $$("body:hover").css({'cursor':'default'});
- this.points[this.points.length-1] = {
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- };
- this.points.splice(this.points.length-2, 1);
- console.log('plaque points', this.points);
- let that = this;
- let hasPlaqueAlready = false;
- for (let i=0; i<this.media[this.currentMediaIndex].measure.length; i++) {
- if(this.media[this.currentMediaIndex].measure[i].type=='plaque') {
- hasPlaqueAlready = true;
- break;
- }
- }
- if(hasPlaqueAlready) {
- app.dialog.create({
- title: global.tr[global.lang].measure.plaqueNew,
- text: null,
- buttons: [{
- text: global.tr[global.lang].measure.plaqueNewYes,
- },{
- text: global.tr[global.lang].measure.plaqueNewNo,
- },{
- text: global.tr[global.lang].topLevel.cancel,
- },
- ],
- onClick: function (dialog, index) {
- let keepPlaques = false;
- if(index === 0){
- keepPlaques=true;
- }
- else if(index === 1){
- }
- else {
- // update
- that.actionStatus=null;
- that.update();
- return;
- }
- that.savePlaque(keepPlaques);
- },
- verticalButtons: true,
- }).open();
- }
- else {
- this.savePlaque(false);
- }
- }
- else if(this.calibrationHover!==null) {
- this.calibrationHover = null;
- $$("body:hover").css({'cursor':'default'});
- }
- },
- mouseout: function() {
- let mx = this.media[this.currentMediaIndex].metrics.pxwidth.toFixed(2);
- let my = this.media[this.currentMediaIndex].metrics.pxheight.toFixed(2);
- let scale = mx+'x'+my;
- if(mx == 0 || my == 0) {
- scale = '<span style="color:red;">'+scale+'</span>';
- }
- $$('#mouseCoord').html('['+scale+']');
- },
- mousemove: function(e) {
- let mx = this.media[this.currentMediaIndex].metrics.pxwidth.toFixed(2);
- let my = this.media[this.currentMediaIndex].metrics.pxheight.toFixed(2);
- let scale = mx+'x'+my;
- if(mx == 0 || my == 0) {
- scale = '<span style="color:red;">'+scale+'</span>';
- }
- $$('#mouseCoord').html('('+this.scaleIn(e.offsetX)+', '+this.scaleIn(e.offsetY)+')'+' '+'['+scale+']');
- if(this.actionStatus=='calibration' && this.points.length==2) {
- this.points[1] = {
- x: this.points[0].x,
- y: this.scaleIn(e.offsetY)
- };
- this.update();
- }
- else if(this.actionStatus=='distance' && this.points.length==2) {
- this.points[1] = {
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- };
- this.update();
- }
- else if(this.actionStatus=='area' && this.points.length>=2) {
- this.points[this.points.length-1] = {
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- };
- this.update();
- }
- else if(this.actionStatus=='imt' && this.points.length>=2) {
- this.points[1] = {
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- };
- this.update();
- }
- else if(this.actionStatus=='plaque' && this.points.length>=2) {
- this.points[this.points.length-1] = {
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- };
- this.update();
- }
- else if(this.calibrationHover!==null) {
- //console.log('calibrationHover', this.calibrationHover);
- let points = this.media[this.currentMediaIndex].measure[this.calibrationHover.m].points;
- let P = points[this.calibrationHover.p];
- let dx = this.scaleIn(e.offsetX) - P.x;
- let dy = this.scaleIn(e.offsetY) - P.y;
- this.media[this.currentMediaIndex].measure[this.calibrationHover.m].points[0].x += dx;
- this.media[this.currentMediaIndex].measure[this.calibrationHover.m].points[0].y += dy;
- this.media[this.currentMediaIndex].measure[this.calibrationHover.m].points[1].x += dx;
- this.media[this.currentMediaIndex].measure[this.calibrationHover.m].points[1].y += dy;
- this.update();
- }
- else if(this.media[this.currentMediaIndex].filename.indexOf('.dicom')!==-1) {
- let x = this.scaleIn(e.offsetX);
- let y = this.scaleIn(e.offsetY);
- for (let i=0; i<this.media[this.currentMediaIndex].measure.length; ++i) {
- let M = this.media[this.currentMediaIndex].measure[i];
- if(M.type == 'calibration') {
- for (let k=0; k<M.points.length; ++k) {
- let distance = global.improc.distance({x:x, y:y}, M.points[k]);
- if(distance<=5) {
- //$$("body:hover").css({'cursor':'move'});
- return;
- }
- }
- //$$("body:hover").css({'cursor':'default'});
- return;
- }
- }
- }
- },
- dblclick: function(e) {
- let that = this;
- if(this.actionStatus=='area' && this.points.length>=2) {
- $$('#measure-area').removeClass('outlined');
- $$("body:hover").css({'cursor':'default'});
- this.points[this.points.length-1] = {
- x: this.scaleIn(e.offsetX),
- y: this.scaleIn(e.offsetY)
- };
- let pxwidth = this.media[this.currentMediaIndex].metrics.pxwidth;
- let pxheight = this.media[this.currentMediaIndex].metrics.pxheight;
- let nbp = global.improc.surface(this.points, 1.0);
- let postData = {
- visitID: app.data.patient.visitID,
- filename: that.media[that.currentMediaIndex].filename,
- points: that.points,
- computation: {
- surface: nbp*pxwidth*pxheight
- },
- frame: (that.videoViewer?that.videoViewer.currentFrame:0),
- apiKey: ''
- };
- // save area
- app.preloader.show();
- app.request.post(app.data.config.apiBaseURL + '/measure/area/', postData, function (data) {
- console.log('measure/area', data);
- app.preloader.hide();
- if (data.result == 'ERROR') {
- switch (data.reason) {
- case 'denied':
- app.methods.signout(global.tr[global.lang].topLevel.warning.disconnected);
- break;
- default:
- app.dialog.alert(global.tr[global.lang].topLevel.error.internal_error);
- break;
- }
- }
- else {
- // add measure
- that.media[that.currentMediaIndex].measure = data.measures;
- that.addDicomCalibration(that.currentMediaIndex);
- that.updateMeasureList();
- //
- that.updateButtonStates();
- }
- // update
- that.actionStatus=null;
- that.update();
- }, function (data) {
- console.log('error', data);
- }, 'json');
- }
- else if(this.actionStatus=='plaque' && this.points.length>=2) {
- console.log("change cursor now");
- this.actionStatus='plaque2';
- $$("body:hover").css({'cursor':'default'});
- $$("body:hover").css({'cursor':'url(\'static/images/cursor_round.png\') 8 8, auto'});
- this.update();
- }
- }
- }
- }
- </script>
|