//dichiarazione interfacce e variabili globali interface coordinates{ xp: number; yp: number; } var a: number = 3.36275; //costante moltiplicativa per la calibrazione var b: number = 58.2353; //costante additiva per la calibrazione var pixelDim: number; //dimensione dei pixel responsive var maxAbsolute: number; //massimo conteggio della matrice nOfCounts var globalxMinRange: number = 0, globalxMaxRange: number = 55; var xDim: number = 0, yDim: number = 0; //numero di pixel nelle due dimensioni var DataMatrix: number[][][], nOfCounts: number[][]; //matrici con i dati var rePrint: boolean = false; //variabile per ricolorare con il max relativo var newOrigin: coordinates; //nuovo origine nel caso di zoom var zPixel1: coordinates = {xp: 0, yp: 0}; //pixel1 dello zoom var zPixel2: coordinates = {xp: 0, yp: 0}; //pixel2 dello zoom var dataCompleteChart: string = "Channel,Counts\n"; var dataCompleteChartCalibrated: string = "Energy,Counts\n"; var calibrated: boolean = false; //variabile per il controllo sulla calibrazione //INIZIO DELLO SCRIPT $(document).ready( function() { //creazione dell'albero e gestione barre laterali setImportFile(); compressingSidenavSettings(); compressingSidenavFS(); //abilitazione drag&drop var droppableArea: any = document.querySelector('.droppable'); makeDroppable(droppableArea, callback); login(); }); //funzione che definisce tutti gli elementi responsabili dell'apertura di un file. //Sono definiti quindi l'albero e il bottone per l'importazione da locale function setImportFile(){ //Leggo il contenuto del file json e ne eseguo il parse var contentfilesystem: any = document.getElementById('contentfilesystem').innerHTML; var jsonObject: any = JSON.parse(contentfilesystem); alert(jsonObject[0].name); //ora genero l'albero e definisco l'evento in caso di selezione di un nodo // $('#FileTreeview').treeview({data: generateTree(xmlDoc)}); // $('#FileTreeview').on('nodeSelected', function(e, node){ // if(node['url'] != undefined){ // openFileFromServer(node['url']); // } // }); //bottone per l'importazione locale var fileInputButton: any = document.getElementById('myImport'); fileInputButton.onchange = function(){ var fileName: string = fileInputButton.files[0]; var readerObject: any = new FileReader(); readerObject.readAsBinaryString(fileName); readerObject.onload = function() { var fileString: string = readerObject.result; readData(fileString); } } } //funzione che genera automaticamente l'albero function generateTree(xmlDoc){ var tree: any = []; var first: boolean = true; var oldFolderParent: string = ""; var oldFolder: string = ""; //inizio leggendo tutti gli elementi da inserire nell'albero (caratterizzati //dall'avere un url di riferimento) var entry: string[] = xmlDoc.getElementsByTagName("d:href"); //per ogni elemento controllo se si tratta di una cartella o di un documento for (var i:number = 0; i < entry.length; i++) { var path: string[] = entry[i].childNodes[0].nodeValue.split(""); //cartella, creo l'oggetto corrsipondente if (path[path.length-1] == "/") { var folderName: string[] = entry[i].childNodes[0].nodeValue.split("/"); var Folder = { text: folderName[folderName.length-2], nodes: [] } //posiziono la radice del file system, ne memorizzo il path e il padre if (first) { tree.push(Folder); first=false; oldFolder = entry[i].childNodes[0].nodeValue; oldFolderParent = oldFolder.slice(0, oldFolder.lastIndexOf(folderName[folderName.length-2])); //per ogni cartella determino la relazione con la cartella precedente } else { var newFolder: string = entry[i].childNodes[0].nodeValue; var newFolderParent: string = newFolder.slice(0, newFolder.lastIndexOf(folderName[folderName.length-2])); //cartella sorella con quella memorizzata if(newFolderParent == oldFolderParent){ oldFolder = newFolder; insertOBJinFS(Folder, tree, folderName, 0); //cartella figlia di quella memorizzata } else if(newFolderParent == oldFolder){ oldFolder = newFolder; oldFolderParent = newFolderParent; insertOBJinFS(Folder, tree, folderName, 0); //nessuno dei casi precedenti } else { //arretro nell'albero fino a trovare lo stesso padre. Per fare questo //tolgo al padre memorizzato in precedenza prima "/" poi il nome dell' //ultima cartella while(newFolderParent != oldFolderParent){ oldFolderParent = oldFolderParent.slice(0, oldFolderParent.length-1); oldFolderParent = oldFolderParent.slice(0, (oldFolderParent.lastIndexOf("/")+1)); } oldFolder = newFolder; insertOBJinFS(Folder, tree, folderName, 0); } } //documento, creo l'oggetto corrispondente e lo inserisco nell'albero } else { var fileName: string[] = entry[i].childNodes[0].nodeValue.split("/"); var filePath: string = "https://oc-chnet.cr.cnaf.infn.it:8443" + entry[i].childNodes[0].nodeValue; var File = { text: fileName[fileName.length-1], icon: "glyphicon glyphicon-file", selectedIcon: "glyphicon glyphicon-file", url: filePath } insertOBJinFS(File, tree, fileName, 1); } } return tree; } //funzione che posiziona l'oggetto passato in input nell'albero function insertOBJinFS(objfs, tree, objfsName, type){ //determino la profondità dell'oggetto (se è un file devo aggiungere 1 a causa si "/") var depth: number = objfsName.length; if(type) depth++; //in base alla profondità determino a quale oggetto agganciare quello in input var treePosition: any; switch(depth){ case 8: treePosition = tree; break; case 9: treePosition = tree[tree.length-1].nodes; break; case 10: treePosition = tree[tree.length-1].nodes[tree[tree.length-1].nodes.length-1].nodes; break; case 11: treePosition = tree[tree.length-1].nodes[tree[tree.length-1].nodes.length-1].nodes[tree[tree.length-1].nodes[tree[tree.length-1].nodes.length-1].nodes.length-1].nodes; break; case 12: treePosition = tree[tree.length-1].nodes[tree[tree.length-1].nodes.length-1].nodes[tree[tree.length-1].nodes[tree[tree.length-1].nodes.length-1].nodes.length-1].nodes[tree[tree.length-1].nodes[tree[tree.length-1].nodes.length-1].nodes[tree[tree.length-1].nodes[tree[tree.length-1].nodes.length-1].nodes.length-1].nodes.length-1].nodes; break; default: break; } treePosition[treePosition.length-1].nodes.push(objfs); } //funzione che dato l'url di un file, lo apre e lo legge passandone il contenuto //alla funzione readData(). Questa funzione è invocata quando viene selezionato //un file dall'albero function openFileFromServer(url){ var fileName: string[] = url.split("/"); console.log("Try to open " + fileName[fileName.length-1] + " ..."); var txtFile: any = new XMLHttpRequest(); txtFile.open("GET", url, true); txtFile.onreadystatechange = function(){ if(txtFile.readyState === 4){ if(txtFile.status === 200){ if(url != "oc-chnet.cr.cnaf.infn.it:8443/owncloud/remote.php/webdav/Documents/log.txt" ){ readData((txtFile.responseText)); } } } } txtFile.send(null); } //funzione per la compressione della sidenav dx function compressingSidenavSettings(){ var setLabel: any = $('.btn-settings'); var isClosedSettings: boolean = false; setLabel.click(function () { setLabel_cross(); }); function setLabel_cross() { if (isClosedSettings == true) { isClosedSettings = false; $('#mySidenavSet').css('width', "0"); $('#wrapper').css('marginRight', "0"); $('#setbtn').css('marginRight', "-2px"); } else { isClosedSettings = true; $('#mySidenavSet').css('width', "250px"); $('#wrapper').css('marginRight', "250px"); $('#setbtn').css('marginRight', "248px"); } } } //funzione per la compressione della sidenav sx function compressingSidenavFS(){ var fsLabel: any = $('.fs-label'); var isClosedfs: boolean = false; fsLabel.click(function () { fsLabel_cross(); }); function fsLabel_cross() { if (isClosedfs == true) { isClosedfs = false; fsLabel.removeClass('is-open'); fsLabel.addClass('is-closed'); $('#mySidenavfs').css('width', "0"); $('#wrapper').css('marginLeft', "0"); $('#fsbtn').css('marginLeft', "-2px"); } else { isClosedfs = true; fsLabel.removeClass('is-closed'); fsLabel.addClass('is-open'); $('#mySidenavfs').css('width', "250px"); $('#wrapper').css('marginLeft', "250px"); $('#fsbtn').css('marginLeft', "248px"); } } } //funzione che definisce l'area su cui si può eseguire il drag&drop function makeDroppable(droppableArea, callback) { //creo l'elemento "input type file" non visibile e lo aggiungo a "droppableArea" var input: any = document.createElement('input'); input.setAttribute('type', 'file'); input.setAttribute('multiple', true); input.style.display = 'none'; droppableArea.appendChild(input); //questo evento è chiamato quando i file sono trascinati ma non ancora lasciati droppableArea.addEventListener('dragover', function(e) { e.preventDefault(); //impediamo l'apertura del file e.stopPropagation(); e.dataTransfer.dropEffect = 'copy'; droppableArea.classList.add('dragover'); }); //l'evento è chiamato quando un file lascia la zona predefinita per il drag&drop droppableArea.addEventListener('dragleave', function(e) { e.preventDefault(); e.stopPropagation(); droppableArea.classList.remove('dragover'); }); //questo evento si innesca quando il drop è effettivamente avvenuto droppableArea.addEventListener('drop', function(e) { e.preventDefault(); e.stopPropagation(); droppableArea.classList.remove('dragover'); callback.call(null, e.dataTransfer.files); }); } //funzione chiamata in caso di drag&drop responsabile dell'apertura del file droppato, //della sua lettura e del passaggio del suo contenuto alla funzione readData() function callback(files) { console.log("Try to open " + files[files.length-1].name + " ..."); var readerObject: any = new FileReader(); readerObject.readAsBinaryString(files[files.length-1]); readerObject.onload = function() { var fileString: string = readerObject.result; readData(fileString); } } //la funzione prepara i dati per il grafico completo function setDataForCompleteChart(){ //per ogni pixel sommo i conteggi di tutti i canali rilevati var dataForChart: number[] = new Array(16384); for(var i: number = 0; i < 16384; i++){ dataForChart[i] = 0; } for(var i: number = 0; i < xDim; i++){ for(var j: number = 0; j < yDim; j++){ for(var k: number = 0; k < 16384; k++){ dataForChart[k] += DataMatrix[i][j][k]; } } } //riempio le stringhe con i dati per il grafico for(var i: number = 0; i < 16348; i++){ dataCompleteChart += (i+1) + "," + dataForChart[i] + "\n"; dataCompleteChartCalibrated+=round3(((i+1)*a-b)/1000)+","+dataForChart[i]+"\n"; } } //La funzione riceve in input un vettore di cui somma gli elementi compresi tra //gli indici from e to function sumVect(vect: number[], from: number, to: number){ var sum: number = 0; for(var i: number = from; i < to; i++){ sum += vect[i]; } return sum; } //La funzione riceve in input la matrice e gli estremi della sottomatrice di cui //calcola il massimo function findMax(matrix: number[][], pixel1: coordinates, pixel2:coordinates){ var max: number = 0; for(var i: number = pixel1.xp; i <= pixel2.xp; i++){ for(var j: number = pixel1.yp; j <= pixel2.yp; j++){ if(matrix[i][j] > max){ max = matrix[i][j]; } } } return max; } //Funzione per arrotondare il numero in input alla terza cifra decimale function round3(val: number){ return (Math.round(val*Math.pow(10,3))/Math.pow(10,3)); } //la funzione findPosition definisce la posizione del cursore del mouse //relativa al canvas nel momento in cui avviene l'evento passato in input function findPosition(event: any, pixel: coordinates){ var scrollTOP: number = (document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop; var scrollLEFT: number = (document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft; var allX: number = event.clientX+scrollLEFT; var allY: number = event.clientY+scrollTOP; var elParent: any = document.getElementById('myCanvas'); var objX: number = 0, objY: number = 0; while (elParent){ objX += elParent.offsetLeft; objY += elParent.offsetTop; elParent = elParent.offsetParent; } pixel.xp = Math.floor((allX-objX - 1) / pixelDim ) + newOrigin.xp; pixel.yp = Math.floor((allY-objY - 1) / pixelDim ) + newOrigin.yp; } //la funzione findPosDown memorizza la posizione del pixel cliccato function findPosDown(event: any){ findPosition(event, zPixel1); } //la funzione findPosUp memorizza la posizione del pixel quando il mouse viene //rilasciato, ordina le coordinate, aggiorna l'origine e la pagina. function findPosUp(event: any){ findPosition(event, zPixel2); var tmp: number; if (zPixel1.xp > zPixel2.xp) { tmp = zPixel1.xp; zPixel1.xp = zPixel2.xp; zPixel2.xp = tmp; } if (zPixel1.yp > zPixel2.yp) { tmp = zPixel1.yp; zPixel1.yp = zPixel2.yp; zPixel2.yp = tmp; } //se è stato cliccato un punto disegno il grafico, altrimenti disegno anche il //canvas e aggiorno l'origine if (zPixel1.xp != zPixel2.xp || zPixel1.yp != zPixel2.yp){ newOrigin = {xp: zPixel1.xp, yp:zPixel1.yp}; drawImg(zPixel1, zPixel2, globalxMinRange, globalxMaxRange); } drawChart(zPixel1, zPixel2, globalxMinRange, globalxMaxRange); } // La funzione readData() prende in ingresso il file di input memorizzato nella // stringa "fileString". La funzione riempie la matrice "DataMatrix" con i dati // in modo che essi siano memorizzati in un formato più leggibile. Sono ricavate // anche altre variabili necessarie per il resto del codice. function readData(fileString){ newOrigin = {xp: 0, yp: 0}; //origine nel caso di zoom var passo: number = 0; //dimensione di un pixel in micorn var readMode: string; //direzione di lettura //coordinate minime e massime in entrambe le dimensioni var xMin: number = 0, yMin: number = 0, xMax: number = 0, yMax: number = 0; //array con il contenuto del file di input suddiviso per righe var fileStringArray: any = fileString.split("\n"); //scorro l'array soffermandomi solo sulle righe "intestazione delle x". Devo //determinare ascisse e cordinate minime e massime, il passo e la direzione di //scansione for(var i: number = 0; i < fileStringArray.length; i++){ if(parseInt(fileStringArray[i]) > 17000 && fileStringArray[i][0] =='5'){ if(xMin == 0){ //se sono alla prima intestazione salvo la x e la y xMin = parseInt(fileStringArray[i]); yMin = parseInt(fileStringArray[i+1]); i++; } else { //definisco passo e direzione di scansione dalla seconda intestazione if(parseInt(fileStringArray[i]) == xMin){ readMode = 'c'; passo = Math.abs(yMin - fileStringArray[i+1]); //se sto leggendo per colonne determino xMax leggendo dalla fine for(var j: number = fileStringArray.length; j > i; j--){ //se la riga è "intestazione x" memorizzo xMax e lo confronto con xMin if(parseInt(fileStringArray[j]) > 17000 && fileStringArray[j][0] =='5'){ xMax = parseInt(fileStringArray[j]); if(xMax < xMin){ var t: number = xMax; xMax = xMin; xMin = t; } break; } } } else { readMode = 'r'; passo = Math.abs(xMin - fileStringArray[i]); //se sto leggendo per righe determino yMax leggendo dalla fine for(var j: number = fileStringArray.length; j > i; j--){ //se la riga è "intestazione y" memorizzo yMax e lo confronto con yMin if(parseInt(fileStringArray[j]) > 17000 && fileStringArray[j][0] =='6'){ yMax = parseInt(fileStringArray[j]); if(yMax < yMin){ var t: number = yMax; yMax = yMin; yMin = t; } break; } } } break; } } } //alert(xMin + " " + xMax + " " + yMin + " " + yMax + " " + passo); //A seconda della direzione di lettura determino o yMin e yMax, o xMin e xMax for(var i: number = 2; i < fileStringArray.length; i++){ if(readMode == 'c'){ //se leggo per colonne devo deterinare yMin e yMax //mi soffermo sulle righe "intestazione y" if (parseInt(fileStringArray[i]) > 17000 && fileStringArray[i][0] == '6') { if (yMin > parseInt(fileStringArray[i])){ yMin = parseInt(fileStringArray[i]); } if(yMax < parseInt(fileStringArray[i])){ yMax = parseInt(fileStringArray[i]); } } //alla terza colonna posso uscire perché ho già tutte le informazioni if (parseInt(fileStringArray[i]) == xMin + (passo * 2)) { break; } } else { //se leggo per righe devo deterinare xMin e xMax //mi soffermo sulle righe "intestazione x" if (parseInt(fileStringArray[i]) > 17000 && fileStringArray[i][0] == '5') { if (xMin > parseInt(fileStringArray[i])){ xMin = parseInt(fileStringArray[i]); } if(xMax < parseInt(fileStringArray[i])){ xMax = parseInt(fileStringArray[i]); } } //alla terza colonna posso uscire perché ho già tutte le informazioni if (parseInt(fileStringArray[i]) == yMin + 2000) { break; } } } //alert(xMin + " " + xMax + " " + yMin + " " + yMax + " " + passo); //Risolvo gli shift for(var i: number = 0; i < fileStringArray.length; i++){ //se leggo per colonne allora aggiungo 1 alle y di tutte le colonne dispari if(readMode == 'c' && parseInt(fileStringArray[i]) > 17000 && fileStringArray[i][0]=='5' && (parseInt(fileStringArray[i])/1000)%2 != 0){ fileStringArray[i+1] = (parseInt(fileStringArray[i+1]) + passo).toString(); } //se leggo per righe allora aggiungo 1 alle x di tutte le righe dispari else if(readMode == 'r' && parseInt(fileStringArray[i]) > 17000 && fileStringArray[i][0]=='5' && (parseInt(fileStringArray[i+1])/1000)%2 != 0){ fileStringArray[i] = (parseInt(fileStringArray[i]) + passo).toString(); } } //Definisco le dimensioni della matrice DataMatrix e la inizializzo if(readMode == 'c'){ xDim = (xMax - xMin)/passo + 1; yDim = (yMax - yMin)/passo - 2; } else { xDim = (xMax - xMin)/passo - 2; yDim = (yMax - yMin)/passo + 1; } //alert(xDim + " " + yDim); DataMatrix = new Array(xDim); for(var i: number = 0; i < xDim; i++){ DataMatrix[i] = new Array(yDim); for(var j: number = 0; j < yDim; j++){ DataMatrix[i][j] = new Array(16384); for(var k: number = 0; k < 16384; k++){ DataMatrix[i][j][k] = 0; } } } //riempio la matrice DataMatrix eliminando i bordi for(var i: number = 0; i < fileStringArray.length; i++){ var x: number, y: number, write: boolean; //riga "intestazione x": memorizzo le x e le y del punto e avanzo al conteggio if(parseInt(fileStringArray[i]) > 17000 && fileStringArray[i][0] == '5'){ x = (parseInt(fileStringArray[i]) - xMin); y = (parseInt(fileStringArray[i+1]) - yMin); if(x != 0){ x /= passo; } if(y != 0){ y /= passo; } i++; //non è un pixel del bordo e sto leggendo per colonne: i successivi valori //sono da considerare if(readMode == 'c' && y != 0 && y != 1 && y != (yMax - yMin)/passo && y != (yMax - yMin)/passo + 1){ write = true; y -= 2; //aggiorno la y con i bordi tagliati } //non è un pixel del bordo e sto leggendo per righe: i successivi valori //sono da considerare else if(readMode == 'r' && x != 0 && x != 1 && x != (xMax - xMin)/passo && x != (xMax - xMin)/passo + 1){ write = true; x -= 2; //aggiorno la x con i bordi tagliati } //pixel del bordo: i valori successivi sono da ignorare else{ write = false; } //conteggio da considerare (non del bordo) } else if (parseInt(fileStringArray[i]) < 17000 && write == true){ //inserisco il conteggio nella matrice (occhio all'orientamento) DataMatrix[xDim-x-1][yDim-y-1][parseInt(fileStringArray[i])] += 1; } } //calcolo il numero di conteggi per pixel e li salvo nella matrice nOfCounts nOfCounts = new Array(xDim); for(var i: number = 0; i < xDim; i++){ nOfCounts[i] = new Array(yDim); for(var j: number = 0; j < yDim; j++){ nOfCounts[i][j] = sumVect(DataMatrix[i][j], 0, DataMatrix[i][j].length); } } //calcolo il conteggio massimo della matrice maxAbsolute = findMax(nOfCounts, {xp: 0, yp: 0}, {xp: xDim-1, yp: yDim-1}); //definisco i dati per il grafico completo setDataForCompleteChart(); console.log("File open with succes"); drawImg({xp: 0, yp: 0}, {xp: xDim - 1, yp: yDim - 1}, 0, 55); drawChart({xp: 0, yp: 0}, {xp: xDim - 1, yp: yDim - 1}, 0, 55); } //la funzione drawImg disegna il canvas con l'immagine desiderata ed è responsabile //della gestione di tutti gli eventi ad essa associati function drawImg(pixel1: coordinates, pixel2:coordinates, xMinRange: number, xMaxRange: number){ //dimensioni pixel var nPixelX: number = pixel2.xp - pixel1.xp + 1; var nPixelY: number = pixel2.yp - pixel1.yp + 1; var mappaPannelDim: any = document.querySelector ('#mappa-pannel').getBoundingClientRect(); var mappaWidth: number = mappaPannelDim.right - mappaPannelDim.left - 20; var mappaHeigth: number = mappaPannelDim.bottom - mappaPannelDim.top - 50; var dimPixelx: number = Math.floor(mappaWidth/nPixelX); var dimPixely: number = Math.floor(mappaHeigth/nPixelY); pixelDim = (dimPixelx < dimPixely) ? dimPixelx : dimPixely; document.getElementById("myCanvas").height = nPixelY * pixelDim; document.getElementById("myCanvas").width = nPixelX * pixelDim; var ctx = document.getElementById('myCanvas').getContext('2d'); //contesto del canvas if(xMaxRange - xMinRange >= 55){ //range completo var max: number; //massimo relativo o assoluto if (rePrint) max = findMax(nOfCounts, pixel1, pixel2); else max = maxAbsolute; max = (max * document.getElementById("SaturationSlider").value)/100 ; //saturazione drawCanvas(nOfCounts, max); //disegno } else { //range parziale (solo alcuni canali) var xMinRangeCh: number = Math.floor((((xMinRange*1000)+b)/a)-1); //16 var xMaxRangeCh: number = Math.floor((((xMaxRange*1000)+b)/a)-1); //16371 //calcolo il numero di conteggi solo dei canali selezionati var nOfCountsRelative: number[][]; nOfCountsRelative = new Array(xDim); for(var i: number = 0; i < xDim; i++){ nOfCountsRelative[i] = new Array(yDim); for(var j: number = 0; j < yDim; j++){ nOfCountsRelative[i][j] = sumVect(DataMatrix[i][j], xMinRangeCh, xMaxRangeCh); } } //calcolo il massimo var max: number; if (rePrint) { max = findMax(nOfCountsRelative, pixel1, pixel2); } else { max = findMax(nOfCountsRelative,{xp:0,yp:0},{xp:xDim-1,yp:yDim-1}); } max = (max * document.getElementById("SaturationSlider").value)/100 ; //saturazione drawCanvas(nOfCountsRelative, max); //disegno } //La funzione, ricevuti dati e massimo, disegna la mappa nel canvas function drawCanvas(noc, max){ //controllo il valore della trasparenza var setTrsp: number = 1-document.getElementById("TrasparencySlider").value/100; //scorro tutti i pixel: ne determino il colore e li disegno var color:string = ""; for (var i: number = pixel1.xp; i <= pixel2.xp; i++) { for (var j: number = pixel1.yp; j <= pixel2.yp; j++) { var intensity: number = noc[i][j] / max; if(intensity < 1/5) //blu color = "rgba(0, 0, "+Math.floor(intensity*5*255)+","+setTrsp+")"; else if (1/5 <= intensity && intensity < 2/5) //blu+verde color="rgba(0, "+Math.floor((intensity-1/5)*5*255)+",255, "+setTrsp+")"; else if (2/5 <= intensity && intensity < 3/5) // verde-blu color="rgba(0, 255, "+(255-Math.floor((intensity-2/5)*5*255))+", "+setTrsp+")"; else if (3/5 <= intensity && intensity < 4/5) //verde + rosso color="rgba("+Math.floor((intensity-3/5)*5*255)+",255,0,"+setTrsp+")"; else //rosso -verde color="rgba(255,"+(255-Math.floor((intensity-4/5)*5*255))+", 0, "+setTrsp+")"; ctx.fillStyle = color; ctx.fillRect((i - pixel1.xp) * pixelDim, (j - pixel1.yp) * pixelDim, pixelDim, pixelDim); } } rePrint = false; //annullo rePrint } $("#SaturationSlider").mouseup(function(){ //Slider della saturazione drawImg(pixel1, pixel2, xMinRange, xMaxRange); }); $("#rePlot").click(function(){ //bottone per colorare con il max relativo rePrint = true; document.getElementById("SaturationSlider").value = "100"; drawImg(pixel1, pixel2, xMinRange, xMaxRange); }); $("#TrasparencySlider").mouseup(function(){ //Slider della trasparenza drawImg(pixel1, pixel2, xMinRange, xMaxRange); }); $("#reset").click(function(){ //bottone per il reset dell'applicazione newOrigin = {xp: 0, yp: 0}; rePrint = false; calibrated = false; globalxMinRange = 0; globalxMaxRange = 55; document.getElementById("SaturationSlider").value = "100"; document.getElementById("TrasparencySlider").value = "0"; document.getElementById("spinBoxMin").setAttribute("value", "-"); document.getElementById("spinBoxMax").setAttribute("value", "-"); drawImg({xp: 0, yp: 0}, {xp: xDim - 1, yp: yDim - 1}, 0, 55); drawChart({xp: 0, yp: 0}, {xp: xDim - 1, yp: yDim - 1}, 0, 55); }); $("#ExportImage").click(function(){ //esportazione immagine var img = document.getElementById("myCanvas").toDataURL("image/png"); $("#ExportImage").attr("href", img); //document.write('<img src="'+img+'"/>'); }); } //la funzione drawChart (input: estremi dell'immagine, estremi dell'intervallo) //disegna il grafico richiesto relativo alla mappa visualizzata function drawChart(pixel1: coordinates, pixel2:coordinates, xMinRange: number, xMaxRange: number){ //definisco la variabile "grafico", i bottoni relativi al grafico, il tag //select e le due spinbox con il relativo botton var g: any; var box1 = <HTMLElement>document.getElementById("spinBoxMin"); var box2 = <HTMLElement>document.getElementById("spinBoxMax"); //disegno il grafico completo if(pixel1.xp == 0 && pixel1.yp == 0 && pixel2.xp == xDim-1 && pixel2.yp == yDim-1){ if(!calibrated){ //canali var chartTitle: string = "Chart from (0, 0) to ("+(xDim-1)+", "+(yDim-1)+")"; g = setChart(dataCompleteChart, chartTitle); } else { //energie var chartTitle: string = "Calibrated chart from (0, 0) to ("+(xDim-1)+", "+(yDim-1)+")"; g = setChart(dataCompleteChartCalibrated, chartTitle); } //disegno il grafico parzialmente } else { //determino i conteggi dei pixel da disegnare var dataForChart: number[] = new Array(16384); for(var i: number = 0; i < 16384; i++){ dataForChart[i] = 0; } for(var i: number = pixel1.xp; i <= pixel2.xp; i++){ for(var j: number = pixel1.yp; j <= pixel2.yp; j++){ for(var k: number = 0; k < 16384; k++){ dataForChart[k] += DataMatrix[i][j][k]; } } } if(!calibrated){ //disegno in canali var dataChart: string = "Channel,Counts\n"; for(var i: number = 0; i < 16348; i++){ dataChart += i + "," + dataForChart[i] + "\n"; } if(pixel1.xp == pixel2.xp && pixel1.yp == pixel2.yp){ var chartTitle: string = "Chart pixel (" + pixel1.xp + ", " + (yDim - pixel1.yp - 1) + ")"; } else { var chartTitle: string = "Chart from (" + pixel1.xp + "," + pixel2.xp + ") to (" + (yDim - pixel1.yp - 1) + ", " + (yDim - pixel2.yp - 1) + ")"; } g = setChart(dataChart, chartTitle); } else { //disegno in energie var dataChartCalibrated: string = "Energy,Counts\n"; for(var i: number = 0; i < 16348; i++){ dataChartCalibrated += round3(((i+1)*a-b)/1000) + "," + dataForChart[i] + "\n"; } if(pixel1.xp == pixel2.xp && pixel1.yp == pixel2.yp){ var chartTitle: string = "Calibrated chart pixel ("+pixel1.xp+", "+(yDim-pixel1.yp-1)+")"; } else { var chartTitle: string = "Calibrated chart from (" + pixel1.xp + ", " + pixel2.xp + ") to ("+ (yDim - pixel1.yp - 1) + ", " + (yDim - pixel2.yp - 1) + ")"; } g = setChart(dataChartCalibrated, chartTitle); } } $('#setlinearButton').on('click', function() { //selezione scala lineare g.updateOptions( {logscale: false} ); }); $('#setlogButton').on('click', function() { //selezione scala logaritmica g.updateOptions( {logscale: true} ); }); $('#setEnergyButton').on('click', function() { //selezione energie calibrated = true; drawChart(pixel1, pixel2, 0, 55); box1.setAttribute("value", "0"); box2.setAttribute("value", "55"); }); $('#setChannelsButton').on('click', function() { //selezione canali calibrated = false; drawChart(pixel1, pixel2, 0, 55); box1.setAttribute("value", "-"); box2.setAttribute("value", "-"); }); $('#ExportGraph').on('click', function() { //esportazione grafico var img = document.getElementById("chartToImg"); Dygraph.Export.asPNG(g, img); document.getElementById("ExportGraph").href = img.src.replace('image/png','image/octet-stream'); }); $('#readSpinbox').on('click', function() { //esportazione grafico peackSelection(0, 0); }); $('#chart').on('click', function() { //zoom manuale sul grafico var r: number[]; r = g.xAxisRange(); if(!calibrated){ r[0] = Math.floor((((r[0] + 1) * a) - b) / 1000); r[1] = Math.floor((((r[1] + 1) * a) - b) / 1000); } else { r[0] = round3(r[0]); r[1] = round3(r[1]); box1.setAttribute("value", r[0].toString()); box2.setAttribute("value", r[1].toString()); } globalxMinRange = r[0]; globalxMaxRange = r[1]; drawImg(pixel1, pixel2, r[0], r[1]); }); $('#elementSelect').on('change', function() { //selezione elemento var element: string = document.getElementById("elementSelect").value; switch(element){ case "1": //Ca peackSelection(3.6, 3.8); box1.setAttribute("value", "3.60"); box2.setAttribute("value", "3.80"); break; case "2": //Pb peackSelection(10.4, 10.7); box1.setAttribute("value", "10.40"); box2.setAttribute("value", "10.70"); break; case "3": //Hg peackSelection(9.8, 10.15); box1.setAttribute("value", "9.80"); box2.setAttribute("value", "10.15"); break; case "4": //Fe peackSelection(6.3, 6.5); box1.setAttribute("value", "6.30"); box2.setAttribute("value", "6.50"); break; case "5": //Cu peackSelection(7.85, 8.2); box1.setAttribute("value", "7.85"); box2.setAttribute("value", "8.20"); break; case "6": //Zn peackSelection(8.5, 8.72); box1.setAttribute("value", "8.50"); box2.setAttribute("value", "8.72"); break; case "7": //Ti peackSelection(4.35, 4.65); box1.setAttribute("value", "4.35"); box2.setAttribute("value", "4.65"); break; case "8": //K peackSelection(3.2, 3.42); box1.setAttribute("value", "3.20"); box2.setAttribute("value", "3.42"); break; case "9": //Co peackSelection(6.8, 7.05); box1.setAttribute("value", "6.80"); box2.setAttribute("value", "7.05"); break; default: peackSelection(0, 55); box1.setAttribute("value", "0"); box2.setAttribute("value", "55"); break; } }); //la funzione setChart riceve in input i dati e il titolo del grafico da disegnare //il quale è restituito il output function setChart(dataString: string, charTitle: string){ var xArrayRange: number[]; //estremi asse x da visualizzare var xLab: string; if(!calibrated){ xArrayRange = [0, 16383]; xLab = "ADC Channel"; }else{ xArrayRange = [xMinRange, xMaxRange]; xLab = "Energy (keV)"; } //dimensioni grafico var chartDim: any = document.querySelector('#chart-pannel').getBoundingClientRect(); var chartWidth = chartDim.right - chartDim.left - 50; $('#chart').css('width', chartWidth); var chartHeight: number = chartDim.bottom - chartDim.top - 100; $('#chart').css('height', chartHeight); //disegno il grafico var graphs: any = new Dygraph(document.getElementById("chart"), dataString, { title: charTitle, ylabel: 'Counts', xlabel: xLab, //legend: 'always', labelsDivStyles: { 'textAlign': 'right' }, dateWindow: xArrayRange, showRangeSelector: true, logscale: false }); //dimensioni responsive alle sideNav $('#fsbtn').on('click', function() { setTimeout(function(){ g = setChart(dataString, charTitle); drawImg(pixel1, pixel2, xMinRange, xMaxRange); }, 400); }); $('#setbtn').on('click', function() { setTimeout(function(){ g = setChart(dataString, charTitle); drawImg(pixel1, pixel2, xMinRange, xMaxRange); }, 400); }); return graphs; } //la funzione, dati gli estremi dell'intervallo da rappresentare, aggiorna mappa e grafico function peackSelection(xMinRange: number, xMaxRange: number){ //se l'intervallo è [0, 0] devo leggere dalle i valori dalle spinbox if(xMinRange == 0 && xMaxRange == 0){ xMinRange = box1.value; xMaxRange = box2.value; } globalxMinRange = xMinRange; globalxMaxRange = xMaxRange; newOrigin = { xp: 0, yp: 0}; rePrint = false; calibrated = true; drawImg({xp:0, yp:0}, {xp:xDim-1, yp:yDim-1}, globalxMinRange, globalxMaxRange); drawChart({xp:0, yp:0}, {xp:xDim-1, yp:yDim-1}, globalxMinRange, globalxMaxRange); } }