From a5cf07409337e6f164122030a4ecdc528e4d5ee2 Mon Sep 17 00:00:00 2001 From: nanli Date: Sun, 3 Mar 2019 12:12:02 -0500 Subject: [PATCH 01/11] add segment panel into viewer. --- apps/segment/segment.html | 80 +++++--- apps/segment/segment.js | 208 ++++++++++----------- apps/segment/segmentpanel/segmentpanel.css | 44 +++++ apps/segment/segmentpanel/segmentpanel.js | 44 +++++ 4 files changed, 238 insertions(+), 138 deletions(-) create mode 100644 apps/segment/segmentpanel/segmentpanel.css create mode 100644 apps/segment/segmentpanel/segmentpanel.js diff --git a/apps/segment/segment.html b/apps/segment/segment.html index a4e581a52..3dfa62dc9 100755 --- a/apps/segment/segment.html +++ b/apps/segment/segment.html @@ -15,7 +15,8 @@ - + + @@ -27,8 +28,8 @@ - - + + @@ -53,7 +54,8 @@ - + + @@ -67,7 +69,8 @@ - + + @@ -95,7 +98,7 @@ - + @@ -107,7 +110,7 @@ - + @@ -135,26 +138,47 @@
diff --git a/apps/segment/segment.js b/apps/segment/segment.js index f53bb43b1..03b94fe83 100644 --- a/apps/segment/segment.js +++ b/apps/segment/segment.js @@ -1,5 +1,4 @@ let PDR = OpenSeadragon.pixelDensityRatio; -console.log('pixelDensityRatio:', PDR); let $CAMIC = null; const $UI = {}; @@ -11,34 +10,17 @@ const $D = { params: null }; -function loadOpenCv(onloadCallback) { - const OPENCV_URL = 'opencv.js'; - let script = document.createElement('script'); - script.setAttribute('async', ''); - script.setAttribute('type', 'text/javascript'); - - script.addEventListener('load', () => { - //console.log(cv.getBuildInformation()); - console.log('OPENCV IS LOADED! :)'); - onloadCallback(); - }); - - script.src = OPENCV_URL; - let node = document.getElementsByTagName('script')[0]; - console.log('node.parentNode', node.parentNode); - node.parentNode.insertBefore(script, node); - -} function initialize() { - loadOpenCv(() => { - initUIcomponents(); - }); + initUIcomponents(); initCore(); } function initUIcomponents() { + /* create UI components */ + // create the message queue + $UI.message = new MessageQueue(); $UI.toolbar = new CaToolbar({ id: 'ca_tools', zIndex: 601, @@ -99,7 +81,11 @@ function initCore() { } try { - $CAMIC = new CaMic("main_viewer", $D.params.slideId, opt); + let slideQuery = {} + slideQuery.id = $D.params.slideId + slideQuery.name = $D.params.slide + slideQuery.location = $D.params.location + $CAMIC = new CaMic("main_viewer", slideQuery, opt); } catch (error) { Loading.close(); $UI.message.addError('Core Initialization Failed'); @@ -115,8 +101,16 @@ function initCore() { }); $CAMIC.viewer.addOnceHandler('open', function (e) { + const viewer = $CAMIC.viewer; // add stop draw function - $CAMIC.viewer.canvasDrawInstance.addHandler('stop-drawing', camicStopDraw); + viewer.canvasDrawInstance.addHandler('stop-drawing', camicStopDraw); + $UI.segmentPanel = new SegmentPanel(viewer); + //add event for range + $UI.segmentPanel.__input.addEventListener('change', function(e){ + const alpha = +this.__input.value; + this.__label.innerHTML = alpha; + watershed(this.__src,this.__out,alpha); + }.bind($UI.segmentPanel)); }); } @@ -152,9 +146,8 @@ function camicStopDraw(e) { const canvasDraw = viewer.canvasDrawInstance; let imgColl = canvasDraw.getImageFeatureCollection(); - if (imgColl.features.length > 0) { - + // Check size first let box = checkSize(imgColl, viewer.imagingHelper); @@ -162,6 +155,11 @@ function camicStopDraw(e) { console.error('SOMETHING WICKED THIS WAY COMES.'); } else { segmentROI(box); + $UI.segmentPanel.setPosition(box.rect.x,box.rect.y,box.rect.width,box.rect.height); + $UI.segmentPanel.open(); + + // close + canvasDraw.clear(); } } else { @@ -174,6 +172,14 @@ function checkSize(imgColl, imagingHelper) { // 5x2 array let bound = imgColl.features[0].bound; + + // get position on viewer + + const top_left = imgColl.features[0].bound[0]; + const bottom_right = imgColl.features[0].bound[2]; + const min = imagingHelper._viewer.viewport.imageToViewportCoordinates(top_left[0],top_left[1]); + const max = imagingHelper._viewer.viewport.imageToViewportCoordinates(bottom_right[0],bottom_right[1]); + const rect = new OpenSeadragon.Rect(min.x,min.y,max.x-min.x,max.y-min.y); // Convert to screen coordinates let foo = convertCoordinates(imagingHelper, bound); @@ -187,13 +193,11 @@ function checkSize(imgColl, imagingHelper) { }); console.log('bounds', newArray); - const xCoord = newArray[0][0]; - const yCoord = newArray[0][1]; - - let width = (newArray[2][0] - xCoord); - let height = (newArray[2][1] - yCoord); + const xCoord = Math.round(newArray[0][0]); + const yCoord = Math.round(newArray[0][1]); - console.log('width, height:\n', width, height); + let width = Math.round(newArray[2][0] - xCoord); + let height = Math.round(newArray[2][1] - yCoord); // check that image size is ok if (width * height > 4000000) { @@ -202,7 +206,7 @@ function checkSize(imgColl, imagingHelper) { $CAMIC.viewer.canvasDrawInstance.clear(); return {}; //throw('image too large') } else { - return {'xCoord': xCoord, 'yCoord': yCoord, 'width': width, 'height': height}; + return {rect:rect,'xCoord': xCoord, 'yCoord': yCoord, 'width': width, 'height': height}; } } @@ -212,23 +216,11 @@ function checkSize(imgColl, imagingHelper) { * @param canvasId * @param hidden */ -function loadImageToCanvas(imgData, canvasId, hidden, div) { - - let canvas = document.createElement('canvas'); - canvas.id = canvasId; - //canvas.style.border = "thick solid #0000FF"; +function loadImageToCanvas(imgData, canvas) { canvas.width = imgData.width; canvas.height = imgData.height; - let context = canvas.getContext("2d"); context.putImageData(imgData, 0, 0); - div.appendChild(canvas); - - if (hidden) { - canvas.style.display = 'none'; - } - - //return canvas.toDataURL("image/png"); } @@ -241,53 +233,58 @@ function segmentROI(box) { // But first, some setup... - let div = document.createElement('div'); - document.body.appendChild(div); - - var mybr = document.createElement('br'); - - // TRACKBAR WEIGHT VALUE - let weightValue = document.createElement("label"); - weightValue.id = 'weightValue'; - div.appendChild(weightValue); - div.appendChild(mybr); - - // TRACKBAR - let trackbar = document.createElement('input'); - trackbar.setAttribute('type', 'range'); - trackbar.id = 'trackbar'; - trackbar.setAttribute('value', '.7'); - trackbar.setAttribute('min', '0'); - trackbar.setAttribute('max', '1'); - trackbar.setAttribute('step', '.1'); - div.appendChild(trackbar); - div.appendChild(mybr); - - weightValue.innerText = trackbar.value; - weightValue.addEventListener('input', () => { - weightValue.innerText = trackbar.value; - }); - - trackbar.addEventListener('input', () => { - let alpha = trackbar.value / trackbar.max; - watershed('canvasInput', 'canvasOutput', alpha); - }); - - // TRIGGER - let trigger = document.getElementById('trigger'); - trigger.addEventListener("click", function () { - watershed('canvasInput', 'canvasOutput', .07); - }, false); + // let div = document.createElement('div'); + // document.body.appendChild(div); + + // var mybr = document.createElement('br'); + + // // TRACKBAR WEIGHT VALUE + // let weightValue = document.createElement("label"); + // weightValue.id = 'weightValue'; + // div.appendChild(weightValue); + // div.appendChild(mybr); + + // // TRACKBAR + // let trackbar = document.createElement('input'); + // trackbar.setAttribute('type', 'range'); + // trackbar.id = 'trackbar'; + // trackbar.setAttribute('value', '.7'); + // trackbar.setAttribute('min', '0'); + // trackbar.setAttribute('max', '1'); + // trackbar.setAttribute('step', '.1'); + // div.appendChild(trackbar); + // div.appendChild(mybr); + + // weightValue.innerText = trackbar.value; + // weightValue.addEventListener('input', () => { + // weightValue.innerText = trackbar.value; + // }); + + // trackbar.addEventListener('input', () => { + // let alpha = trackbar.value / trackbar.max; + // watershed('canvasInput', 'canvasOutput', alpha); + // }); + + // // TRIGGER + // let trigger = document.getElementById('trigger'); + // trigger.addEventListener("click", function () { + // watershed('canvasInput', 'canvasOutput', .07); + // }, false); // SEGMENTATION CANVAS let camicanv = $CAMIC.viewer.drawer.canvas; //Original Canvas let imgData = (camicanv.getContext('2d')).getImageData(box.xCoord, box.yCoord, box.width, box.height); - loadImageToCanvas(imgData, 'canvasOutput', false, div); - loadImageToCanvas(imgData, 'canvasInput', true, div); + // loadImageToCanvas(imgData, $UI.segmentPanel.__out); + loadImageToCanvas(imgData, $UI.segmentPanel.__src); // TRIGGER SEGMENTATION - trigger.click(); + const alpha = +$UI.segmentPanel.__input.value; + $UI.segmentPanel.__label.innerHTML = alpha; + watershed($UI.segmentPanel.__src,$a.segmentPanel.__out,alpha); + + + /* let dataURL = loadImageToCanvas(imgData, 'canvasInput', false); @@ -316,7 +313,6 @@ function watershed(inn, out, thresh) { // Read image let src = cv.imread(inn); - // Matrices let dst = new cv.Mat(); let gray = new cv.Mat(); @@ -368,22 +364,32 @@ function watershed(inn, out, thresh) { } cv.cvtColor(src, dst, cv.COLOR_RGBA2RGB, 0); cv.watershed(dst, markers); - + const cloneSrc = src.clone(); // Draw barriers + //console.log(markers.rows,markers.cols); for (let i = 0; i < markers.rows; i++) { for (let j = 0; j < markers.cols; j++) { if (markers.intPtr(i, j)[0] === -1) { - dst.ucharPtr(i, j)[0] = 255; // R dst.ucharPtr(i, j)[1] = 255; // G - dst.ucharPtr(i, j)[2] = 0; // B + dst.ucharPtr(i, j)[2] = 0; // B + cloneSrc.ucharPtr(i, j)[0] = 255; // R + cloneSrc.ucharPtr(i, j)[1] = 255; // G + cloneSrc.ucharPtr(i, j)[2] = 0; // B + + //console.log(dst.ucharPtr(i, j)); + }else{ + cloneSrc.ucharPtr(i, j)[3] = 0; } } } - // Display it - cv.imshow(out, dst); + // Display it + //cv.imshow(out, dst); + //console.log(document.getElementById('test1')); + cv.imshow(out, cloneSrc); + //cv.imshow($UI.segmentPanel.__out, cloneSrc); // Free up memory src.delete(); @@ -464,21 +470,3 @@ function convertCoordinates(imagingHelper, bound) { return newArray; } - -function redirect(url, text = '', sec = 5) { - let timer = sec; - setInterval(function () { - if (!timer) { - window.location.href = url; - } - - if (Loading.instance.parentNode) { - Loading.text.textContent = `${text} ${timer}s.`; - } else { - Loading.open(document.body, `${text} ${timer}s.`); - } - // Hint Message for clients that page is going to redirect to Flex table in 5s - timer--; - - }, 1000); -} diff --git a/apps/segment/segmentpanel/segmentpanel.css b/apps/segment/segmentpanel/segmentpanel.css new file mode 100644 index 000000000..83f2c535e --- /dev/null +++ b/apps/segment/segmentpanel/segmentpanel.css @@ -0,0 +1,44 @@ +/*segmentpanel.css*/ +.segment-panel { + box-sizing: border-box; + position: absolute; + border: 1px yellow solid; + color:black; + z-index:300; + /*border:2px red solid;*/ +} + +.segment-panel .settings { + font-size:18px; + position: absolute; + border: 1px solid black; + background: white; + top:-22px; + left:-10px; +} + +.segment-panel .segment-setting { + /*display: none;*/ + top: -22px; + left: 10px; + position: absolute; + height: 18px; + background: white; + border: 1px black solid; +} + +.segment-panel .segment-setting { + display: flex; +} + +.segment-panel .src, .segment-panel .out { + width: 100%; + height: 100%; +} + +.segment-panel .src { + display: none; +} + + + diff --git a/apps/segment/segmentpanel/segmentpanel.js b/apps/segment/segmentpanel/segmentpanel.js new file mode 100644 index 000000000..4284674dc --- /dev/null +++ b/apps/segment/segmentpanel/segmentpanel.js @@ -0,0 +1,44 @@ +// segmentpanel.js +// + +function SegmentPanel(viewer){ + const temp = ` +
close
+
+ + + `; + this.viewer = viewer; + this.elt = document.createElement('div'); + this.elt.classList.add('segment-panel'); + this.elt.innerHTML = temp; + this.__out = this.elt.querySelector('.out'); + this.__src = this.elt.querySelector('.src'); + this.__input = this.elt.querySelector('.segment-setting input[type=range]'); + this.__label = this.elt.querySelector('.segment-setting label'); + this.viewer.addOverlay({ + element: this.elt, + location: new OpenSeadragon.Rect(0,0,0,0), + checkResize: false + }); + this.overlay = this.viewer.currentOverlays[this.viewer.currentOverlays.length-1]; + this.elt.querySelector('.material-icons').addEventListener('click',function(e){ + this.close(); + }.bind(this)); + this.close() +} + +SegmentPanel.prototype.open = function(){ + this.elt.style.display = ''; +}; + +SegmentPanel.prototype.close = function(){ + this.elt.style.display = 'none'; +}; +SegmentPanel.prototype.setPosition = function(x,y,w,h){ + this.overlay.location.x = x; + this.overlay.location.y = y; + this.overlay.width = w; + this.overlay.height = h; + this.overlay.drawHTML(this.viewer.overlaysContainer,this.viewer.viewport); +}; \ No newline at end of file From b63637575b0aa2c10b7dfd91a300ebeeaca86fc1 Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 4 Mar 2019 11:03:04 -0500 Subject: [PATCH 02/11] fix segment for Nanoborb. --- apps/segment/segment.html | 2 +- apps/segment/segment.js | 11 ++++++++--- apps/viewer/init.js | 31 +++++++++++++++++-------------- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/apps/segment/segment.html b/apps/segment/segment.html index 3dfa62dc9..84c45b866 100755 --- a/apps/segment/segment.html +++ b/apps/segment/segment.html @@ -121,7 +121,7 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - diff --git a/apps/lite/segment/segment.js b/apps/lite/segment/segment.js deleted file mode 100644 index a9cbdb44c..000000000 --- a/apps/lite/segment/segment.js +++ /dev/null @@ -1,482 +0,0 @@ -let PDR = OpenSeadragon.pixelDensityRatio; -console.log('pixelDensityRatio:', PDR); - -let $CAMIC = null; -const $UI = {}; -const $D = { - pages: { - home: '', - table: '' - }, - params: null -}; - -function loadOpenCv(onloadCallback) { - const OPENCV_URL = 'opencv.js'; - let script = document.createElement('script'); - script.setAttribute('async', ''); - script.setAttribute('type', 'text/javascript'); - - script.addEventListener('load', () => { - //console.log(cv.getBuildInformation()); - console.log('OPENCV IS LOADED! :)'); - onloadCallback(); - }); - - script.src = OPENCV_URL; - let node = document.getElementsByTagName('script')[0]; - console.log('node.parentNode', node.parentNode); - node.parentNode.insertBefore(script, node); - -} - -function initialize() { - loadOpenCv(() => { - initUIcomponents(); - }); - initCore(); -} - -function initUIcomponents() { - - $UI.toolbar = new CaToolbar({ - id: 'ca_tools', - zIndex: 601, - hasMainTools: false, - subTools: [ - // rectangle draw - { - icon: 'timeline', - type: 'check', - value: 'rect', - title: 'Segment', - callback: drawRectangle - }, { - icon: 'insert_photo', - type: 'btn', - value: 'viewer', - title: 'Viewer', - callback: function () { - if (window.location.search.length > 0) { - window.location.href = '../viewer/viewer.html' + window.location.search; - } else { - window.location.href = '../viewer/viewer.html'; - } - } - }, { - icon: 'bug_report', - title: 'Bug Report', - value: 'bugs', - type: 'btn', - callback: () => { - window.open('https://goo.gl/forms/mgyhx4ADH0UuEQJ53', '_blank').focus() - } - } - ] - }); - - let button = document.createElement('button'); - button.id = 'trigger'; - button.style.display = "none"; - document.body.appendChild(button); - -} - -// setting core functionality -function initCore() { - // start initial - const opt = { - hasZoomControl: true, - hasDrawLayer: true, - hasLayerManager: true, - hasScalebar: true, - hasMeasurementTool: true - }; - - // set states if exist - if ($D.params.states) { - opt.states = $D.params.states; - } - - try { - $CAMIC = new CaMic("main_viewer", $D.params.slideId, opt); - } catch (error) { - Loading.close(); - $UI.message.addError('Core Initialization Failed'); - console.error(error); - return; - } - - $CAMIC.loadImg(function (e) { - // image loaded - if (e.hasError) { - $UI.message.addError(e.message) - } - }); - - $CAMIC.viewer.addOnceHandler('open', function (e) { - // add stop draw function - $CAMIC.viewer.canvasDrawInstance.addHandler('stop-drawing', camicStopDraw); - - }); -} - -/** - * Toolbar button callback - * @param e - */ -function drawRectangle(e) { - - let canvas = $CAMIC.viewer.drawer.canvas; //Original Canvas - canvas.style.cursor = e.checked ? 'crosshair' : 'default'; - - const canvasDraw = $CAMIC.viewer.canvasDrawInstance; - canvasDraw.drawMode = 'rect'; - canvasDraw.style.color = '#FFFF00'; - canvasDraw.style.isFill = false; - - if (e.checked) { - canvasDraw.drawOn(); - } else { - canvasDraw.drawOff(); - } -} - -/** - * This is basically onmouseup after drawing rectangle. - * @param e - */ -function camicStopDraw(e) { - - const viewer = $CAMIC.viewer; - const canvasDraw = viewer.canvasDrawInstance; - - let imgColl = canvasDraw.getImageFeatureCollection(); - - if (imgColl.features.length > 0) { - - // Check size first - let box = checkSize(imgColl, viewer.imagingHelper); - - if (Object.keys(box).length === 0 && box.constructor === Object) { - console.error('SOMETHING WICKED THIS WAY COMES.'); - } else { - segmentROI(box); - } - - } else { - console.error('Could not get feature collection.') - } - -} - -function checkSize(imgColl, imagingHelper) { - - // 5x2 array - let bound = imgColl.features[0].bound; - - // Convert to screen coordinates - let foo = convertCoordinates(imagingHelper, bound); - - //retina screen - let newArray = foo.map(function (a) { - let x = a.slice(); - x[0] *= PDR; - x[1] *= PDR; - return x; - }); - console.log('bounds', newArray); - - const xCoord = newArray[0][0]; - const yCoord = newArray[0][1]; - - let width = (newArray[2][0] - xCoord); - let height = (newArray[2][1] - yCoord); - - console.log('width, height:\n', width, height); - - // check that image size is ok - if (width * height > 4000000) { - alert("Selected ROI too large, current version is limited to 4 megapixels"); - // Clear the rectangle canvas-draw-overlay.clear() - $CAMIC.viewer.canvasDrawInstance.clear(); - return {}; //throw('image too large') - } else { - return {'xCoord': xCoord, 'yCoord': yCoord, 'width': width, 'height': height}; - } -} - -/** - * Make a canvas element & draw the ROI. - * @param imgData - * @param canvasId - * @param hidden - */ -function loadImageToCanvas(imgData, canvasId, hidden, div) { - - let canvas = document.createElement('canvas'); - canvas.id = canvasId; - //canvas.style.border = "thick solid #0000FF"; - canvas.width = imgData.width; - canvas.height = imgData.height; - - let context = canvas.getContext("2d"); - context.putImageData(imgData, 0, 0); - div.appendChild(canvas); - - if (hidden) { - canvas.style.display = 'none'; - } - - //return canvas.toDataURL("image/png"); - -} - -/** - * Segment! :) - * @param box - */ -function segmentROI(box) { - - // But first, some setup... - - - let div = document.createElement('div'); - document.body.appendChild(div); - - var mybr = document.createElement('br'); - - // TRACKBAR WEIGHT VALUE - let weightValue = document.createElement("label"); - weightValue.id = 'weightValue'; - div.appendChild(weightValue); - div.appendChild(mybr); - - // TRACKBAR - let trackbar = document.createElement('input'); - trackbar.setAttribute('type', 'range'); - trackbar.id = 'trackbar'; - trackbar.setAttribute('value', '.7'); - trackbar.setAttribute('min', '0'); - trackbar.setAttribute('max', '1'); - trackbar.setAttribute('step', '.1'); - div.appendChild(trackbar); - div.appendChild(mybr); - - weightValue.innerText = trackbar.value; - weightValue.addEventListener('input', () => { - weightValue.innerText = trackbar.value; - }); - - trackbar.addEventListener('input', () => { - let alpha = trackbar.value / trackbar.max; - watershed('canvasInput', 'canvasOutput', alpha); - }); - - // TRIGGER - let trigger = document.getElementById('trigger'); - trigger.addEventListener("click", function () { - watershed('canvasInput', 'canvasOutput', .07); - }, false); - - // SEGMENTATION CANVAS - let camicanv = $CAMIC.viewer.drawer.canvas; //Original Canvas - let imgData = (camicanv.getContext('2d')).getImageData(box.xCoord, box.yCoord, box.width, box.height); - - loadImageToCanvas(imgData, 'canvasOutput', false, div); - loadImageToCanvas(imgData, 'canvasInput', true, div); - - // TRIGGER SEGMENTATION - trigger.click(); - - /* - let dataURL = loadImageToCanvas(imgData, 'canvasInput', false); - var img = document.createElement("img"); - img.src = dataURL; - document.body.appendChild(img); - */ - - /* - let blob = dataURItoBlob(dataURL); - let filename = 'testing'; - let f = new File([blob], filename, {type: blob.type}); - console.log(f); - */ - -} - -/** - * WATERSHED SEGMENTATION - * - * @param inn - * @param out - * @param thresh - */ -function watershed(inn, out, thresh) { - - // Read image - let src = cv.imread(inn); - - // Matrices - let dst = new cv.Mat(); - let gray = new cv.Mat(); - let opening = new cv.Mat(); - let imageBg = new cv.Mat(); - let imageFg = new cv.Mat(); - let distTrans = new cv.Mat(); - let unknown = new cv.Mat(); - let markers = new cv.Mat(); - - // Gray and threshold image - cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0); - - // Find an approximate estimate of the objects - cv.threshold(gray, gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU); - - // Get background - let M = cv.Mat.ones(3, 3, cv.CV_8U); - - // Remove the stuff that's not an object - cv.erode(gray, gray, M); - - // Find the stuff that IS an object - cv.dilate(gray, opening, M); //remove any small white noises in the image - cv.dilate(opening, imageBg, M, new cv.Point(-1, -1), 3); //remove any small holes in the object - - // Distance transform - for the stuff we're not sure about - cv.distanceTransform(opening, distTrans, cv.DIST_L2, 5); - cv.normalize(distTrans, distTrans, 1, 0, cv.NORM_INF); - - // Get foreground - make the objects stand out - // cv.threshold (src, dst, thresh, maxval, type) - cv.threshold(distTrans, imageFg, thresh, 255, cv.THRESH_BINARY); - - // Mark (label) the regions starting with 1 (color output) - imageFg.convertTo(imageFg, cv.CV_8U, 1, 0); - cv.subtract(imageBg, imageFg, unknown); - - // Get connected components markers - - cv.connectedComponents(imageFg, markers); - for (let i = 0; i < markers.rows; i++) { - for (let j = 0; j < markers.cols; j++) { - markers.intPtr(i, j)[0] = markers.ucharPtr(i, j)[0] + 1; - if (unknown.ucharPtr(i, j)[0] === 255) { - markers.intPtr(i, j)[0] = 0; - } - } - } - cv.cvtColor(src, dst, cv.COLOR_RGBA2RGB, 0); - cv.watershed(dst, markers); - - // Draw barriers - for (let i = 0; i < markers.rows; i++) { - for (let j = 0; j < markers.cols; j++) { - if (markers.intPtr(i, j)[0] === -1) { - dst.ucharPtr(i, j)[0] = 255; // R - dst.ucharPtr(i, j)[1] = 255; // G - dst.ucharPtr(i, j)[2] = 0; // B - } - } - } - - - // Display it - cv.imshow(out, dst); - - src.delete(); - dst.delete(); - gray.delete(); - opening.delete(); - imageBg.delete(); - imageFg.delete(); - distTrans.delete(); - unknown.delete(); - markers.delete(); - M.delete(); -} - -/** - * Check file creation - * - * @param filename - * @param dataURL - */ -function download(filename, dataURL) { - var element = document.createElement('a'); - element.setAttribute('href', dataURL); - element.setAttribute('download', filename); - - element.style.display = 'none'; - document.body.appendChild(element); - - element.click(); - - document.body.removeChild(element); -} - -/** - * Convert a dataURI to a Blob - * - * @param dataURI - * @returns {Blob} - */ -function dataURItoBlob(dataURI) { - // convert base64/URLEncoded data component to raw binary data held in a string - let byteString; - if (dataURI.split(',')[0].indexOf('base64') >= 0) - byteString = atob(dataURI.split(',')[1]); - else - byteString = unescape(dataURI.split(',')[1]); - - // separate out the mime component - let mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; - - // write the bytes of the string to a typed array - let ia = new Uint8Array(byteString.length); - for (let i = 0; i < byteString.length; i++) { - ia[i] = byteString.charCodeAt(i); - } - - return new Blob([ia], {type: mimeString}); -} - -/** - * Convert image coordinates - */ -function convertCoordinates(imagingHelper, bound) { - - let newArray = bound.map(function (arr) { - return arr.slice(); // copy - }); - - // 'image coordinate' to 'screen coordinate' - for (let i = 0; i < newArray.length; i++) { - let boundElement = newArray[i]; - for (let j = 0; j < boundElement.length; j++) { - newArray[i][j] = j === 0 ? imagingHelper.dataToPhysicalX(boundElement[j]) - : imagingHelper.dataToPhysicalY(boundElement[j]); - } - } - - return newArray; - -} - -function redirect(url, text = '', sec = 5) { - let timer = sec; - setInterval(function () { - if (!timer) { - window.location.href = url; - } - - if (Loading.instance.parentNode) { - Loading.text.textContent = `${text} ${timer}s.`; - } else { - Loading.open(document.body, `${text} ${timer}s.`); - } - // Hint Message for clients that page is going to redirect to Flex table in 5s - timer--; - - }, 1000); -} diff --git a/apps/lite/viewer/dataloaders.js b/apps/lite/viewer/dataloaders.js deleted file mode 100644 index e0d74a43b..000000000 --- a/apps/lite/viewer/dataloaders.js +++ /dev/null @@ -1,90 +0,0 @@ -// dataloaders.js -// - -// function SlideDataLoader(){ -// function loadingSlideInfo(){ - -// } -// var checkCoreIsReady = setInterval(function () { -// if($CAMIC) { -// clearInterval(checkCoreIsReady); -// //load data -// loadingSlideInfo(); -// } -// }, 1000); -// } - -function FormTempaltesLoader(){ - - function loadingFormTemplates(){ - - $CAMIC.store.findTemplate() - // - .then(function(temps){ - // get templates data - $D.templates = temps; - }) - // - .catch(function(error){ - // templates schema - - console.error(error); - }) - // - .finally(function(){ - if($D.templates){ - // load UI - }else{ - // set message - $UI.message.addError('Loading Templates is Error'); - - } - }); - } - - var checkCoreIsReady = setInterval(function () { - if($CAMIC) { - clearInterval(checkCoreIsReady); - //load data - loadingFormTemplates(); - } - }, 500); -} - -function OverlayersLoader(){ - function loadingOverlayers(){ - $CAMIC.store.findMarkTypes($D.params.data.name) - // - .then(function(layers){ - typeIds = {}; - $D.overlayers = []; - // convert part not nesscary - for(let i = 0 ;i < layers.length;i++){ - $D.overlayers.push(covertToLayViewer(layers[i],($D.params.states)?$D.params.states.l:null)); - } - }) - // - .catch(function(error){ - // overlayers schema - - console.error(error); - }) - // - .finally(function(){ - if($D.overlayers){ - }else{ - // set message - $UI.message.addError('Loading Overlayers is Error'); - - } - }); - } - - var checkCoreIsReady = setInterval(function () { - if($CAMIC && $D.params.data) { - clearInterval(checkCoreIsReady); - //load data - loadingOverlayers(); - } - }, 500); -} diff --git a/apps/lite/viewer/init.js b/apps/lite/viewer/init.js deleted file mode 100644 index db2843e79..000000000 --- a/apps/lite/viewer/init.js +++ /dev/null @@ -1,442 +0,0 @@ -// CAMIC is an instance of camicroscope core -// $CAMIC in there -let $CAMIC = null; -// for all instances of UI components -const $UI = new Map(); - -const $D = { - pages:{ - home:'', - table:'' - }, - params:null, // parameter from url - slide Id and status in it (object). - overlayers:null, // array for each layers - templates:null // json schema for prue-form -}; - - -// initialize viewer page -function initialize(){ - - // init UI -- some of them need to wait data loader to load data - // because UI components need data to initialize - initUIcomponents(); - - // create a viewer and set up - initCore(); - - // loading the form template data - FormTempaltesLoader(); - - // loading the overlayers data - OverlayersLoader(); - - -} - -function loadData(){ - -} - -// setting core functionalities -function initCore(){ - // start initial - // TODO zoom info and mmp - const opt = { - draw:{ - // extend context menu btn group - btns:[ - { // annotation - type:'btn', - title:'Annotation', - class:'material-icons', - text:'description', - callback:saveAnnotation - }, - { // analytics - type:'btn', - title:'Analytics', - class:'material-icons', - text:'settings_backup_restore', - callback:saveAnalytics - } - ] - } - } - // set states if exist - if($D.params.states){ - opt.states = $D.params.states; - } - - try{ - let slideQuery = {} - slideQuery.id = $D.params.slideId - slideQuery.name = $D.params.slide - slideQuery.location = $D.params.location - $CAMIC = new CaMic("main_viewer", slideQuery, opt); - }catch(error){ - Loading.close(); - $UI.message.addError('Core Initialization Failed'); - console.error(error); - return; - } - - $CAMIC.loadImg(function(e){ - // image loaded - if(e.hasError){ - $UI.message.addError(e.message) - }else{ - $D.params.data = e; - // popup panel - $CAMIC.viewer.addHandler('canvas-lay-click',function(e){ - if(!e.data) { - $UI.annotPopup.close(); - return; - } - // for support QUIP 2.0 - const data = Array.isArray(e.data)? e.data[e.data.selected]: e.data; - - const type = data.provenance.analysis.source; - let body; - let attributes; - switch (type) { - case "human": - // human - attributes = data.properties.annotations; - body = convertHumanAnnotationToPopupBody(attributes); - $UI.annotPopup.showFooter(); - break; - case "computer": - // handle data.provenance.analysis.computation = `segmentation` - attributes = data.properties.scalar_features[0].nv; - body = {type:'map',data:attributes}; - $UI.annotPopup.hideFooter(); - break; - default: - return; - // statements_def - break; - } - $UI.annotPopup.data = { - id:data.provenance.analysis.execution_id, - oid:data._id.$oid, - annotation:attributes - }; - $UI.annotPopup.setTitle(`id:${data.provenance.analysis.execution_id}`); - $UI.annotPopup.setBody(body); - $UI.annotPopup.open(e.position); - }); - - // create the message bar TODO for reading slide Info TODO - $UI.slideInfos = new CaMessage({ - /* opts that need to think of*/ - id:'cames', - defaultText:`Slide: ${$D.params.data.name}` - }); - - // spyglass - $UI.spyglass = new Spyglass({ - targetViewer:$CAMIC.viewer, - imgsrc:$D.params.data.url - }); - } - }); - - $CAMIC.viewer.addHandler('open',function(){ - $CAMIC.viewer.canvasDrawInstance.addHandler('start-drawing',startDrawing); - $CAMIC.viewer.canvasDrawInstance.addHandler('stop-drawing',stopDrawing); - if(!$CAMIC.viewer.measureInstance) $UI.toolbar._sub_tools[4].style.display = 'none'; - }); -} - - -// initialize all UI components -function initUIcomponents(){ - /* create UI components */ - - - // create the message queue - $UI.message = new MessageQueue(); - - // create the tool bar - $UI.toolbar = new CaToolbar({ - /* opts that need to think of*/ - id:'ca_tools', - zIndex:601, - mainToolsCallback:mainMenuChange, - subTools:[ - // home - { - icon:'cloud_download',// material icons' name - title:'Download Marks', - type:'btn',// btn/check/dropdown - value:'download', - callback:Store.prototype.DownloadMarksToFile - }, - { - icon:'cloud_upload', - title:'Load Marks', - type:'btn', - value:'upload', - callback:Store.prototype.LoadMarksFromFile - }, - // pen - { - icon:'create',// material icons' name - title:'Draw', - type:'multistates', - callback:draw - }, - // magnifier - { - icon:'search', - title:'Magnifier', - type:'dropdown', - value:'magn', - dropdownList:[ - // free draw - { - //icon:'linear_scale', - value:0.5, - title:'0.5', - checked:true - }, - // rectangle fraw - { - //icon:'timeline', - value:1, - title:'1.0' - }, - { - //icon:'timeline', - value:2, - title:'2.0' - } - ], - callback:toggleMagnifier - }, - // measurement tool - { - icon:'space_bar', - title:'Measurement', - type:'check', - value:'measure', - // dropdownList:[ - // // free draw - // { - // icon:'linear_scale', - // value:'straight', - // title:'Line', - // checked:true - // }, - // // rectangle draw - // { - // icon:'timeline', - // value:'coordinate', - // title:'Coordinate' - // } - // ], - callback:toggleMeasurement - }, - // download TODO - // { - // icon:'file_download', - // title:'Download Image', - // type:'btn', - // value:'download', - // callback:imageDownload - // }, - // share - { - icon:'view_carousel', - title:'Side By Side Viewer', - value:'dbviewers', - type:'check', - callback:toggleViewerMode - }, - { - icon: 'bug_report', - title: 'Bug Report', - value: 'bugs', - type: 'btn', - callback: ()=>{window.open('https://goo.gl/forms/mgyhx4ADH0UuEQJ53','_blank').focus()} - } - //, - // { - // icon: 'timeline', - // type: 'check', - // value: 'rect', - // title: 'Segment', - // callback: function () { - // if (window.location.search.length > 0) { - // window.location.href = '../segment/segment.html' + window.location.search; - // } - // else { - // window.location.href = '../segment/segment.html'; - // } - - // } - // } - - ] - }); - - // create two side menus for tools - $UI.appsSideMenu = new SideMenu({ - id:'side_apps', - width: 300, - //, isOpen:true - callback:toggleSideMenu - }); - - $UI.layersSideMenu = new SideMenu({ - id:'side_layers', - width: 300, - contentPadding:5, - //, isOpen:true - callback:toggleSideMenu - }); - - /* annotation popup */ - $UI.annotPopup = new PopupPanel({ - footer:[ - // { // edit - // title:'Edit', - // class:'material-icons', - // text:'notes', - // callback:anno_edit - // }, - { // delete - title:'Delete', - class:'material-icons', - text:'delete_forever', - callback:anno_delete - } - ] - }); - - var checkOverlaysDataReady = setInterval(function () { - if($D.overlayers) { - clearInterval(checkOverlaysDataReady); - - // create UI and set data - $UI.layersViewer = new LayersViewer({id:'overlayers',data:$D.overlayers,sortChange:sort_change,callback:callback }); - - callback($D.overlayers.filter(lay => lay.isShow)); - - $UI.layersViewer.elt.parentNode.removeChild($UI.layersViewer.elt); - - // add to layers side menu - const title = document.createElement('div'); - title.classList.add('item_head'); - title.textContent = 'Layers Manager'; - $UI.layersSideMenu.addContent(title); - $UI.layersSideMenu.addContent($UI.layersViewer.elt); - } - }, 500); - - - - - - - var checkTemplateSchemasDataReady = setInterval(function () { - if($D.templates) { - clearInterval(checkTemplateSchemasDataReady); - const annotRegex = new RegExp('annotation', 'gi'); - const annotSchemas = $D.templates.filter(item=> item.id.match(annotRegex)); - /* annotation control */ - $UI.annotOptPanel = new OperationPanel({ - //id: - //element: - formSchemas:annotSchemas, - resetCallback:reset_callback, - action:{ - title:'Save', - callback:anno_callback - } - }); - // START QUIP550 TEMPORARILY REMOVE Algorithm Panel // - // add to layers side menu - const title = document.createElement('div'); - title.classList.add('item_head'); - title.textContent = 'Annotation'; - $UI.appsSideMenu.addContent(title); - $UI.annotOptPanel.elt.classList.add('item_body'); - $UI.appsSideMenu.addContent($UI.annotOptPanel.elt); - - // $UI.appsList.clearContent('annotation'); - // $UI.appsList.addContent('annotation',$UI.annotOptPanel.elt); - - // /* algorithm control */ - // const algoRegex = new RegExp('algo', 'gi'); - // const algoSchemas = $D.templates.filter(item => item.id.match(algoRegex)); - // $UI.algOptPanel = new OperationPanel({ - // //id: - // //element: - // title:'Algorithm:', - // formSchemas:algoSchemas, - // action:{ - // title:'Run', - // callback:algo_callback - // } - // }); - // $UI.appsList.clearContent('analytics'); - // $UI.appsList.addContent('analytics',$UI.algOptPanel.elt); - // $UI.appsList.addContent('analytics', AnalyticsPanelContent); - // END QUIP550 TEMPORARILY REMOVE Algorithm Panel // - - } - }, 500); - - - // START QUIP550 // - // // collapsible list - // $UI.appsList = new CollapsibleList({ - // id:'collapsiblelist', - // list:[ - // { - // id:'annotation', - // title:'Annotation', - // icon:'border_color', - // content: "No Template Loaded" //$UI.annotOptPanel.elt - // // isExpand:true - - // },{ - // id:'analytics', - // icon:'find_replace', - // title:'Analytics', - // content:"No Template Loaded" //$UI.algOptPanel.elt, - // } - // ], - // changeCallBack:getCurrentItem - // }); - - - // // detach collapsible_list - // $UI.appsList.elt.parentNode.removeChild($UI.appsList.elt); - // $UI.appsSideMenu.addContent($UI.appsList.elt); - // START QUIP550 // - - $UI.multSelector = new MultSelector({id:'mult_selector'}); - $UI.multSelector.addHandler('cancel',multSelector_cancel); - $UI.multSelector.addHandler('action',multSelector_action); -} - -function redirect(url ,text = '', sec = 5){ - let timer = sec; - setInterval(function(){ - if(!timer) { - window.location.href = url; - } - - if(Loading.instance&&Loading.instance.parentNode){ - Loading.text.textContent = `${text} ${timer}s.`; - }else{ - Loading.open(document.body,`${text} ${timer}s.`); - } - // Hint Message for clients that page is going to redirect to Flex table in 5s - timer--; - - }, 1000); -} diff --git a/apps/lite/viewer/uicallbacks.js b/apps/lite/viewer/uicallbacks.js deleted file mode 100644 index ceb477419..000000000 --- a/apps/lite/viewer/uicallbacks.js +++ /dev/null @@ -1,751 +0,0 @@ -//UI and Core callback and hook -// all functions help the UI and Core part together that makes workflows. - -/* UI callback functions list */ -$minorCAMIC = null; -function toggleViewerMode(opt){ - const main = document.getElementById('main_viewer'); - const secondary = document.getElementById('secondary'); - const canvasDraw = $CAMIC.viewer.canvasDrawInstance; - if(opt.checked){ - // turn off drawing - canvasDraw.clear(); - canvasDraw.drawOff(); - $CAMIC.drawContextmenu.off(); - toggleOffDrawBtns(); - // turn off magnifier - $UI.toolbar._sub_tools[3].querySelector('input[type=checkbox]').checked = false; - $UI.spyglass.close(); - // turn off measurement - $UI.toolbar._sub_tools[4].querySelector('input[type=checkbox]').checked = false; - $CAMIC.viewer.measureInstance.off(); - //close layers menu - $UI.layersSideMenu.close(); - //close apps menu - $UI.appsSideMenu.close(); - - openSecondaryViewer(); - }else{ - closeSecondaryViewer(); - } -} - -//mainfest -function multSelector_action(event){ - - // if(event.data.length == 0){ - // alert('No Layer selected'); - // return; - // } - - // hide the window - $UI.multSelector.elt.classList.add('none'); - - // show the minor part - const minor = document.getElementById('minor_viewer'); - minor.classList.remove('none'); - minor.classList.add('display'); - - // open new instance camic - try{ - let slideQuery = {} - slideQuery.id = $D.params.slideId - slideQuery.name = $D.params.slide - slideQuery.location = $D.params.location - $minorCAMIC = new CaMic("minor_viewer", slideQuery, { - // osd options - // mouseNavEnabled:false, - // panVertical:false, - // panHorizontal:false, - showNavigator:false, - // customized options - hasZoomControl:false, - hasDrawLayer:false, - //hasLayerManager:false, - //hasScalebar:false, - // states options - states:{ - x:$CAMIC.viewer.viewport.getCenter().x, - y:$CAMIC.viewer.viewport.getCenter().y*$CAMIC.viewer.imagingHelper.imgAspectRatio, - z:$CAMIC.viewer.viewport.getZoom(), - } - }); - - // synchornic zoom and move - // coordinated Viewer - zoom - $CAMIC.viewer.addHandler('zoom',synchornicView1); - - // coordinated Viewer - pan - $CAMIC.viewer.addHandler('pan',synchornicView1); - - // loading image - $minorCAMIC.loadImg(function(e){ - // image loaded - if(e.hasError){ - $UI.message.addError(e.message); - } - }); - $minorCAMIC.viewer.addOnceHandler('tile-drawing',function(){ - $minorCAMIC.viewer.addHandler('zoom',synchornicView2); - $minorCAMIC.viewer.addHandler('pan',synchornicView2); - }); - }catch(error){ - Loading.close(); - $UI.message.addError('Core Initialization Failed'); - console.error(error); - return; - } - - // find unloaded data - event.data = event.data.map(lay=>lay[0]); - const unloaded = event.data.filter(id =>{ - const layer = $D.overlayers.find(layer=> layer.id == id); - return layer && !layer.data - }); - // if all data loaded then add selected layer to minor viewer - if(unloaded.length == 0){ - // add overlays to - // wait util omanager create - var checkOmanager = setInterval(function () { - if($minorCAMIC.viewer.omanager) { - clearInterval(checkOmanager); - // add overlays to - event.data.forEach(id =>{ - // find data - const layer = $D.overlayers.find(layer=> layer.id == id); - // add to the minor viewer - $minorCAMIC.viewer.omanager.addOverlay({id:id,data:layer.data,render:anno_render,isShow:true}); - }); - $minorCAMIC.viewer.omanager.updateView(); - } - }, 500); - return; - } - - // load data from service side - $CAMIC.store.getMarkByIds(unloaded,$D.params.data.name) - .then(function(datas){ - // response error - if(datas.error){ - const errorMessage = `${datas.text}: ${datas.url}`; - $UI.message.addError(errorMessage, 5000); - // close - return; - } - - // no data found - if(datas.length == 0){ - $UI.message.addError(`Selected annotations do not exist.`,5000); - return; - } - - // add overlays - if(Array.isArray(datas)) datas = datas.map(d=>{ - d.geometries = VieweportFeaturesToImageFeatures($CAMIC.viewer, d.geometries); - const id = d.provenance.analysis.execution_id; - const item = $D.overlayers.find(l=>l.id==id); - item.data = d; - item.render = anno_render; - item.layer = $CAMIC.viewer.omanager.addOverlay(item); - }); - - // wait util omanager create - var checkOmanager = setInterval(function () { - if($minorCAMIC.viewer.omanager) { - clearInterval(checkOmanager); - // add overlays to - event.data.forEach(id =>{ - // find data - const layer = $D.overlayers.find(layer=> layer.id == id); - // add to the minor viewer - $minorCAMIC.viewer.omanager.addOverlay({id:id,data:layer.data,render:anno_render,isShow:true}); - }); - $minorCAMIC.viewer.omanager.updateView(); - } - }, 500); - - }) - .catch(function(e){ - console.error(e); - }).finally(function(){ - - }); - -} - - -var active1 = false; -var active2 = false; -function synchornicView1(data){ - if (active2) { - return; - } - - active1 = true; - $minorCAMIC.viewer.viewport.zoomTo($CAMIC.viewer.viewport.getZoom()); - $minorCAMIC.viewer.viewport.panTo($CAMIC.viewer.viewport.getCenter()); - active1 = false; -} - -function synchornicView2(data){ - if (active1) { - return; - } - active2 = true; - $CAMIC.viewer.viewport.zoomTo($minorCAMIC.viewer.viewport.getZoom()); - $CAMIC.viewer.viewport.panTo($minorCAMIC.viewer.viewport.getCenter()); - active2 = false; -} - -function multSelector_cancel(){ - closeSecondaryViewer(); -} - -function openSecondaryViewer(){ - // ui changed - const main = document.getElementById('main_viewer'); - const secondary = document.getElementById('secondary'); - main.classList.remove('main'); - main.classList.add('left'); - secondary.classList.remove('none'); - secondary.classList.add('right'); - Loading.open(main,'Waiting for Operation.',600); - $UI.multSelector.elt.classList.remove('none'); - $UI.multSelector.setData($D.overlayers.map(l=>[l.id,l.name])); -} - -function closeSecondaryViewer(){ - // ui changed - const main = document.getElementById('main_viewer'); - const secondary = document.getElementById('secondary'); - main.classList.add('main'); - main.classList.remove('left'); - secondary.classList.add('none'); - secondary.classList.remove('right'); - $UI.multSelector.elt.classList.add('none'); - $UI.toolbar._sub_tools[5].querySelector('input[type="checkbox"]').checked = false; - Loading.close(); - - //destory - if($minorCAMIC) { - // remove handler - $CAMIC.viewer.removeHandler('zoom',synchornicView1); - $CAMIC.viewer.removeHandler('pan',synchornicView1); - - // destroy object - $minorCAMIC.destroy(); - $minorCAMIC = null; - } - const minor = document.getElementById('minor_viewer'); - minor.classList.remove('display'); - minor.classList.add('none'); - -} - -// side menu close callback -function toggleSideMenu(opt){ - if(!opt.isOpen){ - const id = opt.target.id.split('_')[1]; - $UI.toolbar.changeMainToolStatus(id,false); - } -} - -// go home callback -function goHome(data){ - redirect($D.pages.home,`GO Home Page`, 0); -} - -// pen draw callback -const label = document.createElement('div'); -label.style.transformOrigin = 'center'; -label.style.height = 0; -label.style.width = 0; - -function draw(e){ - if(!$CAMIC.viewer.canvasDrawInstance){ - alert('draw doesn\'t initialize'); - return; - } - const state = +e.state; - const canvasDraw = $CAMIC.viewer.canvasDrawInstance; - const li = $UI.toolbar._sub_tools[2]; - - const target = this.srcElement || this.target || this.eventSource.canvas; - switch (state) { - case 0: // off - li.removeChild(label); - canvasDraw.clear(); - canvasDraw.drawOff(); - $CAMIC.drawContextmenu.off(); - $UI.appsSideMenu.close(); - - break; - case 1: // once - // statements_1 - case 2: // stick - li.appendChild(label); - if(state==1){ - $UI.annotOptPanel._action_.style.display = 'none'; - label.style.transform = 'translateY(-12px) translateX(18px)'; - label.textContent = '1'; - label.style.color = ''; - }else if(state==2){ - $UI.annotOptPanel._action_.style.display = ''; - label.style.transform = ' rotate(-90deg) translateX(2px) translateY(13px)'; - label.textContent = '8'; - label.style.color = 'white'; - } - canvasDraw.drawOn(); - // $CAMIC.drawContextmenu.on(); - // $CAMIC.drawContextmenu.open({x:this.clientX,y:this.clientY,target:target}); - // turn off magnifier - $UI.toolbar._sub_tools[3].querySelector('input[type=checkbox]').checked = false; - $UI.spyglass.close(); - // turn off measurement - $UI.toolbar._sub_tools[4].querySelector('input[type=checkbox]').checked = false; - $CAMIC.viewer.measureInstance.off(); - - //close layers menu - $UI.layersSideMenu.close(); - - // open annotation menu - $UI.appsSideMenu.open(); - // -- START QUIP550 -- // - // $UI.appsList.triggerContent('annotation','open'); - // -- END QUIP550 -- // - const input = $UI.annotOptPanel._form_.querySelector('#name'); - input.focus(); - input.select(); - break; - default: - // statements_def - break; - } -} - -function toggleOffDrawBtns(){ - const label = $UI.toolbar._sub_tools[2].querySelector('label'); - const state = +label.dataset.state; - label.classList.remove(`s${state}`); - - label.dataset.state = 0; - label.classList.add(`s0`); - -} - -function toggleMeasurement(data){ - //$UI.message.add(`Measument Tool ${data.checked?'ON':'OFF'}`); - if(data.checked){ - $CAMIC.viewer.measureInstance.on(); - // trun off the main menu - $UI.layersSideMenu.close(); - $UI.appsSideMenu.close(); - // turn off draw - $CAMIC.viewer.canvasDrawInstance.drawOff(); - $CAMIC.drawContextmenu.off(); - toggleOffDrawBtns(); - // turn off magnifier - $UI.toolbar._sub_tools[3].querySelector('input[type=checkbox]').checked = false; - $UI.spyglass.close(); - }else{ - $CAMIC.viewer.measureInstance.off(); - } -} - -// toggle magnifier callback -function toggleMagnifier(data){ - if(data.checked){ - $UI.spyglass.factor = +data.status; - $UI.spyglass.open(this.clientX,this.clientY); - // trun off the main menu - $UI.layersSideMenu.close(); - $UI.appsSideMenu.close(); - //$UI.toolbar._sub_tools[2].querySelector('input[type=checkbox]').checked = false; - $CAMIC.viewer.canvasDrawInstance.drawOff(); - $CAMIC.drawContextmenu.off(); - toggleOffDrawBtns(); - // turn off measurement - $UI.toolbar._sub_tools[4].querySelector('input[type=checkbox]').checked = false; - $CAMIC.viewer.measureInstance.off(); - }else{ - $UI.spyglass.close(); - } -} - -// image download -function imageDownload(data){ - // TODO functionality - alert('Download Image'); - console.log(data); -} - -// share url -function shareURL(data){ - const URL = StatesHelper.getCurrentStatesURL(true); - window.prompt('Share this link', URL); -} -// main menu changed -function mainMenuChange(data){ - - if(data.apps){ - $UI.appsSideMenu.open(); - }else{ - $UI.appsSideMenu.close(); - } - - if(data.layers){ - $UI.layersSideMenu.open(); - }else{ - $UI.layersSideMenu.close(); - } -} - -function convertHumanAnnotationToPopupBody(notes){ - - const rs = {type:'map',data:[]}; - for(let field in notes){ - const val = notes[field]; - field = field.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' '); - rs.data.push({key:field,value:val}); - } - return rs; - -} - -function anno_delete(data){ - if(!data.id) return; - if(!confirm(`Are you sure you want to delete this markup {ID:${data.id}}?`)) return; - $CAMIC.store.deleteMark(data.oid,$D.params.data.name) - .then(datas =>{ - // server error - if(datas.error){ - const errorMessage = `${datas.text}: ${datas.url}`; - $UI.message.addError(errorMessage, 5000); - // close - return; - } - - // no data found - if(!datas.rowsAffected || datas.rowsAffected < 1){ - $UI.message.addWarning(`Delete Annotations Failed.`,5000); - return; - } - - const index = $D.overlayers.findIndex(layer => layer.id == data.id); - - if(index==-1) return; - - data.index = index; - const layer = $D.overlayers[data.index]; - // update UI - if(Array.isArray(layer.data)) deleteCallback_old(data) - else deleteCallback(data) - }) - .catch(e=>{ - $UI.message.addError(e); - console.error(e); - }) - .finally(()=>{ - //console.log('delete end'); - }); - -} -function deleteCallback(data){ - // remove overlay - $D.overlayers.splice(data.index, 1); - // update layer manager - $CAMIC.viewer.omanager.removeOverlay(data.id); - // update layers Viewer - $UI.layersViewer.update(); - // close popup panel - $UI.annotPopup.close(); - -} - -// for support QUIP2.0 Data model - delete callback -function deleteCallback_old(data){ - const layer = $D.overlayers[data.index]; - // for support QUIP2.0 - const idx = layer.data.findIndex(d=> d._id.$oid === data.oid ); - if(idx ==-1) return; - layer.data.splice(idx, 1); - - // delete entire layer if there is no data. - if(layer.data.length == 0){ - $D.overlayers.splice(data.index, 1); - $CAMIC.viewer.omanager.removeOverlay(data.id); - } - - - $CAMIC.viewer.omanager.updateView(); - // update layers Viewer - $UI.layersViewer.update(); - // close popup panel - $UI.annotPopup.close(); -} -function sort_change(sort){ - console.log('sort_change'); - $CAMIC.layersManager.sort(sort); - -} - -function reset_callback(data){ - $CAMIC.viewer.canvasDrawInstance.clear(); -} - -function anno_callback(data){ - // is form ok? - const noteData = $UI.annotOptPanel._form_.value; - if($UI.annotOptPanel._action_.disabled || noteData.name == ''){ - - // close layer silde - $UI.toolbar._main_tools[1].querySelector('[type=checkbox]').checked = false; - $UI.layersSideMenu.close(); - - // open app silde - $UI.toolbar._main_tools[0].querySelector('[type=checkbox]').checked = true; - $UI.appsSideMenu.open(); - // open annotaion list - // -- START QUIP550 -- // - // $UI.appsList.triggerContent('annotation','open'); - // -- END QUIP550 -- // - return; - - } - // has Path? - - if($CAMIC.viewer.canvasDrawInstance._path_index===0){ - alert('No Markup on Annotation.'); - return; - } - // save - // provenance - Loading.open($UI.annotOptPanel.elt,'Saving Annotation...'); - const exec_id = randomId(); - - const annotJson = { - provenance:{ - image:{ - slide:$D.params.data.name, - specimen:$D.params.data.specimen, - study:$D.params.data.study - }, - analysis:{ - source:'human', - execution_id:exec_id, - name:noteData.name - } - }, - properties:{ - annotations:noteData - }, - geometries:ImageFeaturesToVieweportFeatures($CAMIC.viewer, $CAMIC.viewer.canvasDrawInstance.getImageFeatureCollection()) - } - //return; - $CAMIC.store.addMark(annotJson) - .then(data=>{ - - // server error - if(data.error){ - $UI.message.addWarning(`${data.text}:${data.url}`); - Loading.close(); - return; - } - - // no data added - if(data.count < 1){ - Loading.close(); - $UI.message.addWarning(`Annotation Save Failed`); - return; - } - loadAnnotationById(null,exec_id); - }) - .catch(e=>{ - Loading.close(); - console.log('save failed'); - console.log(e); - }) - .finally(()=>{ - - }); -} - -function saveAnnotCallback(){ - /* reset as default */ - // clear draw data and UI - $CAMIC.viewer.canvasDrawInstance.drawOff(); - $CAMIC.drawContextmenu.off(); - toggleOffDrawBtns(); - $CAMIC.viewer.canvasDrawInstance.clear(); - // uncheck pen draw icon and checkbox - //$UI.toolbar._sub_tools[2].querySelector('[type=checkbox]').checked = false; - // clear form - $UI.annotOptPanel.clear(); - - // close app side - $UI.toolbar._main_tools[0].querySelector('[type=checkbox]').checked = false; - $UI.appsSideMenu.close(); - // -- START QUIP550 -- // - // $UI.appsList.triggerContent('annotation','close'); - // -- END QUIP550 -- // - // open layer side - $UI.toolbar._main_tools[1].querySelector('[type=checkbox]').checked = true; - $UI.layersSideMenu.open(); - $UI.layersViewer.update(); - -} -function algo_callback(data){ - console.log(data); - -} - -// overlayer manager callback function for show or hide -function callback(data){ - data.forEach(item => { - if(!item.layer){ - // load layer data - loadAnnotationById(item,item.id); - - }else{ - item.layer.isShow = item.isShow; - $CAMIC.viewer.omanager.updateView(); - } - }); -} - -function loadAnnotationById(item,id){ - Loading.open(document.body,'loading layers...'); - $CAMIC.store.getMarkByIds([id],$D.params.data.name) - .then(data =>{ - // response error - if(data.error){ - const errorMessage = `${data.text}: ${data.url}`; - $UI.message.addError(errorMessage, 5000); - const layer = $D.overlayers.find(layer => layer.id==id); - if(layer){ - layer.isShow = false; - $UI.layersViewer.update(); - } - return; - } - - // no data found - if(!data[0]){ - console.log(`Annotation:${id} doesn't exist.`); - $UI.message.addError(`Annotation:${id} doesn't exist.`,5000); - // delete item form layview - if(item) removeElement($D.overlayers,id); - $UI.layersViewer.update(); - return; - } - - - - - if(!item){ - console.log(data[0]); - item = covertToLayViewer(data[0].provenance); - item.isShow = true; - // update lay viewer UI - $D.overlayers.push(item); - $UI.layersViewer.update(); - saveAnnotCallback(); - }else{ - data[0].isShow = item.isShow; - } - - // for support quip 2.0 data model - if(data[0].geometry){ - - // twist them - var image = $CAMIC.viewer.world.getItemAt(0); - this.imgWidth = image.source.dimensions.x; - this.imgHeight = image.source.dimensions.y; - item.data = data.map(d => { - d.geometry.coordinates[0] = d.geometry.coordinates[0].map(point => { - return [Math.round(point[0]*imgWidth),Math.round(point[1]*imgHeight)]; - }); - d.properties.style = { - color: "#7CFC00", - lineCap: "round", - lineJoin: "round" - }; - return { - _id:d._id, - provenance:d.provenance, - properties:d.properties, - geometry:d.geometry - } - - - }); - if(item) data[0].isShow = item.isShow; - item.render = old_anno_render; - }else{ - data[0].geometries = VieweportFeaturesToImageFeatures($CAMIC.viewer, data[0].geometries); - item.data = data[0]; - item.render = anno_render; - } - - // create lay and update view - item.layer = $CAMIC.viewer.omanager.addOverlay(item); - $CAMIC.viewer.omanager.updateView(); - }) - .catch(e=>{ - console.error(e); - }) - .finally(()=>{ - Loading.close(); - }); -} -/* - collapsible list - 1. Annotation - 2. Analytics -*/ -function getCurrentItem(data){ - console.log(data); -} -// some fake events callback for demo - - -function annotationSave(){ - $UI.message.add('Annotation Saved'); - -}; -function algoRun(){ - $UI.message.add('Algo is running...'); - -} - -function saveAnnotation(){ - console.log('saveAnnotation'); - - anno_callback.call(null,{id:$UI.annotOptPanel.setting.formSchemas[$UI.annotOptPanel._select_.value].id, data:$UI.annotOptPanel._form_.value}); -} - -function saveAnalytics(){ - console.log('saveAnalytics'); -} -function startDrawing(e){ - $CAMIC.viewer.canvasDrawInstance.stop = !$UI.annotOptPanel._form_.isValid(); - return; -} -function stopDrawing(e){ - let state = +$UI.toolbar._sub_tools[2].querySelector('label').dataset.state; - if(state===1&&$CAMIC.viewer.canvasDrawInstance._draws_data_.length > 0){ - saveAnnotation(); - } -} -/* call back list END */ -/* -- -- */ -/* -- for render anno_data to canavs -- */ -function anno_render(ctx,data){ - DrawHelper.draw(ctx, data.geometries.features); - //DrawHelper.draw(this._canvas_ctx, this.data.canvasData); -} -function old_anno_render(ctx,data){ - DrawHelper.draw(ctx, data); - -} -/* -- -- */ diff --git a/apps/lite/viewer/viewer.html b/apps/lite/viewer/viewer.html deleted file mode 100644 index b28db0f0f..000000000 --- a/apps/lite/viewer/viewer.html +++ /dev/null @@ -1,204 +0,0 @@ - - - - - - - - - - caMicroscope - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - -
-
-
-
-
- -
- - -
- - -
- - -
- - -
- - - - diff --git a/apps/lite/segment/README.md b/apps/segment/README.md similarity index 100% rename from apps/lite/segment/README.md rename to apps/segment/README.md diff --git a/apps/lite/segment/img/roi.png b/apps/segment/img/roi.png similarity index 100% rename from apps/lite/segment/img/roi.png rename to apps/segment/img/roi.png diff --git a/apps/lite/segment/img/segmented.png b/apps/segment/img/segmented.png similarity index 100% rename from apps/lite/segment/img/segmented.png rename to apps/segment/img/segmented.png diff --git a/apps/lite/segment/img/toolbar.png b/apps/segment/img/toolbar.png similarity index 100% rename from apps/lite/segment/img/toolbar.png rename to apps/segment/img/toolbar.png From 1afcb8d78f079da8011a49a63d81487668248a7f Mon Sep 17 00:00:00 2001 From: nanli Date: Mon, 4 Mar 2019 11:38:34 -0500 Subject: [PATCH 04/11] fix the demo bug then user can use `demo` to learn how to draw an annotation and overlay. --- demo/demo.html | 66 ++++++++++++++++++++++++++------------------------ demo/demo.js | 1 + 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/demo/demo.html b/demo/demo.html index 9a2e70664..7c3eede56 100755 --- a/demo/demo.html +++ b/demo/demo.html @@ -9,52 +9,56 @@ caMicroscope - + - + - + - + - + - + - + - - - + + + + - + - + - + - - - - - + + + + + + + - - + + + - + - - - - - - - - - + + + + + + + + + @@ -62,7 +66,7 @@ - + diff --git a/demo/demo.js b/demo/demo.js index d21e14cdc..f78797820 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -82,6 +82,7 @@ function initCore() { function initUIcomponents() { // ui init + $UI.message = new MessageQueue(); $UI.toolbar = new CaToolbar({ /* opts that need to think of */ id: 'ca_tools', From 0e44b1b5ad53f0547994916d4d44274d9d249778 Mon Sep 17 00:00:00 2001 From: Ryan Birmingham Date: Tue, 5 Mar 2019 17:00:51 -0500 Subject: [PATCH 05/11] add find and add support for heatmap, idb --- apps/viewer/viewer.html | 4 +++- dist/imgbox_package.js | 8 ++++---- dist/imgbox_package.map | 2 +- package/LocalStore.js | 35 +++++++++++++++++++++++++++++++++-- 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/apps/viewer/viewer.html b/apps/viewer/viewer.html index ca4ded900..5780d24cc 100644 --- a/apps/viewer/viewer.html +++ b/apps/viewer/viewer.html @@ -71,6 +71,8 @@ + + @@ -125,7 +127,7 @@ - + diff --git a/dist/imgbox_package.js b/dist/imgbox_package.js index 1e8bb0090..52458c8af 100644 --- a/dist/imgbox_package.js +++ b/dist/imgbox_package.js @@ -1,8 +1,8 @@ -parcelRequire=function(e,r,n,t){var i="function"==typeof parcelRequire&&parcelRequire,o="function"==typeof require&&require;function u(n,t){if(!r[n]){if(!e[n]){var f="function"==typeof parcelRequire&&parcelRequire;if(!t&&f)return f(n,!0);if(i)return i(n,!0);if(o&&"string"==typeof n)return o(n);var c=new Error("Cannot find module '"+n+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[n][1][r]||r},p.cache={};var l=r[n]=new u.Module(n);e[n][0].call(l.exports,p,l,l.exports,this)}return r[n].exports;function p(e){return u(p.resolve(e))}}u.isParcelRequire=!0,u.Module=function(e){this.id=e,this.bundle=u,this.exports={}},u.modules=e,u.cache=r,u.parent=i,u.register=function(r,n){e[r]=[function(e,r){r.exports=n},{}]};for(var f=0;f=400)throw e;return e.json()}).then(function(i){for(var o=Math.ceil(Math.log2(Math.max(i.height,i.width))),a=[],n=0;n<=o;n++)a.push(Math.pow(2,n));var m={"@context":"http://iiif.io/api/image/2/context.json","@id":t,height:i.height,width:i.width,profile:["http://iiif.io/api/image/2/level2.json"],protocol:"http://iiif.io/api/image",tiles:[{scaleFactors:a,width:256}]};p.viewer.open(m),p.mpp_x=+i["mpp-x"],p.mpp_y=+i["mpp-y"],p.mpp=i.mpp||p.mpp_x||p.mpp_y||1e9,p.mpp_x=+i["mpp-x"]||p.mpp,p.mpp_y=+i["mpp-y"]||p.mpp,p.viewer.mpp=p.mpp,p.viewer.mpp_x=p.mpp_x,p.viewer.mpp_y=p.mpp_y;var r=p.mpp_x||p.mpp;r&&1e9!=r&&p.createScalebar(p.mpp),new OpenSeadragonImaging.ImagingHelper({viewer:p.viewer}).setMaxZoom(1);var s={_id:"0"};s.name=p.slideName,s.study=p.study,s.specimen=p.specimen,s.mpp=p.mpp,s.mpp_x=p.mpp_x,s.mpp_y=p.mpp_y,s.location=t,s.url=m,e&&"function"==typeof e&&e.call(null,s),Loading.text.textContent="loading slide's tiles..."}).catch(function(e){console.error(e),Loading.text.textContent="ERROR - Slide May be Broken or Unsupported"})}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var p=e;exports.default=p; +"use strict";function e(){console.warn("{imgbox mods enabled}"),CaMic.prototype.default_loadImg=CaMic.prototype.loadImg,CaMic.prototype.loadImg=function(e){var p=this,t=new URLSearchParams(window.location.search).get("id"),i=t;this.slideId=i,this.slideName=i,this.study="",this.specimen="",fetch(t+"/info.json").then(function(e){if(e.status>=400)throw e;return e.json()}).then(function(i){for(var o=Math.ceil(Math.log2(Math.max(i.height,i.width))),a=[],n=0;n<=o;n++)a.push(Math.pow(2,n));var m={"@context":"http://iiif.io/api/image/2/context.json","@id":t,height:i.height,width:i.width,profile:["http://iiif.io/api/image/2/level2.json"],protocol:"http://iiif.io/api/image",tiles:[{scaleFactors:a,width:256}]};p.viewer.open(m),p.mpp_x=+i["mpp-x"],p.mpp_y=+i["mpp-y"],p.mpp=i.mpp||p.mpp_x||p.mpp_y||1e9,p.mpp_x=+i["mpp-x"]||p.mpp,p.mpp_y=+i["mpp-y"]||p.mpp,p.viewer.mpp=p.mpp,p.viewer.mpp_x=p.mpp_x,p.viewer.mpp_y=p.mpp_y;var r=p.mpp_x||p.mpp;r&&1e9!=r&&p.createScalebar(p.mpp),new OpenSeadragonImaging.ImagingHelper({viewer:p.viewer}).setMaxZoom(1);var s={_id:"0"};s.name=p.slideName,s.study=p.study,s.specimen=p.specimen,s.mpp=p.mpp,s.mpp_x=p.mpp_x,s.mpp_y=p.mpp_y,s.location=t,s.url=m,e&&"function"==typeof e&&e.call(null,s),Loading.text.textContent="loading slide's tiles..."}).catch(function(e){console.error(e),Loading.text.textContent="ERROR - Slide May be Broken or Unsupported"})}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=e; },{}],"lM4v":[function(require,module,exports) { -"use strict";var e=o(require("./LocalStore.js")),r=o(require("./ImgBoxMods.js"));function o(e){return e&&e.__esModule?e:{default:e}}(0,e.default)(),(0,r.default)(),console.warn("This setup is intended for imagebox"); +"use strict";var e=require("./LocalStore.js"),r=t(e),o=require("./ImgBoxMods.js"),s=t(o);function t(e){return e&&e.__esModule?e:{default:e}}(0,r.default)(),(0,s.default)(),console.warn("This setup is intended for imagebox"); },{"./LocalStore.js":"WDG/","./ImgBoxMods.js":"5g62"}]},{},["lM4v"], null) //# sourceMappingURL=/imgbox_package.map \ No newline at end of file diff --git a/dist/imgbox_package.map b/dist/imgbox_package.map index 390fbb633..a11be3b1f 100644 --- a/dist/imgbox_package.map +++ b/dist/imgbox_package.map @@ -1 +1 @@ -{"version":3,"sources":["LocalStore.js","ImgBoxMods.js","imgbox_package.js"],"names":["init_LocalStore","findInLocalStorage","type","query","data","JSON","parse","window","localStorage","getItem","filter","x","matching","i","Object","byString","getInLocalStorage","id","putInLocalStorage","newData","push","setItem","stringify","removeFromLocalStorage","console","log","length","warn","o","s","a","replace","split","n","k","Store","prototype","validation","filterBroken","b","findMarkTypes","slide","name","Promise","res","rej","Set","map","findMark","specimen","study","footprint","source","x0","x1","y0","y1","then","getMarkByIds","ids","getMark","addMark","json","mark","errors","Date","now","deleteMark","findHeatmap","getHeatmap","addHeatmap","heatmap","deleteHeatmap","export","import","findSlide","location","slideId","URLSearchParams","document","search","substring","get","getSlide","params","findTemplate","getTemplate","DownloadMarksToFile","$D","decodeURIComponent","text","element","createElement","blob","Blob","uri","URL","createObjectURL","setAttribute","style","display","body","appendChild","click","removeChild","LoadMarksFromFile","onchange","event","input","target","reader","FileReader","onload","result","forEach","provenance","image","$VALIDATION","data2","concat","error","reload","e","readAsText","files","defaultTemplate","template_data","ImgBoxMods","CaMic","default_loadImg","loadImg","func","img_id","slideName","fetch","response","status","tile_count","Math","ceil","log2","max","height","width","scaleFactors","imbox_source","viewer","open","mpp_x","mpp_y","mpp","createScalebar","OpenSeadragonImaging","ImagingHelper","setMaxZoom","url","call","Loading","textContent","catch"],"mappings":"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","file":"imgbox_package.map","sourceRoot":"../package","sourcesContent":["// overwrite store with equivalent local functions\nfunction init_LocalStore(){\n // requirements\n console.warn(\"{localstore mods enabled}\")\n Object.byString = function(o, s) {\n s = s.replace(/\\[(\\w+)\\]/g, '.$1'); // convert indexes to properties\n s = s.replace(/^\\./, ''); // strip a leading dot\n var a = s.split('.');\n for (var i = 0, n = a.length; i < n; ++i) {\n var k = a[i];\n if (k in o) {\n o = o[k];\n } else {\n return;\n }\n }\n return o;\n }\n\n function findInLocalStorage(type, query){\n let data = JSON.parse(window.localStorage.getItem(type))\n if (data){\n return data.filter(x=>{\n let matching = true;\n for (var i in query){\n matching = matching && Object.byString(x, i) == query[i]\n }\n return matching\n })\n } else {\n return []\n }\n\n }\n\n function getInLocalStorage(type, id){\n let data = JSON.parse(window.localStorage.getItem(type))\n if (data){\n return data.filter(x=>x['_id'] == id)[0]\n } else {\n return {}\n }\n\n }\n\n function putInLocalStorage(type, newData){\n let data = JSON.parse(window.localStorage.getItem(type))\n data = data || []\n data.push(newData)\n window.localStorage.setItem(type, JSON.stringify(data))\n return newData\n }\n\n function removeFromLocalStorage(type, id){\n console.log(id)\n let data = JSON.parse(window.localStorage.getItem(type))\n data = data || []\n let newData = data.filter(x=>x['_id']['$oid'] !== id)\n window.localStorage.setItem(type, JSON.stringify(newData))\n console.log(data.length - newData.length)\n return {'rowsAffected': data.length - newData.length}\n }\n\n\n\n // stange fixes for potential mismatches in validation version\n Store.prototype.validation = Store.prototype.validation || {}\n Store.prototype.filterBroken = Store.prototype.filterBroken || function(a,b){return a}\n // replace impacted store functionality.\n Store.prototype.findMarkTypes = function(slide, name){\n return new Promise(function(res, rej){\n let query={}\n if(name){\n query['provenance.analysis.execution_id']= name\n }\n if(slide){\n query['provenance.image.slide'] = slide\n }\n let data = findInLocalStorage(\"mark\", query)\n if (data){\n const unique = [...new Set(data.map(x => Object.byString(x,'provenance')))];\n res(unique)\n } else {\n res([])\n }\n\n // TODO!!!\n })\n }\n Store.prototype.findMark = function(slide, name, specimen, study, footprint, source, x0, x1, y0, y1){\n return new Promise(function(res, rej){\n let query = {}\n if (name){\n query['provenance.image.slide'] = slide\n }\n if(slide){\n query['provenance.analysis.execution_id']= name\n }\n if(source){\n query['provenance.analysis.source']= source\n }\n if(specimen){\n query['provenance.image.specimen'] = specimen\n }\n if(study){\n query['provenance.image.study'] = study\n }\n res(findInLocalStorage('mark', query))\n }).then(x=>this.filterBroken(x,\"mark\"))\n }\n Store.prototype.getMarkByIds = function(ids, slide, study, specimen, source, footprint, x0, x1, y0, y1){\n return new Promise(function(res, rej){\n let data = []\n for (var i in ids){\n data.push(...findInLocalStorage('mark', {'provenance.analysis.execution_id': ids[i], 'provenance.image.slide': slide}))\n }\n res(data)\n }).then(x=>this.filterBroken(x,\"mark\"))\n }\n Store.prototype.getMark = function(id){\n return new Promise(function(res, rej){\n res(getInLocalStorage(\"mark\", id))\n }).then(x=>this.filterBroken(x,\"mark\"))\n }\n Store.prototype.addMark = function(json){\n if (!this.validation.mark(json)){\n console.warn(this.validation.mark.errors)\n }\n return new Promise(function(res, rej){\n // give it an that's probably semi-unique\n json['_id'] = json['_id'] || {'$oid': Date.now()}\n res(putInLocalStorage('mark', json))\n })\n }\n Store.prototype.deleteMark = function(id, slide){\n return new Promise((res, rej)=>{\n res(removeFromLocalStorage('mark', id))\n })\n }\n Store.prototype.findHeatmap = function(slide, name){\n return new Promise(function(res, rej){\n let query = {}\n if (name){\n query['provenance.image.slide'] = slide\n }\n if(slide){\n query['provenance.analysis.execution_id']= name\n }\n res(findInLocalStorage('heatmap', query))\n }).then(x=>this.filterBroken(x,\"heatmap\"))\n }\n Store.prototype.getHeatmap = function(id){\n return new Promise(function(res, rej){\n res(getInLocalStorage(\"heatmap\", id))\n }).then(x=>this.filterBroken(x,\"heatmap\"))\n }\n Store.prototype.addHeatmap = function(json){\n // give it an that's probably semi-unique\n if (!this.validation.heatmap(json)){\n console.warn(this.validation.heatmap.errors)\n }\n json['_id'] = json['_id'] || {'$oid': Date.now()}\n return new Promise(function(res, rej){\n res(putInLocalStorage('heatmap', json))\n })\n }\n Store.prototype.deleteHeatmap = function(id,slide){\n return new Promise(function(res, rej){\n res(removeFromLocalStorage('heatmap', id))\n })\n }\n\n // import and export functions\n Store.prototype.export = function(type){\n return new Promise(function(res, rej){\n res(window.localStorage.getItem(type))\n })\n }\n // NOTE -- overwrites\n Store.prototype.import = function(type, data){\n return new Promise(function(res, rej){\n res(window.localStorage.setItem(type, data))\n })\n }\n Store.prototype.findSlide = function(slide, specimen, study, location){\n return new Promise(function(res, rej){\n let params = new URLSearchParams(document.location.search.substring(1));\n let slideId = params.get(\"id\") || \"local\";\n let local_dummy = {\n 'id': slideId,\n 'mpp': '0.001',\n 'study':\"\",\n 'specimen':\"\"\n }\n res([local_dummy])\n })\n }\n Store.prototype.getSlide = function(id){\n return new Promise(function(res, rej){\n let params = new URLSearchParams(document.location.search.substring(1));\n let slideId = params.get(\"id\") || \"local\";\n console.log(params)\n let local_dummy = {\n 'id': slideId,\n 'mpp': '0.001',\n 'study':\"\",\n 'specimen':\"\"\n }\n res(local_dummy)\n })\n }\n Store.prototype.findTemplate = function(name,type){\n let query = {}\n if (name){\n query.name = name\n }\n if (type){\n query.type = type\n }\n return new Promise(function(res, rej){\n res(findInLocalStorage(\"template\", query))\n }).then(x=>this.filterBroken(x,\"template\"))\n }\n Store.prototype.getTemplate = function(id){\n return new Promise(function(res, rej){\n res(getInLocalStorage(\"template\", id))\n }).then(x=>this.filterBroken(x,\"template\"))\n }\n Store.prototype.DownloadMarksToFile = function(){\n // downloads marks for the current slide only\n // make the browser download it\n let slide = $D.params.id // portable?\n slide = decodeURIComponent(slide) // fix for url fix\n let query = {}\n query['provenance.image.slide'] = slide\n let data = JSON.parse(window.localStorage.getItem(\"mark\"))\n let text = \"\"\n if (data) {\n text = JSON.stringify(data.filter(x => {\n let matching = true;\n for (var i in query) {\n matching = matching && Object.byString(x, i) == query[i]\n }\n return matching\n }))\n }\n var element = document.createElement('a');\n var blob = new Blob([text], {type: \"application/json\"});\n var uri = URL.createObjectURL(blob);\n element.setAttribute('href', uri);\n element.setAttribute('download', \"markups.json\");\n element.style.display = 'none';\n document.body.appendChild(element);\n element.click();\n document.body.removeChild(element);\n }\n Store.prototype.LoadMarksFromFile = function(){\n // loads marks for the current slide only, without replacement\n // open a file selector\n let slide = $D.params.id\n slide = decodeURIComponent(slide)\n var element = document.createElement('input');\n document.body.appendChild(element);\n element.setAttribute('type', \"file\")\n element.style.display = 'position: fixed; top: -100em';\n element.onchange = function(event) {\n var input = event.target;\n var reader = new FileReader();\n reader.onload = function() {\n var text = reader.result;\n try {\n let data = JSON.parse(text)\n console.log(data)\n data.forEach(x => {\n x.provenance.image.slide = slide\n })\n console.log($VALIDATION.mark)\n let data2 = JSON.parse(window.localStorage.getItem(\"mark\"))\n data2 = data2 || []\n console.log(data2)\n data2 = data2.concat(data)\n data2 = data2.filter($VALIDATION.mark)\n console.log(data2)\n window.localStorage.setItem(\"mark\", JSON.stringify(data2))\n if ($VALIDATION.mark.errors){\n console.error($VALIDATION.mark.errors)\n } else {\n window.location.reload()\n }\n\n } catch (e) {\n console.error(e)\n }\n console.log(text.substring(0, 200));\n };\n reader.readAsText(input.files[0]);\n };\n\n element.click();\n document.body.removeChild(element);\n }\n}\n\n// default template\nlet defaultTemplate = {\n \"_id\": \"0\",\n \"type\": \"object\",\n \"id\": \"annotation-form\",\n \"name\": \"AnnotSchema\",\n \"description\": \"\",\n \"links\": [],\n \"additionalProperties\": false,\n \"properties\": {\n \"name\": {\n \"id\": \"a0\",\n \"title\": \"Identity Name\",\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"note name\"\n },\"notes\": {\n \"id\": \"a1\",\n \"title\": \"Notes: \",\n \"type\": \"string\",\n \"format\":\"textarea\",\n \"maxLength\": 128\n }\n }\n}\n// if no template, add our default\nlet template_data = JSON.parse(window.localStorage.getItem(\"template\"))\nif (!template_data){\n template_data=[];\n template_data.push(defaultTemplate)\n window.localStorage.setItem(\"template\", JSON.stringify(template_data))\n}\n\n\nexport default init_LocalStore\n","function ImgBoxMods() {\n console.warn(\"{imgbox mods enabled}\")\n CaMic.prototype.default_loadImg = CaMic.prototype.loadImg\n CaMic.prototype.loadImg = function(func) {\n var urlParams = new URLSearchParams(window.location.search);\n var img_id = urlParams.get('id');\n let slideId = img_id\n this.slideId = slideId\n this.slideName = slideId\n this.study = \"\"\n this.specimen = \"\"\n fetch(img_id + \"/info.json\").then(response => {\n if (response.status >=400){\n throw response;\n } else {\n return response.json();\n }\n }).then(data => {\n let tile_count = Math.ceil(Math.log2(Math.max(data.height,data.width)))\n let scaleFactors = []\n for(let i=0; i <= tile_count; i++){\n scaleFactors.push(2**i)\n }\n let imbox_source = {\n \"@context\": \"http://iiif.io/api/image/2/context.json\",\n \"@id\": img_id,\n \"height\": data.height,\n \"width\": data.width,\n \"profile\": [\"http://iiif.io/api/image/2/level2.json\"],\n \"protocol\": \"http://iiif.io/api/image\",\n \"tiles\": [{\n \"scaleFactors\": scaleFactors,\n \"width\": 256\n }]\n }\n this.viewer.open(imbox_source);\n // set mpp\n this.mpp_x = +data['mpp-x']\n this.mpp_y = +data['mpp-y']\n this.mpp = data.mpp || this.mpp_x || this.mpp_y || 1e9;\n this.mpp_x = +data['mpp-x'] || this.mpp\n this.mpp_y = +data['mpp-y'] || this.mpp\n\n this.viewer.mpp = this.mpp;\n this.viewer.mpp_x = this.mpp_x;\n this.viewer.mpp_y = this.mpp_y;\n \n //set scalebar\n let mpp = this.mpp_x || this.mpp;\n if(mpp&&mpp!=1e9) this.createScalebar(this.mpp)\n var imagingHelper = new OpenSeadragonImaging.ImagingHelper({\n viewer: this.viewer\n });\n imagingHelper.setMaxZoom(1);\n // create item to pass to the callback function, previously x[0] (slide data)\n let x = {}\n x['_id'] = \"0\"\n x.name = this.slideName\n x.study = this.study\n x.specimen = this.specimen\n x.mpp = this.mpp;\n x.mpp_x = this.mpp_x;\n x.mpp_y = this.mpp_y;\n x.location = img_id;\n x.url = imbox_source;\n if (func && typeof func === 'function'){\n func.call(null, x);\n }\n Loading.text.textContent = `loading slide's tiles...`;\n // WARN; note that spyglass isn't working due to semi-hardcoded value at init.js line 140\n // we may want another init.js or our own callback\n }).catch(e=>{\n console.error(e)\n Loading.text.textContent = \"ERROR - Slide May be Broken or Unsupported\"\n //if(func && typeof func === 'function') func.call(null,{hasError:true,message:e});\n })\n\n }\n}\n\n\nexport default ImgBoxMods\n","import init_LocalStore from './LocalStore.js'\nimport ImgBoxMods from './ImgBoxMods.js'\n\ninit_LocalStore()\nImgBoxMods()\nconsole.warn(\"This setup is intended for imagebox\")\n// parcel build package/imgbox_package.js\n"]} \ No newline at end of file +{"version":3,"sources":["LocalStore.js","ImgBoxMods.js","imgbox_package.js"],"names":["init_LocalStore","findInLocalStorage","type","query","data","JSON","parse","window","localStorage","getItem","filter","matching","i","Object","byString","x","getInLocalStorage","id","removeFromLocalStorage","log","newData","setItem","stringify","length","prototype","db","idb","openDb","createObjectStore","autoIncrement","warn","o","s","a","replace","split","n","k","validation","Store","filterBroken","b","findMarkTypes","slide","name","Promise","res","rej","unique","Set","map","findMark","specimen","study","footprint","source","x0","x1","y0","y1","then","getMarkByIds","ids","push","getMark","addMark","json","mark","errors","putInLocalStorage","Date","now","deleteMark","findHeatmap","findInIDB","transaction","objectStore","getAll","console","getHeatmap","addHeatmap","heatmap","putInIDB","add","deleteHeatmap","export","import","findSlide","location","slideId","URLSearchParams","document","search","substring","get","getSlide","params","local_dummy","findTemplate","getTemplate","DownloadMarksToFile","$D","decodeURIComponent","text","element","createElement","blob","Blob","uri","URL","createObjectURL","setAttribute","style","display","body","appendChild","click","removeChild","LoadMarksFromFile","onchange","event","input","target","reader","FileReader","onload","result","forEach","provenance","image","$VALIDATION","data2","concat","error","reload","e","readAsText","files","defaultTemplate","template_data","ImgBoxMods","default_loadImg","CaMic","loadImg","func","img_id","slideName","response","status","tile_count","Math","ceil","log2","max","height","width","scaleFactors","imbox_source","viewer","open","mpp_x","mpp_y","mpp","createScalebar","OpenSeadragonImaging","ImagingHelper","setMaxZoom","url","call","textContent","catch"],"mappings":"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","file":"imgbox_package.map","sourceRoot":"../package","sourcesContent":["// overwrite store with equivalent local functions\nfunction init_LocalStore(){\n // requirements\n Store.prototype.db = idb.openDb(\"heatmap\", 1, x=>{\n let recordStore = x.createObjectStore(\"heatmap\", {autoIncrement : true});\n })\n console.warn(\"{localstore mods enabled}\")\n Object.byString = function(o, s) {\n s = s.replace(/\\[(\\w+)\\]/g, '.$1'); // convert indexes to properties\n s = s.replace(/^\\./, ''); // strip a leading dot\n var a = s.split('.');\n for (var i = 0, n = a.length; i < n; ++i) {\n var k = a[i];\n if (k in o) {\n o = o[k];\n } else {\n return;\n }\n }\n return o;\n }\n\n function findInIDB(type, query){\n return new Promise((res,rej)=>{\n Store.prototype.db.then(x=>{\n var data = x.transaction(type).objectStore(type, 'readonly').getAll()\n data.then(console.log)\n data.then(data=>{\n res(data.filter(x=>{\n let matching = true;\n for (var i in query){\n matching = matching && Object.byString(x, i) == query[i]\n }\n return matching\n }))\n })\n }\n )\n })\n }\n\n function putInIDB(type, newData){\n Store.prototype.db.then(x=>{\n let tx = x.transaction(type, 'readwrite')\n var store = tx.objectStore(type)\n store.add(newData)\n })\n return newData\n }\n\n function findInLocalStorage(type, query){\n let data = JSON.parse(window.localStorage.getItem(type))\n if (data){\n return data.filter(x=>{\n let matching = true;\n for (var i in query){\n matching = matching && Object.byString(x, i) == query[i]\n }\n return matching\n })\n } else {\n return []\n }\n\n }\n\n function getInLocalStorage(type, id){\n let data = JSON.parse(window.localStorage.getItem(type))\n if (data){\n return data.filter(x=>x['_id'] == id)[0]\n } else {\n return {}\n }\n\n }\n\n function putInLocalStorage(type, newData){\n let data = JSON.parse(window.localStorage.getItem(type))\n data = data || []\n data.push(newData)\n window.localStorage.setItem(type, JSON.stringify(data))\n return newData\n }\n\n function removeFromLocalStorage(type, id){\n console.log(id)\n let data = JSON.parse(window.localStorage.getItem(type))\n data = data || []\n let newData = data.filter(x=>x['_id']['$oid'] !== id)\n window.localStorage.setItem(type, JSON.stringify(newData))\n console.log(data.length - newData.length)\n return {'rowsAffected': data.length - newData.length}\n }\n\n\n\n // stange fixes for potential mismatches in validation version\n Store.prototype.validation = Store.prototype.validation || {}\n Store.prototype.filterBroken = Store.prototype.filterBroken || function(a,b){return a}\n // replace impacted store functionality.\n Store.prototype.findMarkTypes = function(slide, name){\n return new Promise(function(res, rej){\n let query={}\n if(name){\n query['provenance.analysis.execution_id']= name\n }\n if(slide){\n query['provenance.image.slide'] = slide\n }\n let data = findInLocalStorage(\"mark\", query)\n if (data){\n const unique = [...new Set(data.map(x => Object.byString(x,'provenance')))];\n res(unique)\n } else {\n res([])\n }\n\n // TODO!!!\n })\n }\n\n Store.prototype.findMark = function(slide, name, specimen, study, footprint, source, x0, x1, y0, y1){\n return new Promise(function(res, rej){\n let query = {}\n if (name){\n query['provenance.image.slide'] = slide\n }\n if(slide){\n query['provenance.analysis.execution_id']= name\n }\n if(source){\n query['provenance.analysis.source']= source\n }\n if(specimen){\n query['provenance.image.specimen'] = specimen\n }\n if(study){\n query['provenance.image.study'] = study\n }\n res(findInLocalStorage('mark', query))\n }).then(x=>this.filterBroken(x,\"mark\"))\n }\n Store.prototype.getMarkByIds = function(ids, slide, study, specimen, source, footprint, x0, x1, y0, y1){\n return new Promise(function(res, rej){\n let data = []\n for (var i in ids){\n data.push(...findInLocalStorage('mark', {'provenance.analysis.execution_id': ids[i], 'provenance.image.slide': slide}))\n }\n res(data)\n }).then(x=>this.filterBroken(x,\"mark\"))\n }\n Store.prototype.getMark = function(id){\n return new Promise(function(res, rej){\n res(getInLocalStorage(\"mark\", id))\n }).then(x=>this.filterBroken(x,\"mark\"))\n }\n Store.prototype.addMark = function(json){\n if (!this.validation.mark(json)){\n console.warn(this.validation.mark.errors)\n }\n return new Promise(function(res, rej){\n // give it an that's probably semi-unique\n json['_id'] = json['_id'] || {'$oid': Date.now()}\n res(putInLocalStorage('mark', json))\n })\n }\n Store.prototype.deleteMark = function(id, slide){\n return new Promise((res, rej)=>{\n res(removeFromLocalStorage('mark', id))\n })\n }\n Store.prototype.findHeatmap = function(slide, name){\n return new Promise(function(res, rej){\n let query = {}\n if (name){\n query['provenance.image.slide'] = slide\n }\n if(slide){\n query['provenance.analysis.execution_id']= name\n }\n res(findInIDB('heatmap', query))\n }).then(x=>this.filterBroken(x,\"heatmap\"))\n }\n Store.prototype.getHeatmap = function(id){\n return new Promise(function(res, rej){\n res(getInLocalStorage(\"heatmap\", id))\n }).then(x=>this.filterBroken(x,\"heatmap\"))\n }\n Store.prototype.addHeatmap = function(json){\n // give it an that's probably semi-unique\n if (!this.validation.heatmap(json)){\n console.warn(this.validation.heatmap.errors)\n }\n json['_id'] = json['_id'] || {'$oid': Date.now()}\n return new Promise(function(res, rej){\n res(putInIDB('heatmap', json))\n })\n }\n Store.prototype.deleteHeatmap = function(id,slide){\n return new Promise(function(res, rej){\n res(removeFromLocalStorage('heatmap', id))\n })\n }\n\n // import and export functions\n Store.prototype.export = function(type){\n return new Promise(function(res, rej){\n res(window.localStorage.getItem(type))\n })\n }\n // NOTE -- overwrites\n Store.prototype.import = function(type, data){\n return new Promise(function(res, rej){\n res(window.localStorage.setItem(type, data))\n })\n }\n Store.prototype.findSlide = function(slide, specimen, study, location){\n return new Promise(function(res, rej){\n let params = new URLSearchParams(document.location.search.substring(1));\n let slideId = params.get(\"id\") || \"local\";\n let local_dummy = {\n 'id': slideId,\n 'mpp': '0.001',\n 'study':\"\",\n 'specimen':\"\"\n }\n res([local_dummy])\n })\n }\n Store.prototype.getSlide = function(id){\n return new Promise(function(res, rej){\n let params = new URLSearchParams(document.location.search.substring(1));\n let slideId = params.get(\"id\") || \"local\";\n console.log(params)\n let local_dummy = {\n 'id': slideId,\n 'mpp': '0.001',\n 'study':\"\",\n 'specimen':\"\"\n }\n res(local_dummy)\n })\n }\n Store.prototype.findTemplate = function(name,type){\n let query = {}\n if (name){\n query.name = name\n }\n if (type){\n query.type = type\n }\n return new Promise(function(res, rej){\n res(findInLocalStorage(\"template\", query))\n }).then(x=>this.filterBroken(x,\"template\"))\n }\n Store.prototype.getTemplate = function(id){\n return new Promise(function(res, rej){\n res(getInLocalStorage(\"template\", id))\n }).then(x=>this.filterBroken(x,\"template\"))\n }\n Store.prototype.DownloadMarksToFile = function(){\n // downloads marks for the current slide only\n // make the browser download it\n let slide = $D.params.id // portable?\n slide = decodeURIComponent(slide) // fix for url fix\n let query = {}\n query['provenance.image.slide'] = slide\n let data = JSON.parse(window.localStorage.getItem(\"mark\"))\n let text = \"\"\n if (data) {\n text = JSON.stringify(data.filter(x => {\n let matching = true;\n for (var i in query) {\n matching = matching && Object.byString(x, i) == query[i]\n }\n return matching\n }))\n }\n var element = document.createElement('a');\n var blob = new Blob([text], {type: \"application/json\"});\n var uri = URL.createObjectURL(blob);\n element.setAttribute('href', uri);\n element.setAttribute('download', \"markups.json\");\n element.style.display = 'none';\n document.body.appendChild(element);\n element.click();\n document.body.removeChild(element);\n }\n Store.prototype.LoadMarksFromFile = function(){\n // loads marks for the current slide only, without replacement\n // open a file selector\n let slide = $D.params.id\n slide = decodeURIComponent(slide)\n var element = document.createElement('input');\n document.body.appendChild(element);\n element.setAttribute('type', \"file\")\n element.style.display = 'position: fixed; top: -100em';\n element.onchange = function(event) {\n var input = event.target;\n var reader = new FileReader();\n reader.onload = function() {\n var text = reader.result;\n try {\n let data = JSON.parse(text)\n console.log(data)\n data.forEach(x => {\n x.provenance.image.slide = slide\n })\n console.log($VALIDATION.mark)\n let data2 = JSON.parse(window.localStorage.getItem(\"mark\"))\n data2 = data2 || []\n console.log(data2)\n data2 = data2.concat(data)\n data2 = data2.filter($VALIDATION.mark)\n console.log(data2)\n window.localStorage.setItem(\"mark\", JSON.stringify(data2))\n if ($VALIDATION.mark.errors){\n console.error($VALIDATION.mark.errors)\n } else {\n window.location.reload()\n }\n\n } catch (e) {\n console.error(e)\n }\n console.log(text.substring(0, 200));\n };\n reader.readAsText(input.files[0]);\n };\n\n element.click();\n document.body.removeChild(element);\n }\n}\n\n// default template\nlet defaultTemplate = {\n \"_id\": \"0\",\n \"type\": \"object\",\n \"id\": \"annotation-form\",\n \"name\": \"AnnotSchema\",\n \"description\": \"\",\n \"links\": [],\n \"additionalProperties\": false,\n \"properties\": {\n \"name\": {\n \"id\": \"a0\",\n \"title\": \"Identity Name\",\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"note name\"\n },\"notes\": {\n \"id\": \"a1\",\n \"title\": \"Notes: \",\n \"type\": \"string\",\n \"format\":\"textarea\",\n \"maxLength\": 128\n }\n }\n}\n// if no template, add our default\nlet template_data = JSON.parse(window.localStorage.getItem(\"template\"))\nif (!template_data){\n template_data=[];\n template_data.push(defaultTemplate)\n window.localStorage.setItem(\"template\", JSON.stringify(template_data))\n}\n\n\nexport default init_LocalStore\n","function ImgBoxMods() {\n console.warn(\"{imgbox mods enabled}\")\n CaMic.prototype.default_loadImg = CaMic.prototype.loadImg\n CaMic.prototype.loadImg = function(func) {\n var urlParams = new URLSearchParams(window.location.search);\n var img_id = urlParams.get('id');\n let slideId = img_id\n this.slideId = slideId\n this.slideName = slideId\n this.study = \"\"\n this.specimen = \"\"\n fetch(img_id + \"/info.json\").then(response => {\n if (response.status >=400){\n throw response;\n } else {\n return response.json();\n }\n }).then(data => {\n let tile_count = Math.ceil(Math.log2(Math.max(data.height,data.width)))\n let scaleFactors = []\n for(let i=0; i <= tile_count; i++){\n scaleFactors.push(2**i)\n }\n let imbox_source = {\n \"@context\": \"http://iiif.io/api/image/2/context.json\",\n \"@id\": img_id,\n \"height\": data.height,\n \"width\": data.width,\n \"profile\": [\"http://iiif.io/api/image/2/level2.json\"],\n \"protocol\": \"http://iiif.io/api/image\",\n \"tiles\": [{\n \"scaleFactors\": scaleFactors,\n \"width\": 256\n }]\n }\n this.viewer.open(imbox_source);\n // set mpp\n this.mpp_x = +data['mpp-x']\n this.mpp_y = +data['mpp-y']\n this.mpp = data.mpp || this.mpp_x || this.mpp_y || 1e9;\n this.mpp_x = +data['mpp-x'] || this.mpp\n this.mpp_y = +data['mpp-y'] || this.mpp\n\n this.viewer.mpp = this.mpp;\n this.viewer.mpp_x = this.mpp_x;\n this.viewer.mpp_y = this.mpp_y;\n \n //set scalebar\n let mpp = this.mpp_x || this.mpp;\n if(mpp&&mpp!=1e9) this.createScalebar(this.mpp)\n var imagingHelper = new OpenSeadragonImaging.ImagingHelper({\n viewer: this.viewer\n });\n imagingHelper.setMaxZoom(1);\n // create item to pass to the callback function, previously x[0] (slide data)\n let x = {}\n x['_id'] = \"0\"\n x.name = this.slideName\n x.study = this.study\n x.specimen = this.specimen\n x.mpp = this.mpp;\n x.mpp_x = this.mpp_x;\n x.mpp_y = this.mpp_y;\n x.location = img_id;\n x.url = imbox_source;\n if (func && typeof func === 'function'){\n func.call(null, x);\n }\n Loading.text.textContent = `loading slide's tiles...`;\n // WARN; note that spyglass isn't working due to semi-hardcoded value at init.js line 140\n // we may want another init.js or our own callback\n }).catch(e=>{\n console.error(e)\n Loading.text.textContent = \"ERROR - Slide May be Broken or Unsupported\"\n //if(func && typeof func === 'function') func.call(null,{hasError:true,message:e});\n })\n\n }\n}\n\n\nexport default ImgBoxMods\n","import init_LocalStore from './LocalStore.js'\nimport ImgBoxMods from './ImgBoxMods.js'\n\ninit_LocalStore()\nImgBoxMods()\nconsole.warn(\"This setup is intended for imagebox\")\n// parcel build package/imgbox_package.js\n"]} \ No newline at end of file diff --git a/package/LocalStore.js b/package/LocalStore.js index 589e82bd5..29f3b8dd1 100644 --- a/package/LocalStore.js +++ b/package/LocalStore.js @@ -1,6 +1,9 @@ // overwrite store with equivalent local functions function init_LocalStore(){ // requirements + Store.prototype.db = idb.openDb("heatmap", 1, x=>{ + let recordStore = x.createObjectStore("heatmap", {autoIncrement : true}); + }) console.warn("{localstore mods enabled}") Object.byString = function(o, s) { s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties @@ -17,6 +20,33 @@ function init_LocalStore(){ return o; } + function findInIDB(type, query){ + return new Promise((res,rej)=>{ + Store.prototype.db.then(x=>{ + var data = x.transaction(type).objectStore(type, 'readonly').getAll() + data.then(data=>{ + res(data.filter(x=>{ + let matching = true; + for (var i in query){ + matching = matching && Object.byString(x, i) == query[i] + } + return matching + })) + }) + } + ) + }) + } + + function putInIDB(type, newData){ + Store.prototype.db.then(x=>{ + let tx = x.transaction(type, 'readwrite') + var store = tx.objectStore(type) + store.add(newData) + }) + return newData + } + function findInLocalStorage(type, query){ let data = JSON.parse(window.localStorage.getItem(type)) if (data){ @@ -87,6 +117,7 @@ function init_LocalStore(){ // TODO!!! }) } + Store.prototype.findMark = function(slide, name, specimen, study, footprint, source, x0, x1, y0, y1){ return new Promise(function(res, rej){ let query = {} @@ -146,7 +177,7 @@ function init_LocalStore(){ if(slide){ query['provenance.analysis.execution_id']= name } - res(findInLocalStorage('heatmap', query)) + res(findInIDB('heatmap', query)) }).then(x=>this.filterBroken(x,"heatmap")) } Store.prototype.getHeatmap = function(id){ @@ -161,7 +192,7 @@ function init_LocalStore(){ } json['_id'] = json['_id'] || {'$oid': Date.now()} return new Promise(function(res, rej){ - res(putInLocalStorage('heatmap', json)) + res(putInIDB('heatmap', json)) }) } Store.prototype.deleteHeatmap = function(id,slide){ From 82a5b40acd01a8776c93052facd7e8b400a065f1 Mon Sep 17 00:00:00 2001 From: Ryan Birmingham Date: Tue, 5 Mar 2019 17:08:39 -0500 Subject: [PATCH 06/11] get as find due to structure --- dist/imgbox_package.js | 2 +- dist/imgbox_package.map | 2 +- package/LocalStore.js | 15 +++++++++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/dist/imgbox_package.js b/dist/imgbox_package.js index 52458c8af..d3e0261a1 100644 --- a/dist/imgbox_package.js +++ b/dist/imgbox_package.js @@ -1,5 +1,5 @@ parcelRequire=function(e,r,n,t){var i="function"==typeof parcelRequire&&parcelRequire,o="function"==typeof require&&require;function u(n,t){if(!r[n]){if(!e[n]){var f="function"==typeof parcelRequire&&parcelRequire;if(!t&&f)return f(n,!0);if(i)return i(n,!0);if(o&&"string"==typeof n)return o(n);var c=new Error("Cannot find module '"+n+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[n][1][r]||r};var l=r[n]=new u.Module(n);e[n][0].call(l.exports,p,l,l.exports,this)}return r[n].exports;function p(e){return u(p.resolve(e))}}u.isParcelRequire=!0,u.Module=function(e){this.id=e,this.bundle=u,this.exports={}},u.modules=e,u.cache=r,u.parent=i,u.register=function(r,n){e[r]=[function(e,r){r.exports=n},{}]};for(var f=0;f=400)throw e;return e.json()}).then(function(i){for(var o=Math.ceil(Math.log2(Math.max(i.height,i.width))),a=[],n=0;n<=o;n++)a.push(Math.pow(2,n));var m={"@context":"http://iiif.io/api/image/2/context.json","@id":t,height:i.height,width:i.width,profile:["http://iiif.io/api/image/2/level2.json"],protocol:"http://iiif.io/api/image",tiles:[{scaleFactors:a,width:256}]};p.viewer.open(m),p.mpp_x=+i["mpp-x"],p.mpp_y=+i["mpp-y"],p.mpp=i.mpp||p.mpp_x||p.mpp_y||1e9,p.mpp_x=+i["mpp-x"]||p.mpp,p.mpp_y=+i["mpp-y"]||p.mpp,p.viewer.mpp=p.mpp,p.viewer.mpp_x=p.mpp_x,p.viewer.mpp_y=p.mpp_y;var r=p.mpp_x||p.mpp;r&&1e9!=r&&p.createScalebar(p.mpp),new OpenSeadragonImaging.ImagingHelper({viewer:p.viewer}).setMaxZoom(1);var s={_id:"0"};s.name=p.slideName,s.study=p.study,s.specimen=p.specimen,s.mpp=p.mpp,s.mpp_x=p.mpp_x,s.mpp_y=p.mpp_y,s.location=t,s.url=m,e&&"function"==typeof e&&e.call(null,s),Loading.text.textContent="loading slide's tiles..."}).catch(function(e){console.error(e),Loading.text.textContent="ERROR - Slide May be Broken or Unsupported"})}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=e; },{}],"lM4v":[function(require,module,exports) { diff --git a/dist/imgbox_package.map b/dist/imgbox_package.map index a11be3b1f..cb13388f5 100644 --- a/dist/imgbox_package.map +++ b/dist/imgbox_package.map @@ -1 +1 @@ -{"version":3,"sources":["LocalStore.js","ImgBoxMods.js","imgbox_package.js"],"names":["init_LocalStore","findInLocalStorage","type","query","data","JSON","parse","window","localStorage","getItem","filter","matching","i","Object","byString","x","getInLocalStorage","id","removeFromLocalStorage","log","newData","setItem","stringify","length","prototype","db","idb","openDb","createObjectStore","autoIncrement","warn","o","s","a","replace","split","n","k","validation","Store","filterBroken","b","findMarkTypes","slide","name","Promise","res","rej","unique","Set","map","findMark","specimen","study","footprint","source","x0","x1","y0","y1","then","getMarkByIds","ids","push","getMark","addMark","json","mark","errors","putInLocalStorage","Date","now","deleteMark","findHeatmap","findInIDB","transaction","objectStore","getAll","console","getHeatmap","addHeatmap","heatmap","putInIDB","add","deleteHeatmap","export","import","findSlide","location","slideId","URLSearchParams","document","search","substring","get","getSlide","params","local_dummy","findTemplate","getTemplate","DownloadMarksToFile","$D","decodeURIComponent","text","element","createElement","blob","Blob","uri","URL","createObjectURL","setAttribute","style","display","body","appendChild","click","removeChild","LoadMarksFromFile","onchange","event","input","target","reader","FileReader","onload","result","forEach","provenance","image","$VALIDATION","data2","concat","error","reload","e","readAsText","files","defaultTemplate","template_data","ImgBoxMods","default_loadImg","CaMic","loadImg","func","img_id","slideName","response","status","tile_count","Math","ceil","log2","max","height","width","scaleFactors","imbox_source","viewer","open","mpp_x","mpp_y","mpp","createScalebar","OpenSeadragonImaging","ImagingHelper","setMaxZoom","url","call","textContent","catch"],"mappings":"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","file":"imgbox_package.map","sourceRoot":"../package","sourcesContent":["// overwrite store with equivalent local functions\nfunction init_LocalStore(){\n // requirements\n Store.prototype.db = idb.openDb(\"heatmap\", 1, x=>{\n let recordStore = x.createObjectStore(\"heatmap\", {autoIncrement : true});\n })\n console.warn(\"{localstore mods enabled}\")\n Object.byString = function(o, s) {\n s = s.replace(/\\[(\\w+)\\]/g, '.$1'); // convert indexes to properties\n s = s.replace(/^\\./, ''); // strip a leading dot\n var a = s.split('.');\n for (var i = 0, n = a.length; i < n; ++i) {\n var k = a[i];\n if (k in o) {\n o = o[k];\n } else {\n return;\n }\n }\n return o;\n }\n\n function findInIDB(type, query){\n return new Promise((res,rej)=>{\n Store.prototype.db.then(x=>{\n var data = x.transaction(type).objectStore(type, 'readonly').getAll()\n data.then(console.log)\n data.then(data=>{\n res(data.filter(x=>{\n let matching = true;\n for (var i in query){\n matching = matching && Object.byString(x, i) == query[i]\n }\n return matching\n }))\n })\n }\n )\n })\n }\n\n function putInIDB(type, newData){\n Store.prototype.db.then(x=>{\n let tx = x.transaction(type, 'readwrite')\n var store = tx.objectStore(type)\n store.add(newData)\n })\n return newData\n }\n\n function findInLocalStorage(type, query){\n let data = JSON.parse(window.localStorage.getItem(type))\n if (data){\n return data.filter(x=>{\n let matching = true;\n for (var i in query){\n matching = matching && Object.byString(x, i) == query[i]\n }\n return matching\n })\n } else {\n return []\n }\n\n }\n\n function getInLocalStorage(type, id){\n let data = JSON.parse(window.localStorage.getItem(type))\n if (data){\n return data.filter(x=>x['_id'] == id)[0]\n } else {\n return {}\n }\n\n }\n\n function putInLocalStorage(type, newData){\n let data = JSON.parse(window.localStorage.getItem(type))\n data = data || []\n data.push(newData)\n window.localStorage.setItem(type, JSON.stringify(data))\n return newData\n }\n\n function removeFromLocalStorage(type, id){\n console.log(id)\n let data = JSON.parse(window.localStorage.getItem(type))\n data = data || []\n let newData = data.filter(x=>x['_id']['$oid'] !== id)\n window.localStorage.setItem(type, JSON.stringify(newData))\n console.log(data.length - newData.length)\n return {'rowsAffected': data.length - newData.length}\n }\n\n\n\n // stange fixes for potential mismatches in validation version\n Store.prototype.validation = Store.prototype.validation || {}\n Store.prototype.filterBroken = Store.prototype.filterBroken || function(a,b){return a}\n // replace impacted store functionality.\n Store.prototype.findMarkTypes = function(slide, name){\n return new Promise(function(res, rej){\n let query={}\n if(name){\n query['provenance.analysis.execution_id']= name\n }\n if(slide){\n query['provenance.image.slide'] = slide\n }\n let data = findInLocalStorage(\"mark\", query)\n if (data){\n const unique = [...new Set(data.map(x => Object.byString(x,'provenance')))];\n res(unique)\n } else {\n res([])\n }\n\n // TODO!!!\n })\n }\n\n Store.prototype.findMark = function(slide, name, specimen, study, footprint, source, x0, x1, y0, y1){\n return new Promise(function(res, rej){\n let query = {}\n if (name){\n query['provenance.image.slide'] = slide\n }\n if(slide){\n query['provenance.analysis.execution_id']= name\n }\n if(source){\n query['provenance.analysis.source']= source\n }\n if(specimen){\n query['provenance.image.specimen'] = specimen\n }\n if(study){\n query['provenance.image.study'] = study\n }\n res(findInLocalStorage('mark', query))\n }).then(x=>this.filterBroken(x,\"mark\"))\n }\n Store.prototype.getMarkByIds = function(ids, slide, study, specimen, source, footprint, x0, x1, y0, y1){\n return new Promise(function(res, rej){\n let data = []\n for (var i in ids){\n data.push(...findInLocalStorage('mark', {'provenance.analysis.execution_id': ids[i], 'provenance.image.slide': slide}))\n }\n res(data)\n }).then(x=>this.filterBroken(x,\"mark\"))\n }\n Store.prototype.getMark = function(id){\n return new Promise(function(res, rej){\n res(getInLocalStorage(\"mark\", id))\n }).then(x=>this.filterBroken(x,\"mark\"))\n }\n Store.prototype.addMark = function(json){\n if (!this.validation.mark(json)){\n console.warn(this.validation.mark.errors)\n }\n return new Promise(function(res, rej){\n // give it an that's probably semi-unique\n json['_id'] = json['_id'] || {'$oid': Date.now()}\n res(putInLocalStorage('mark', json))\n })\n }\n Store.prototype.deleteMark = function(id, slide){\n return new Promise((res, rej)=>{\n res(removeFromLocalStorage('mark', id))\n })\n }\n Store.prototype.findHeatmap = function(slide, name){\n return new Promise(function(res, rej){\n let query = {}\n if (name){\n query['provenance.image.slide'] = slide\n }\n if(slide){\n query['provenance.analysis.execution_id']= name\n }\n res(findInIDB('heatmap', query))\n }).then(x=>this.filterBroken(x,\"heatmap\"))\n }\n Store.prototype.getHeatmap = function(id){\n return new Promise(function(res, rej){\n res(getInLocalStorage(\"heatmap\", id))\n }).then(x=>this.filterBroken(x,\"heatmap\"))\n }\n Store.prototype.addHeatmap = function(json){\n // give it an that's probably semi-unique\n if (!this.validation.heatmap(json)){\n console.warn(this.validation.heatmap.errors)\n }\n json['_id'] = json['_id'] || {'$oid': Date.now()}\n return new Promise(function(res, rej){\n res(putInIDB('heatmap', json))\n })\n }\n Store.prototype.deleteHeatmap = function(id,slide){\n return new Promise(function(res, rej){\n res(removeFromLocalStorage('heatmap', id))\n })\n }\n\n // import and export functions\n Store.prototype.export = function(type){\n return new Promise(function(res, rej){\n res(window.localStorage.getItem(type))\n })\n }\n // NOTE -- overwrites\n Store.prototype.import = function(type, data){\n return new Promise(function(res, rej){\n res(window.localStorage.setItem(type, data))\n })\n }\n Store.prototype.findSlide = function(slide, specimen, study, location){\n return new Promise(function(res, rej){\n let params = new URLSearchParams(document.location.search.substring(1));\n let slideId = params.get(\"id\") || \"local\";\n let local_dummy = {\n 'id': slideId,\n 'mpp': '0.001',\n 'study':\"\",\n 'specimen':\"\"\n }\n res([local_dummy])\n })\n }\n Store.prototype.getSlide = function(id){\n return new Promise(function(res, rej){\n let params = new URLSearchParams(document.location.search.substring(1));\n let slideId = params.get(\"id\") || \"local\";\n console.log(params)\n let local_dummy = {\n 'id': slideId,\n 'mpp': '0.001',\n 'study':\"\",\n 'specimen':\"\"\n }\n res(local_dummy)\n })\n }\n Store.prototype.findTemplate = function(name,type){\n let query = {}\n if (name){\n query.name = name\n }\n if (type){\n query.type = type\n }\n return new Promise(function(res, rej){\n res(findInLocalStorage(\"template\", query))\n }).then(x=>this.filterBroken(x,\"template\"))\n }\n Store.prototype.getTemplate = function(id){\n return new Promise(function(res, rej){\n res(getInLocalStorage(\"template\", id))\n }).then(x=>this.filterBroken(x,\"template\"))\n }\n Store.prototype.DownloadMarksToFile = function(){\n // downloads marks for the current slide only\n // make the browser download it\n let slide = $D.params.id // portable?\n slide = decodeURIComponent(slide) // fix for url fix\n let query = {}\n query['provenance.image.slide'] = slide\n let data = JSON.parse(window.localStorage.getItem(\"mark\"))\n let text = \"\"\n if (data) {\n text = JSON.stringify(data.filter(x => {\n let matching = true;\n for (var i in query) {\n matching = matching && Object.byString(x, i) == query[i]\n }\n return matching\n }))\n }\n var element = document.createElement('a');\n var blob = new Blob([text], {type: \"application/json\"});\n var uri = URL.createObjectURL(blob);\n element.setAttribute('href', uri);\n element.setAttribute('download', \"markups.json\");\n element.style.display = 'none';\n document.body.appendChild(element);\n element.click();\n document.body.removeChild(element);\n }\n Store.prototype.LoadMarksFromFile = function(){\n // loads marks for the current slide only, without replacement\n // open a file selector\n let slide = $D.params.id\n slide = decodeURIComponent(slide)\n var element = document.createElement('input');\n document.body.appendChild(element);\n element.setAttribute('type', \"file\")\n element.style.display = 'position: fixed; top: -100em';\n element.onchange = function(event) {\n var input = event.target;\n var reader = new FileReader();\n reader.onload = function() {\n var text = reader.result;\n try {\n let data = JSON.parse(text)\n console.log(data)\n data.forEach(x => {\n x.provenance.image.slide = slide\n })\n console.log($VALIDATION.mark)\n let data2 = JSON.parse(window.localStorage.getItem(\"mark\"))\n data2 = data2 || []\n console.log(data2)\n data2 = data2.concat(data)\n data2 = data2.filter($VALIDATION.mark)\n console.log(data2)\n window.localStorage.setItem(\"mark\", JSON.stringify(data2))\n if ($VALIDATION.mark.errors){\n console.error($VALIDATION.mark.errors)\n } else {\n window.location.reload()\n }\n\n } catch (e) {\n console.error(e)\n }\n console.log(text.substring(0, 200));\n };\n reader.readAsText(input.files[0]);\n };\n\n element.click();\n document.body.removeChild(element);\n }\n}\n\n// default template\nlet defaultTemplate = {\n \"_id\": \"0\",\n \"type\": \"object\",\n \"id\": \"annotation-form\",\n \"name\": \"AnnotSchema\",\n \"description\": \"\",\n \"links\": [],\n \"additionalProperties\": false,\n \"properties\": {\n \"name\": {\n \"id\": \"a0\",\n \"title\": \"Identity Name\",\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"note name\"\n },\"notes\": {\n \"id\": \"a1\",\n \"title\": \"Notes: \",\n \"type\": \"string\",\n \"format\":\"textarea\",\n \"maxLength\": 128\n }\n }\n}\n// if no template, add our default\nlet template_data = JSON.parse(window.localStorage.getItem(\"template\"))\nif (!template_data){\n template_data=[];\n template_data.push(defaultTemplate)\n window.localStorage.setItem(\"template\", JSON.stringify(template_data))\n}\n\n\nexport default init_LocalStore\n","function ImgBoxMods() {\n console.warn(\"{imgbox mods enabled}\")\n CaMic.prototype.default_loadImg = CaMic.prototype.loadImg\n CaMic.prototype.loadImg = function(func) {\n var urlParams = new URLSearchParams(window.location.search);\n var img_id = urlParams.get('id');\n let slideId = img_id\n this.slideId = slideId\n this.slideName = slideId\n this.study = \"\"\n this.specimen = \"\"\n fetch(img_id + \"/info.json\").then(response => {\n if (response.status >=400){\n throw response;\n } else {\n return response.json();\n }\n }).then(data => {\n let tile_count = Math.ceil(Math.log2(Math.max(data.height,data.width)))\n let scaleFactors = []\n for(let i=0; i <= tile_count; i++){\n scaleFactors.push(2**i)\n }\n let imbox_source = {\n \"@context\": \"http://iiif.io/api/image/2/context.json\",\n \"@id\": img_id,\n \"height\": data.height,\n \"width\": data.width,\n \"profile\": [\"http://iiif.io/api/image/2/level2.json\"],\n \"protocol\": \"http://iiif.io/api/image\",\n \"tiles\": [{\n \"scaleFactors\": scaleFactors,\n \"width\": 256\n }]\n }\n this.viewer.open(imbox_source);\n // set mpp\n this.mpp_x = +data['mpp-x']\n this.mpp_y = +data['mpp-y']\n this.mpp = data.mpp || this.mpp_x || this.mpp_y || 1e9;\n this.mpp_x = +data['mpp-x'] || this.mpp\n this.mpp_y = +data['mpp-y'] || this.mpp\n\n this.viewer.mpp = this.mpp;\n this.viewer.mpp_x = this.mpp_x;\n this.viewer.mpp_y = this.mpp_y;\n \n //set scalebar\n let mpp = this.mpp_x || this.mpp;\n if(mpp&&mpp!=1e9) this.createScalebar(this.mpp)\n var imagingHelper = new OpenSeadragonImaging.ImagingHelper({\n viewer: this.viewer\n });\n imagingHelper.setMaxZoom(1);\n // create item to pass to the callback function, previously x[0] (slide data)\n let x = {}\n x['_id'] = \"0\"\n x.name = this.slideName\n x.study = this.study\n x.specimen = this.specimen\n x.mpp = this.mpp;\n x.mpp_x = this.mpp_x;\n x.mpp_y = this.mpp_y;\n x.location = img_id;\n x.url = imbox_source;\n if (func && typeof func === 'function'){\n func.call(null, x);\n }\n Loading.text.textContent = `loading slide's tiles...`;\n // WARN; note that spyglass isn't working due to semi-hardcoded value at init.js line 140\n // we may want another init.js or our own callback\n }).catch(e=>{\n console.error(e)\n Loading.text.textContent = \"ERROR - Slide May be Broken or Unsupported\"\n //if(func && typeof func === 'function') func.call(null,{hasError:true,message:e});\n })\n\n }\n}\n\n\nexport default ImgBoxMods\n","import init_LocalStore from './LocalStore.js'\nimport ImgBoxMods from './ImgBoxMods.js'\n\ninit_LocalStore()\nImgBoxMods()\nconsole.warn(\"This setup is intended for imagebox\")\n// parcel build package/imgbox_package.js\n"]} \ No newline at end of file +{"version":3,"sources":["LocalStore.js","ImgBoxMods.js","imgbox_package.js"],"names":["init_LocalStore","findInIDB","type","query","Promise","res","rej","prototype","db","then","x","transaction","objectStore","getAll","data","filter","matching","i","Object","byString","findInLocalStorage","JSON","parse","window","localStorage","getItem","getInLocalStorage","id","removeFromLocalStorage","log","newData","setItem","stringify","length","idb","openDb","createObjectStore","autoIncrement","warn","o","s","a","replace","split","n","k","validation","Store","filterBroken","b","findMarkTypes","slide","name","unique","Set","map","findMark","specimen","study","footprint","source","x0","x1","y0","y1","getMarkByIds","ids","push","getMark","addMark","json","mark","errors","putInLocalStorage","Date","now","deleteMark","findHeatmap","getHeatmap","execution_id","addHeatmap","heatmap","putInIDB","add","deleteHeatmap","export","import","findSlide","location","slideId","URLSearchParams","document","search","substring","get","getSlide","params","local_dummy","findTemplate","getTemplate","DownloadMarksToFile","$D","decodeURIComponent","text","element","createElement","blob","Blob","uri","URL","createObjectURL","setAttribute","style","display","body","appendChild","click","removeChild","LoadMarksFromFile","onchange","event","input","target","reader","FileReader","onload","result","forEach","provenance","image","$VALIDATION","data2","concat","error","reload","e","readAsText","files","defaultTemplate","template_data","ImgBoxMods","default_loadImg","CaMic","loadImg","func","img_id","slideName","response","status","tile_count","Math","ceil","log2","max","height","width","scaleFactors","imbox_source","viewer","open","mpp_x","mpp_y","mpp","createScalebar","OpenSeadragonImaging","ImagingHelper","setMaxZoom","url","call","textContent","catch","console"],"mappings":"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","file":"imgbox_package.map","sourceRoot":"../package","sourcesContent":["// overwrite store with equivalent local functions\nfunction init_LocalStore(){\n // requirements\n Store.prototype.db = idb.openDb(\"heatmap\", 1, x=>{\n let recordStore = x.createObjectStore(\"heatmap\", {autoIncrement : true});\n })\n console.warn(\"{localstore mods enabled}\")\n Object.byString = function(o, s) {\n s = s.replace(/\\[(\\w+)\\]/g, '.$1'); // convert indexes to properties\n s = s.replace(/^\\./, ''); // strip a leading dot\n var a = s.split('.');\n for (var i = 0, n = a.length; i < n; ++i) {\n var k = a[i];\n if (k in o) {\n o = o[k];\n } else {\n return;\n }\n }\n return o;\n }\n\n function findInIDB(type, query){\n return new Promise((res,rej)=>{\n Store.prototype.db.then(x=>{\n var data = x.transaction(type).objectStore(type, 'readonly').getAll()\n data.then(data=>{\n res(data.filter(x=>{\n let matching = true;\n for (var i in query){\n matching = matching && Object.byString(x, i) == query[i]\n }\n return matching\n }))\n })\n }\n )\n })\n }\n\n function putInIDB(type, newData){\n Store.prototype.db.then(x=>{\n let tx = x.transaction(type, 'readwrite')\n var store = tx.objectStore(type)\n store.add(newData)\n })\n return newData\n }\n\n function findInLocalStorage(type, query){\n let data = JSON.parse(window.localStorage.getItem(type))\n if (data){\n return data.filter(x=>{\n let matching = true;\n for (var i in query){\n matching = matching && Object.byString(x, i) == query[i]\n }\n return matching\n })\n } else {\n return []\n }\n\n }\n\n function getInLocalStorage(type, id){\n let data = JSON.parse(window.localStorage.getItem(type))\n if (data){\n return data.filter(x=>x['_id'] == id)[0]\n } else {\n return {}\n }\n\n }\n\n function putInLocalStorage(type, newData){\n let data = JSON.parse(window.localStorage.getItem(type))\n data = data || []\n data.push(newData)\n window.localStorage.setItem(type, JSON.stringify(data))\n return newData\n }\n\n function removeFromLocalStorage(type, id){\n console.log(id)\n let data = JSON.parse(window.localStorage.getItem(type))\n data = data || []\n let newData = data.filter(x=>x['_id']['$oid'] !== id)\n window.localStorage.setItem(type, JSON.stringify(newData))\n console.log(data.length - newData.length)\n return {'rowsAffected': data.length - newData.length}\n }\n\n\n\n // stange fixes for potential mismatches in validation version\n Store.prototype.validation = Store.prototype.validation || {}\n Store.prototype.filterBroken = Store.prototype.filterBroken || function(a,b){return a}\n // replace impacted store functionality.\n Store.prototype.findMarkTypes = function(slide, name){\n return new Promise(function(res, rej){\n let query={}\n if(name){\n query['provenance.analysis.execution_id']= name\n }\n if(slide){\n query['provenance.image.slide'] = slide\n }\n let data = findInLocalStorage(\"mark\", query)\n if (data){\n const unique = [...new Set(data.map(x => Object.byString(x,'provenance')))];\n res(unique)\n } else {\n res([])\n }\n\n // TODO!!!\n })\n }\n\n Store.prototype.findMark = function(slide, name, specimen, study, footprint, source, x0, x1, y0, y1){\n return new Promise(function(res, rej){\n let query = {}\n if (name){\n query['provenance.image.slide'] = slide\n }\n if(slide){\n query['provenance.analysis.execution_id']= name\n }\n if(source){\n query['provenance.analysis.source']= source\n }\n if(specimen){\n query['provenance.image.specimen'] = specimen\n }\n if(study){\n query['provenance.image.study'] = study\n }\n res(findInLocalStorage('mark', query))\n }).then(x=>this.filterBroken(x,\"mark\"))\n }\n Store.prototype.getMarkByIds = function(ids, slide, study, specimen, source, footprint, x0, x1, y0, y1){\n return new Promise(function(res, rej){\n let data = []\n for (var i in ids){\n data.push(...findInLocalStorage('mark', {'provenance.analysis.execution_id': ids[i], 'provenance.image.slide': slide}))\n }\n res(data)\n }).then(x=>this.filterBroken(x,\"mark\"))\n }\n Store.prototype.getMark = function(id){\n return new Promise(function(res, rej){\n res(getInLocalStorage(\"mark\", id))\n }).then(x=>this.filterBroken(x,\"mark\"))\n }\n Store.prototype.addMark = function(json){\n if (!this.validation.mark(json)){\n console.warn(this.validation.mark.errors)\n }\n return new Promise(function(res, rej){\n // give it an that's probably semi-unique\n json['_id'] = json['_id'] || {'$oid': Date.now()}\n res(putInLocalStorage('mark', json))\n })\n }\n Store.prototype.deleteMark = function(id, slide){\n return new Promise((res, rej)=>{\n res(removeFromLocalStorage('mark', id))\n })\n }\n Store.prototype.findHeatmap = function(slide, name){\n return new Promise(function(res, rej){\n let query = {}\n if (slide){\n query['provenance.image.slide'] = slide\n }\n if(name){\n query['provenance.analysis.execution_id']= name\n }\n res(findInIDB('heatmap', query))\n }).then(x=>this.filterBroken(x,\"heatmap\"))\n }\n Store.prototype.getHeatmap = function(slide, execution_id){\n return new Promise(function(res, rej){\n let query = {}\n if (slide){\n query['provenance.image.slide'] = slide\n }\n if(execution_id){\n query['provenance.analysis.execution_id']= execution_id\n }\n res(findInIDB('heatmap', query))\n }).then(x=>this.filterBroken(x,\"heatmap\"))\n }\n Store.prototype.addHeatmap = function(json){\n // give it an that's probably semi-unique\n if (!this.validation.heatmap(json)){\n console.warn(this.validation.heatmap.errors)\n }\n json['_id'] = json['_id'] || {'$oid': Date.now()}\n return new Promise(function(res, rej){\n res(putInIDB('heatmap', json))\n })\n }\n Store.prototype.deleteHeatmap = function(id,slide){\n return new Promise(function(res, rej){\n res(removeFromLocalStorage('heatmap', id))\n })\n }\n\n // import and export functions\n Store.prototype.export = function(type){\n return new Promise(function(res, rej){\n res(window.localStorage.getItem(type))\n })\n }\n // NOTE -- overwrites\n Store.prototype.import = function(type, data){\n return new Promise(function(res, rej){\n res(window.localStorage.setItem(type, data))\n })\n }\n Store.prototype.findSlide = function(slide, specimen, study, location){\n return new Promise(function(res, rej){\n let params = new URLSearchParams(document.location.search.substring(1));\n let slideId = params.get(\"id\") || \"local\";\n let local_dummy = {\n 'id': slideId,\n 'mpp': '0.001',\n 'study':\"\",\n 'specimen':\"\"\n }\n res([local_dummy])\n })\n }\n Store.prototype.getSlide = function(id){\n return new Promise(function(res, rej){\n let params = new URLSearchParams(document.location.search.substring(1));\n let slideId = params.get(\"id\") || \"local\";\n console.log(params)\n let local_dummy = {\n 'id': slideId,\n 'mpp': '0.001',\n 'study':\"\",\n 'specimen':\"\"\n }\n res(local_dummy)\n })\n }\n Store.prototype.findTemplate = function(name,type){\n let query = {}\n if (name){\n query.name = name\n }\n if (type){\n query.type = type\n }\n return new Promise(function(res, rej){\n res(findInLocalStorage(\"template\", query))\n }).then(x=>this.filterBroken(x,\"template\"))\n }\n Store.prototype.getTemplate = function(id){\n return new Promise(function(res, rej){\n res(getInLocalStorage(\"template\", id))\n }).then(x=>this.filterBroken(x,\"template\"))\n }\n Store.prototype.DownloadMarksToFile = function(){\n // downloads marks for the current slide only\n // make the browser download it\n let slide = $D.params.id // portable?\n slide = decodeURIComponent(slide) // fix for url fix\n let query = {}\n query['provenance.image.slide'] = slide\n let data = JSON.parse(window.localStorage.getItem(\"mark\"))\n let text = \"\"\n if (data) {\n text = JSON.stringify(data.filter(x => {\n let matching = true;\n for (var i in query) {\n matching = matching && Object.byString(x, i) == query[i]\n }\n return matching\n }))\n }\n var element = document.createElement('a');\n var blob = new Blob([text], {type: \"application/json\"});\n var uri = URL.createObjectURL(blob);\n element.setAttribute('href', uri);\n element.setAttribute('download', \"markups.json\");\n element.style.display = 'none';\n document.body.appendChild(element);\n element.click();\n document.body.removeChild(element);\n }\n Store.prototype.LoadMarksFromFile = function(){\n // loads marks for the current slide only, without replacement\n // open a file selector\n let slide = $D.params.id\n slide = decodeURIComponent(slide)\n var element = document.createElement('input');\n document.body.appendChild(element);\n element.setAttribute('type', \"file\")\n element.style.display = 'position: fixed; top: -100em';\n element.onchange = function(event) {\n var input = event.target;\n var reader = new FileReader();\n reader.onload = function() {\n var text = reader.result;\n try {\n let data = JSON.parse(text)\n console.log(data)\n data.forEach(x => {\n x.provenance.image.slide = slide\n })\n console.log($VALIDATION.mark)\n let data2 = JSON.parse(window.localStorage.getItem(\"mark\"))\n data2 = data2 || []\n console.log(data2)\n data2 = data2.concat(data)\n data2 = data2.filter($VALIDATION.mark)\n console.log(data2)\n window.localStorage.setItem(\"mark\", JSON.stringify(data2))\n if ($VALIDATION.mark.errors){\n console.error($VALIDATION.mark.errors)\n } else {\n window.location.reload()\n }\n\n } catch (e) {\n console.error(e)\n }\n console.log(text.substring(0, 200));\n };\n reader.readAsText(input.files[0]);\n };\n\n element.click();\n document.body.removeChild(element);\n }\n}\n\n// default template\nlet defaultTemplate = {\n \"_id\": \"0\",\n \"type\": \"object\",\n \"id\": \"annotation-form\",\n \"name\": \"AnnotSchema\",\n \"description\": \"\",\n \"links\": [],\n \"additionalProperties\": false,\n \"properties\": {\n \"name\": {\n \"id\": \"a0\",\n \"title\": \"Identity Name\",\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"note name\"\n },\"notes\": {\n \"id\": \"a1\",\n \"title\": \"Notes: \",\n \"type\": \"string\",\n \"format\":\"textarea\",\n \"maxLength\": 128\n }\n }\n}\n// if no template, add our default\nlet template_data = JSON.parse(window.localStorage.getItem(\"template\"))\nif (!template_data){\n template_data=[];\n template_data.push(defaultTemplate)\n window.localStorage.setItem(\"template\", JSON.stringify(template_data))\n}\n\n\nexport default init_LocalStore\n","function ImgBoxMods() {\n console.warn(\"{imgbox mods enabled}\")\n CaMic.prototype.default_loadImg = CaMic.prototype.loadImg\n CaMic.prototype.loadImg = function(func) {\n var urlParams = new URLSearchParams(window.location.search);\n var img_id = urlParams.get('id');\n let slideId = img_id\n this.slideId = slideId\n this.slideName = slideId\n this.study = \"\"\n this.specimen = \"\"\n fetch(img_id + \"/info.json\").then(response => {\n if (response.status >=400){\n throw response;\n } else {\n return response.json();\n }\n }).then(data => {\n let tile_count = Math.ceil(Math.log2(Math.max(data.height,data.width)))\n let scaleFactors = []\n for(let i=0; i <= tile_count; i++){\n scaleFactors.push(2**i)\n }\n let imbox_source = {\n \"@context\": \"http://iiif.io/api/image/2/context.json\",\n \"@id\": img_id,\n \"height\": data.height,\n \"width\": data.width,\n \"profile\": [\"http://iiif.io/api/image/2/level2.json\"],\n \"protocol\": \"http://iiif.io/api/image\",\n \"tiles\": [{\n \"scaleFactors\": scaleFactors,\n \"width\": 256\n }]\n }\n this.viewer.open(imbox_source);\n // set mpp\n this.mpp_x = +data['mpp-x']\n this.mpp_y = +data['mpp-y']\n this.mpp = data.mpp || this.mpp_x || this.mpp_y || 1e9;\n this.mpp_x = +data['mpp-x'] || this.mpp\n this.mpp_y = +data['mpp-y'] || this.mpp\n\n this.viewer.mpp = this.mpp;\n this.viewer.mpp_x = this.mpp_x;\n this.viewer.mpp_y = this.mpp_y;\n \n //set scalebar\n let mpp = this.mpp_x || this.mpp;\n if(mpp&&mpp!=1e9) this.createScalebar(this.mpp)\n var imagingHelper = new OpenSeadragonImaging.ImagingHelper({\n viewer: this.viewer\n });\n imagingHelper.setMaxZoom(1);\n // create item to pass to the callback function, previously x[0] (slide data)\n let x = {}\n x['_id'] = \"0\"\n x.name = this.slideName\n x.study = this.study\n x.specimen = this.specimen\n x.mpp = this.mpp;\n x.mpp_x = this.mpp_x;\n x.mpp_y = this.mpp_y;\n x.location = img_id;\n x.url = imbox_source;\n if (func && typeof func === 'function'){\n func.call(null, x);\n }\n Loading.text.textContent = `loading slide's tiles...`;\n // WARN; note that spyglass isn't working due to semi-hardcoded value at init.js line 140\n // we may want another init.js or our own callback\n }).catch(e=>{\n console.error(e)\n Loading.text.textContent = \"ERROR - Slide May be Broken or Unsupported\"\n //if(func && typeof func === 'function') func.call(null,{hasError:true,message:e});\n })\n\n }\n}\n\n\nexport default ImgBoxMods\n","import init_LocalStore from './LocalStore.js'\nimport ImgBoxMods from './ImgBoxMods.js'\n\ninit_LocalStore()\nImgBoxMods()\nconsole.warn(\"This setup is intended for imagebox\")\n// parcel build package/imgbox_package.js\n"]} \ No newline at end of file diff --git a/package/LocalStore.js b/package/LocalStore.js index 29f3b8dd1..ee95eecc4 100644 --- a/package/LocalStore.js +++ b/package/LocalStore.js @@ -171,18 +171,25 @@ function init_LocalStore(){ Store.prototype.findHeatmap = function(slide, name){ return new Promise(function(res, rej){ let query = {} - if (name){ + if (slide){ query['provenance.image.slide'] = slide } - if(slide){ + if(name){ query['provenance.analysis.execution_id']= name } res(findInIDB('heatmap', query)) }).then(x=>this.filterBroken(x,"heatmap")) } - Store.prototype.getHeatmap = function(id){ + Store.prototype.getHeatmap = function(slide, execution_id){ return new Promise(function(res, rej){ - res(getInLocalStorage("heatmap", id)) + let query = {} + if (slide){ + query['provenance.image.slide'] = slide + } + if(execution_id){ + query['provenance.analysis.execution_id']= execution_id + } + res(findInIDB('heatmap', query)) }).then(x=>this.filterBroken(x,"heatmap")) } Store.prototype.addHeatmap = function(json){ From a70877d2ca9ebe34e086f96f65e25cd462b78e96 Mon Sep 17 00:00:00 2001 From: Ryan Birmingham Date: Tue, 5 Mar 2019 17:20:00 -0500 Subject: [PATCH 07/11] add idb helper --- common/idb.js | 316 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 common/idb.js diff --git a/common/idb.js b/common/idb.js new file mode 100644 index 000000000..7a61396d9 --- /dev/null +++ b/common/idb.js @@ -0,0 +1,316 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = global || self, factory(global.idb = {})); +}(this, function (exports) { 'use strict'; + + function toArray(arr) { + return Array.prototype.slice.call(arr); + } + + function promisifyRequest(request) { + return new Promise(function(resolve, reject) { + request.onsuccess = function() { + resolve(request.result); + }; + + request.onerror = function() { + reject(request.error); + }; + }); + } + + function promisifyRequestCall(obj, method, args) { + var request; + var p = new Promise(function(resolve, reject) { + request = obj[method].apply(obj, args); + promisifyRequest(request).then(resolve, reject); + }); + + p.request = request; + return p; + } + + function promisifyCursorRequestCall(obj, method, args) { + var p = promisifyRequestCall(obj, method, args); + return p.then(function(value) { + if (!value) return; + return new Cursor(value, p.request); + }); + } + + function proxyProperties(ProxyClass, targetProp, properties) { + properties.forEach(function(prop) { + Object.defineProperty(ProxyClass.prototype, prop, { + get: function() { + return this[targetProp][prop]; + }, + set: function(val) { + this[targetProp][prop] = val; + } + }); + }); + } + + function proxyRequestMethods(ProxyClass, targetProp, Constructor, properties) { + properties.forEach(function(prop) { + if (!(prop in Constructor.prototype)) return; + ProxyClass.prototype[prop] = function() { + return promisifyRequestCall(this[targetProp], prop, arguments); + }; + }); + } + + function proxyMethods(ProxyClass, targetProp, Constructor, properties) { + properties.forEach(function(prop) { + if (!(prop in Constructor.prototype)) return; + ProxyClass.prototype[prop] = function() { + return this[targetProp][prop].apply(this[targetProp], arguments); + }; + }); + } + + function proxyCursorRequestMethods(ProxyClass, targetProp, Constructor, properties) { + properties.forEach(function(prop) { + if (!(prop in Constructor.prototype)) return; + ProxyClass.prototype[prop] = function() { + return promisifyCursorRequestCall(this[targetProp], prop, arguments); + }; + }); + } + + function Index(index) { + this._index = index; + } + + proxyProperties(Index, '_index', [ + 'name', + 'keyPath', + 'multiEntry', + 'unique' + ]); + + proxyRequestMethods(Index, '_index', IDBIndex, [ + 'get', + 'getKey', + 'getAll', + 'getAllKeys', + 'count' + ]); + + proxyCursorRequestMethods(Index, '_index', IDBIndex, [ + 'openCursor', + 'openKeyCursor' + ]); + + function Cursor(cursor, request) { + this._cursor = cursor; + this._request = request; + } + + proxyProperties(Cursor, '_cursor', [ + 'direction', + 'key', + 'primaryKey', + 'value' + ]); + + proxyRequestMethods(Cursor, '_cursor', IDBCursor, [ + 'update', + 'delete' + ]); + + // proxy 'next' methods + ['advance', 'continue', 'continuePrimaryKey'].forEach(function(methodName) { + if (!(methodName in IDBCursor.prototype)) return; + Cursor.prototype[methodName] = function() { + var cursor = this; + var args = arguments; + return Promise.resolve().then(function() { + cursor._cursor[methodName].apply(cursor._cursor, args); + return promisifyRequest(cursor._request).then(function(value) { + if (!value) return; + return new Cursor(value, cursor._request); + }); + }); + }; + }); + + function ObjectStore(store) { + this._store = store; + } + + ObjectStore.prototype.createIndex = function() { + return new Index(this._store.createIndex.apply(this._store, arguments)); + }; + + ObjectStore.prototype.index = function() { + return new Index(this._store.index.apply(this._store, arguments)); + }; + + proxyProperties(ObjectStore, '_store', [ + 'name', + 'keyPath', + 'indexNames', + 'autoIncrement' + ]); + + proxyRequestMethods(ObjectStore, '_store', IDBObjectStore, [ + 'put', + 'add', + 'delete', + 'clear', + 'get', + 'getAll', + 'getKey', + 'getAllKeys', + 'count' + ]); + + proxyCursorRequestMethods(ObjectStore, '_store', IDBObjectStore, [ + 'openCursor', + 'openKeyCursor' + ]); + + proxyMethods(ObjectStore, '_store', IDBObjectStore, [ + 'deleteIndex' + ]); + + function Transaction(idbTransaction) { + this._tx = idbTransaction; + this.complete = new Promise(function(resolve, reject) { + idbTransaction.oncomplete = function() { + resolve(); + }; + idbTransaction.onerror = function() { + reject(idbTransaction.error); + }; + idbTransaction.onabort = function() { + reject(idbTransaction.error); + }; + }); + } + + Transaction.prototype.objectStore = function() { + return new ObjectStore(this._tx.objectStore.apply(this._tx, arguments)); + }; + + proxyProperties(Transaction, '_tx', [ + 'objectStoreNames', + 'mode' + ]); + + proxyMethods(Transaction, '_tx', IDBTransaction, [ + 'abort' + ]); + + function UpgradeDB(db, oldVersion, transaction) { + this._db = db; + this.oldVersion = oldVersion; + this.transaction = new Transaction(transaction); + } + + UpgradeDB.prototype.createObjectStore = function() { + return new ObjectStore(this._db.createObjectStore.apply(this._db, arguments)); + }; + + proxyProperties(UpgradeDB, '_db', [ + 'name', + 'version', + 'objectStoreNames' + ]); + + proxyMethods(UpgradeDB, '_db', IDBDatabase, [ + 'deleteObjectStore', + 'close' + ]); + + function DB(db) { + this._db = db; + } + + DB.prototype.transaction = function() { + return new Transaction(this._db.transaction.apply(this._db, arguments)); + }; + + proxyProperties(DB, '_db', [ + 'name', + 'version', + 'objectStoreNames' + ]); + + proxyMethods(DB, '_db', IDBDatabase, [ + 'close' + ]); + + // Add cursor iterators + // TODO: remove this once browsers do the right thing with promises + ['openCursor', 'openKeyCursor'].forEach(function(funcName) { + [ObjectStore, Index].forEach(function(Constructor) { + // Don't create iterateKeyCursor if openKeyCursor doesn't exist. + if (!(funcName in Constructor.prototype)) return; + + Constructor.prototype[funcName.replace('open', 'iterate')] = function() { + var args = toArray(arguments); + var callback = args[args.length - 1]; + var nativeObject = this._store || this._index; + var request = nativeObject[funcName].apply(nativeObject, args.slice(0, -1)); + request.onsuccess = function() { + callback(request.result); + }; + }; + }); + }); + + // polyfill getAll + [Index, ObjectStore].forEach(function(Constructor) { + if (Constructor.prototype.getAll) return; + Constructor.prototype.getAll = function(query, count) { + var instance = this; + var items = []; + + return new Promise(function(resolve) { + instance.iterateCursor(query, function(cursor) { + if (!cursor) { + resolve(items); + return; + } + items.push(cursor.value); + + if (count !== undefined && items.length == count) { + resolve(items); + return; + } + cursor.continue(); + }); + }); + }; + }); + + function openDb(name, version, upgradeCallback) { + var p = promisifyRequestCall(indexedDB, 'open', [name, version]); + var request = p.request; + + if (request) { + request.onupgradeneeded = function(event) { + if (upgradeCallback) { + upgradeCallback(new UpgradeDB(request.result, event.oldVersion, request.transaction)); + } + }; + } + + return p.then(function(db) { + return new DB(db); + }); + } + + function deleteDb(name) { + return promisifyRequestCall(indexedDB, 'deleteDatabase', [name]); + } + + exports.openDb = openDb; + exports.deleteDb = deleteDb; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); From 22d0ae975b50d0fde7ffa8dd553b800ef9226bea Mon Sep 17 00:00:00 2001 From: nanli Date: Tue, 5 Mar 2019 18:10:15 -0500 Subject: [PATCH 08/11] Nanoborb support Heatmap --- apps/heatmap/heatmap.html | 6 +++++- apps/heatmap/init.js | 40 ++++++++++++++++++++++++++++---------- apps/viewer/init.js | 28 +++++++++++++------------- apps/viewer/uicallbacks.js | 40 +++++++++++++++++++++++++++++++++++++- 4 files changed, 88 insertions(+), 26 deletions(-) diff --git a/apps/heatmap/heatmap.html b/apps/heatmap/heatmap.html index 90435c61d..a96ea7f59 100644 --- a/apps/heatmap/heatmap.html +++ b/apps/heatmap/heatmap.html @@ -72,6 +72,8 @@ + + @@ -125,7 +127,7 @@ - + @@ -169,9 +171,11 @@ // normal initialization starts document.addEventListener('DOMContentLoaded', initialize); } + else if(!$D.params.execId){ redirect($D.pages.table,'execId is undefined. Redirecting to Table.'); } + else if ($D.params && ($D.params.slide || $D.params.specimen ||$D.params.study || $D.params.location)){ let STORE = new Store() STORE.findSlide($D.params.slide, $D.params.study, $D.params.specimen, $D.params.location).then(x=>{ diff --git a/apps/heatmap/init.js b/apps/heatmap/init.js index 4bcbb6fe4..c7a4aa0e4 100644 --- a/apps/heatmap/init.js +++ b/apps/heatmap/init.js @@ -15,17 +15,18 @@ const $D = { templates:null // json schema for prue-form }; - // initialize viewer page function initialize(){ - - // init UI -- some of them need to wait data loader to load data - // because UI components need data to initialize - initUIcomponents(); - - // create a viewer and set up - initCore(); - + var checkPackageIsReady = setInterval(function () { + if(IsPackageLoading) { + clearInterval(checkPackageIsReady); + // init UI -- some of them need to wait data loader to load data + // because UI components need data to initialize + initUIcomponents(); + // create a viewer and set up + initCore(); + } + }, 100); // loading the form template data //FormTempaltesLoader(); @@ -203,8 +204,8 @@ function initCore(){ }); $UI.settingsSideMenu.addContent($UI.heatmapcontrol.elt); - Loading.close(); + } }, 500); }); @@ -324,6 +325,25 @@ function initUIcomponents(){ value:'dbviewers', type:'check', callback:toggleViewerMode + },{ + icon: 'insert_photo', + type: 'btn', + value: 'viewer', + title: 'Viewer', + callback: function () { + if (window.location.search.length > 0) { + window.location.href = '../viewer/viewer.html' + window.location.search; + } else { + window.location.href = '../viewer/viewer.html'; + } + } + },{ + name:'bugs', + icon: 'bug_report', + title: 'Bug Report', + value: 'bugs', + type: 'btn', + callback: ()=>{window.open('https://goo.gl/forms/mgyhx4ADH0UuEQJ53','_blank').focus()} } ] diff --git a/apps/viewer/init.js b/apps/viewer/init.js index d0513ac2a..01beaed22 100644 --- a/apps/viewer/init.js +++ b/apps/viewer/init.js @@ -293,20 +293,20 @@ function initUIcomponents(){ type:'btn', callback:openHeatmap }); - subToolsOpt.push({ - name:'segment', - icon: 'timeline', - type: 'check', - value: 'rect', - title: 'Segment', - callback: function () { - if(window.location.search.length > 0) { - window.location.href = '../segment/segment.html' + window.location.search; - }else{ - window.location.href = '../segment/segment.html'; - } - } - }); + // subToolsOpt.push({ + // name:'segment', + // icon: 'timeline', + // type: 'btn', + // value: 'rect', + // title: 'Segment', + // callback: function () { + // if(window.location.search.length > 0) { + // window.location.href = '../segment/segment.html' + window.location.search; + // }else{ + // window.location.href = '../segment/segment.html'; + // } + // } + // }); // -- For Nano borb Start -- // if(ImgloaderMode =='imgbox'){ diff --git a/apps/viewer/uicallbacks.js b/apps/viewer/uicallbacks.js index f1e408350..6de3c88e4 100644 --- a/apps/viewer/uicallbacks.js +++ b/apps/viewer/uicallbacks.js @@ -792,6 +792,8 @@ function stopDrawing(e){ } } + + function openHeatmap(){ switch (ImgloaderMode) { @@ -840,8 +842,44 @@ function hostedHeatmap(){ } function imgboxHeatmap(){ - alert('coming soon ... :)'); + let slide = $D.params.id + slide = decodeURIComponent(slide) + // create file input + var element = document.createElement('input'); + element.setAttribute('type', "file") + element.style.display = 'none'; + document.body.appendChild(element); + + + element.onchange = function(event) { + var input = event.target; + var reader = new FileReader(); + reader.onload = function() { + var text = reader.result; + try { + let data = JSON.parse(text); + + var valid = $VALIDATION.heatmap(data); + if (!valid) { + alert($VALIDATION.heatmap.errors) + return; + }; + + data.provenance.image.slide = slide + const execId = data.provenance.analysis.execution_id; + $CAMIC.store.addHeatmap(data).then(rs=>{ + window.location.href = `../heatmap/heatmap.html${window.location.search}&execId=${execId}`; + }); + } catch (e) { + console.error(e) + } + }; + reader.readAsText(input.files[0]); + } + element.click(); + document.body.removeChild(element); } + function createHeatMapList(list){ empty($UI.modalbox.body); list.forEach(data=>{ From 267c6240ab86a210deeae6fb08f514fdfaef2bd9 Mon Sep 17 00:00:00 2001 From: nanli Date: Thu, 7 Mar 2019 10:57:43 -0500 Subject: [PATCH 09/11] QUIP544 - camic table should be able to take in search parameters --- apps/table.html | 353 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 275 insertions(+), 78 deletions(-) diff --git a/apps/table.html b/apps/table.html index 5d8d40ad5..1c9f1bb9a 100644 --- a/apps/table.html +++ b/apps/table.html @@ -5,40 +5,213 @@ - + - - + + - - - Camic Data Table - + + + + + CaMicroscope Data Table +
@@ -47,60 +220,65 @@
+ - + function eq(v1, v2){ + return v1 == v2; + } + + function getValues(d, keys){ + const rs = []; + keys.forEach( key=>{ + rs.push(d[key]); + }); + return rs; + } + document.addEventListener('DOMContentLoaded', initialize); + + \ No newline at end of file From c2dbed8bb378731e7688ec4f517f332b5f64e62e Mon Sep 17 00:00:00 2001 From: nanli Date: Fri, 8 Mar 2019 12:10:18 -0500 Subject: [PATCH 10/11] add an `Open` btn to open viewer --- apps/table.html | 51 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/apps/table.html b/apps/table.html index 1c9f1bb9a..1b68c2cdd 100644 --- a/apps/table.html +++ b/apps/table.html @@ -211,6 +211,36 @@ content: " "; display: table; } + .btn{ + color: #fff; + background-color: #365f9c; + border-color: #365f9c; + display: inline-block; + /*font-weight: 400;*/ + /*line-height: 1.25;*/ + text-align: center; + white-space: nowrap; + vertical-align: middle; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border: 1px solid transparent; + /*padding: .5rem 1rem;*/ + font-size: 1rem; + text-decoration: none; + border-radius: .25rem; + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; + opacity: 0.8; + } + .btn:hover { + color: #fff; + background-color: #365f9c; + border-color: #365f9c; + opacity: 1; + @@ -263,6 +293,8 @@ else if(!d[key]) rs.push('') else rs.push(d[key]) }); + const btn = `` + rs.push(btn); return rs; }); }) @@ -272,18 +304,15 @@ div.textContent = `No Data Found ... x _ x`; return; } + const head = HeadMapping.map(d=>d.title); + head.push(""); const obj = { - headings: HeadMapping.map(d=>d.title), + headings:head , data:data }; dataTableInstance = new DataTable("#datatables",{ perPage:50, perPageSelect:[25,50,100], - columns:[ - {select: 0, render: function(data){ - return `${data}`; - }}, - ], data:obj }); }); @@ -306,6 +335,16 @@ }); return rs; } + + function openView(e){ + const oid = e.dataset.id; + if(oid){ + window.location.href = `./viewer/viewer.html?slideId=${oid}`; + }else{ + alert('No Data Id'); + } + } + document.addEventListener('DOMContentLoaded', initialize); \ No newline at end of file From bb734b9d91dbcdac000e5e1444e2f2aace018f67 Mon Sep 17 00:00:00 2001 From: nanli Date: Fri, 8 Mar 2019 12:13:52 -0500 Subject: [PATCH 11/11] missing `}` on `.btn` css. --- apps/table.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/table.html b/apps/table.html index 1b68c2cdd..8f5807434 100644 --- a/apps/table.html +++ b/apps/table.html @@ -240,7 +240,7 @@ background-color: #365f9c; border-color: #365f9c; opacity: 1; - + }