-
Laura Cappelli authoredLaura Cappelli authored
LoadFile.ts 31.97 KiB
//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);
});
//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(){
//genero e leggo il contenuto della directory "filesystem"
var jsonResponse: any;
var xmlListingFile: any = new XMLHttpRequest();
xmlListingFile.open("GET", "https://baltig.infn.it/api/v4/projects/819/repository/tree?recursive=1&path=XRF-File-System", false);
xmlListingFile.onreadystatechange = function(){
if(xmlListingFile.readyState === 4){
if(xmlListingFile.status === 200){
jsonResponse = JSON.parse(xmlListingFile.responseText);
}
}
}
xmlListingFile.send(null);
//ora genero l'albero e definisco l'evento in caso di selezione di un nodo
$('#FileTreeview').treeview({data: generateTree(jsonResponse)});
$('#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(jsonDoc){
var tree: any = [ {
text:"XRF-File-System",
nodes: [ ]
}];
//scorro ogni elemento dell'albero
for (var i: number = 0; i < jsonDoc.length; i++) {
if(jsonDoc[i].type == "tree"){ //è una cartella
var Folder = { //definisco l'oggetto Folder
text: jsonDoc[i].name,
relativePath: jsonDoc[i].path,
nodes: []
}
insertOBJinFS(Folder, 0, tree);
} else { //è un file
var File = { //definisco l'oggetto File
text: jsonDoc[i].name,
relativePath: jsonDoc[i].path,
icon: "glyphicon glyphicon-file",
selectedIcon: "glyphicon glyphicon-file",
url: jsonDoc[i].path
}
//inserisco il file nella giusta posizione
insertOBJinFS(File, 1, tree);
}
}
return tree;
}
//funzione che posiziona l'oggetto passato in input nell'albero
function insertOBJinFS(objfs, type,tree){
tree[0].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){
alert(url);
console.log("Try to open " + url.slice(url.lastIndexOf("/"), url.lastIndexOf("?")+1) + " ...");
url = "https://baltig.infn.it/api/v4/projects/819/repository/files/ " +
encodeURIComponent(url) + "?ref=master";
var txtFile: any = new XMLHttpRequest();
txtFile.open("GET", url, true);
txtFile.onreadystatechange = function(){
if(txtFile.readyState === 4){
if(txtFile.status === 200){
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);
}
}