Skip to content
Snippets Groups Projects
start.js 33.13 KiB
var a = 3.36275; //costante moltiplicativa per la calibrazione
var b = 58.2353; //costante additiva per la calibrazione
var pixelDim; //dimensione dei pixel responsive
var maxAbsolute; //massimo conteggio della matrice nOfCounts
var xDim = 0, yDim = 0; //numero di pixel nelle due dimensioni
var DataMatrix, nOfCounts; //matrici con i dati
var rePrint = false; //variabile per ricolorare con il max relativo
var newOrigin; //nuovo origine nel caso di zoom
var zPixel1; //pixel1 dello zoom
var zPixel2; //pixel2 dello zoom
var dataCompleteChart = "Channel,Counts\n";
var dataCompleteChartCalibrated = "Energy,Counts\n";
var calibrated = false; //variabile per il controllo sulla calibrazione
var depth = 8000; //profondità massima della matrice
var channelDepth = round3(((depth + 1) * a - b) / 1000); //profondità massima in canali
var globalxMinRange = 0, globalxMaxRange = channelDepth;
//INIZIO DELLO SCRIPT
$(document).ready(function () {
    $('[data-toggle="tooltip"]').tooltip();
    //creazione dell'albero e gestione barre laterali
    setImportFile();
    compressingSidenavFS();
    //abilitazione drag&drop
    var droppableArea = document.querySelector('.droppable');
    makeDroppable(droppableArea, callback);
    //inizializzazione variabili
    zPixel1 = { xp: 0, yp: 0 };
    zPixel2 = { xp: 0, yp: 0 };
});
//funzione per la compressione della sidenav sx
function compressingSidenavFS() {
    var fsLabel = $('.fs-label');
    var isClosedfs = 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");
            $('#fsbtn').css('marginLeft', "-2px");
        }
        else {
            isClosedfs = true;
            fsLabel.removeClass('is-closed');
            fsLabel.addClass('is-open');
            $('#mySidenavfs').css('width', "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 = 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) {
    $("#load-spinner").css("display", "inline");
    $("#wrapper").css("opacity", "0.25");
    console.log("Try to open " + files[files.length - 1].name + " ...");
    var readerObject = new FileReader();
    readerObject.readAsBinaryString(files[files.length - 1]);
    readerObject.onload = function () {
        var fileString = 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 = new Array(depth);
    for (var i = 0; i < depth; i++) {
        dataForChart[i] = 0;
    }
    for (var i = 0; i < xDim; i++) {
        for (var j = 0; j < yDim; j++) {
            for (var k = 0; k < depth; k++) {
                dataForChart[k] += DataMatrix[i][j][k];
            }
        }
    }
    //riempio le stringhe con i dati per il grafico
    for (var i = 0; i < depth; 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, from, to) {
    var sum = 0;
    for (var i = 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, pixel1, pixel2) {
    var max = 0;
    for (var i = pixel1.xp; i <= pixel2.xp; i++) {
        for (var j = 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) {
    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, pixel) {
    var scrollTOP = (document.documentElement.scrollTop) ?
        document.documentElement.scrollTop : document.body.scrollTop;
    var scrollLEFT = (document.documentElement.scrollLeft) ?
        document.documentElement.scrollLeft : document.body.scrollLeft;
    var allX = event.clientX + scrollLEFT;
    var allY = event.clientY + scrollTOP;
    var elParent = document.getElementById('myCanvas');
    var objX = 0, objY = 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) {
    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) {
    findPosition(event, zPixel2);
    var tmp;
    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
    //alert(zPixel1.xp + ", " + zPixel1.yp + " - " + zPixel2.xp + ", " + zPixel2.yp);
    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 = 0; //dimensione di un pixel in micorn
    var readMode; //direzione di lettura
    //coordinate minime e massime in entrambe le dimensioni
    var xMin = 0, yMin = 0, xMax = 0, yMax = 0;
    //array con il contenuto del file di input suddiviso per righe
    var fileStringArray = 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 = 0; i < fileStringArray.length; i++) {
        if (parseInt(fileStringArray[i]) > 17000 && fileStringArray[i][0] == '5') {
            if (xMin == 0) {
                xMin = parseInt(fileStringArray[i]);
                yMin = parseInt(fileStringArray[i + 1]);
                i++;
            }
            else {
                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 = 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 = 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 = 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 = 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 = 2; i < fileStringArray.length; i++) {
        if (readMode == 'c') {
            //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 {
            //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 = 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();
        }
        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);
    //determino la profondità del problema: mi soffermo solo sui conteggi e tengo
    //il massimo
    // for(var i: number = 0; i < fileStringArray.length; i++){
    //   if(parseInt(fileStringArray[i]) < 17000){
    //     if(parseInt(fileStringArray[i]) > depth){
    //       depth = parseInt(fileStringArray[i]);
    //     }
    //   }
    // }
    //alert(depth);
    DataMatrix = new Array(xDim);
    for (var i = 0; i < xDim; i++) {
        DataMatrix[i] = new Array(yDim);
        for (var j = 0; j < yDim; j++) {
            DataMatrix[i][j] = new Array(depth);
            for (var k = 0; k < depth; k++) {
                DataMatrix[i][j][k] = 0;
            }
        }
    }
    //riempio la matrice DataMatrix eliminando i bordi
    for (var i = 0; i < fileStringArray.length; i++) {
        var x, y, write;
        //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
            }
            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
            }
            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 = 0; i < xDim; i++) {
        nOfCounts[i] = new Array(yDim);
        for (var j = 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, channelDepth);
    drawChart({ xp: 0, yp: 0 }, { xp: xDim - 1, yp: yDim - 1 }, 0, channelDepth);
    $("#load-spinner").css("display", "none");
    $("#wrapper").css("opacity", "1");
}
//la funzione disegna il rettangolo durante la selezione di un'area della mappa
function zoomRect() {
    var selectCanvas = document.getElementById("selectionCanvas");
    var ctx = selectCanvas.getContext("2d");
    // style the context
    ctx.fillStyle = "rgba(0, 110, 255, 0.25)";
    // this flage is true when the user is dragging the mouse
    var isDown = false;
    // these vars will hold the starting mouse position
    var startX;
    var startY;
    var mouseX;
    var mouseY;
    // these vars will hold the starting mouse position
    function handleMouseDown(e) {
        e.preventDefault();
        e.stopPropagation();
        //calculate mouse position
        var scrollTOP = (document.documentElement.scrollTop) ?
            document.documentElement.scrollTop : document.body.scrollTop;
        var scrollLEFT = (document.documentElement.scrollLeft) ?
            document.documentElement.scrollLeft : document.body.scrollLeft;
        var allX = e.clientX + scrollLEFT;
        var allY = e.clientY + scrollTOP;
        var elParent = document.getElementById('myCanvas');
        var objX = 0, objY = 0;
        while (elParent) {
            objX += elParent.offsetLeft;
            objY += elParent.offsetTop;
            elParent = elParent.offsetParent;
        }
        startX = allX - objX;
        startY = allY - objY;
        // set a flag indicating the drag has begun
        isDown = true;
    }
    function handleMouseUp(e) {
        e.preventDefault();
        e.stopPropagation();
        // the drag is over, clear the dragging flag
        isDown = false;
        ctx.clearRect(0, 0, selectCanvas.width, selectCanvas.height);
    }
    function handleMouseOut(e) {
        e.preventDefault();
        e.stopPropagation();
        // the drag is over, clear the dragging flag
        isDown = false;
        ctx.clearRect(0, 0, selectCanvas.width, selectCanvas.height);
    }
    function handleMouseMove(e) {
        e.preventDefault();
        e.stopPropagation();
        // if we're not dragging, just return
        if (!isDown) {
            return;
        }
        //calculate mouse position
        var scrollTOP = (document.documentElement.scrollTop) ?
            document.documentElement.scrollTop : document.body.scrollTop;
        var scrollLEFT = (document.documentElement.scrollLeft) ?
            document.documentElement.scrollLeft : document.body.scrollLeft;
        var allX = e.clientX + scrollLEFT;
        var allY = e.clientY + scrollTOP;
        var elParent = document.getElementById('myCanvas');
        var objX = 0, objY = 0;
        while (elParent) {
            objX += elParent.offsetLeft;
            objY += elParent.offsetTop;
            elParent = elParent.offsetParent;
        }
        mouseX = allX - objX;
        mouseY = allY - objY;
        // Put your mousemove stuff here
        // clear the canvas
        ctx.clearRect(0, 0, selectCanvas.width, selectCanvas.height);
        // calculate the rectangle width/height based
        // on starting vs current mouse position
        var width = mouseX - startX;
        var height = mouseY - startY;
        // draw a new rect from the start position 
        // to the current mouse position
        ctx.fillRect(startX, startY, width, height);
    }
    // listen for mouse events
    $("#selectionCanvas").mousedown(function (e) { handleMouseDown(e); });
    $("#selectionCanvas").mousemove(function (e) { handleMouseMove(e); });
    $("#selectionCanvas").mouseup(function (e) { handleMouseUp(e); });
    $("#selectionCanvas").mouseout(function (e) { handleMouseOut(e); });
}
//la funzione drawImg disegna il canvas con l'immagine desiderata ed è responsabile
//della gestione di tutti gli eventi ad essa associati
function drawImg(pixel1, pixel2, xMinRange, xMaxRange) {
    //alert("disegno in corso");
    //numero di pixel per dimensione
    var nPixelX = pixel2.xp - pixel1.xp + 1;
    var nPixelY = pixel2.yp - pixel1.yp + 1;
    //dimensione dei canvas
    var mappaPannelDim = document.querySelector('#mappa-pannel').getBoundingClientRect();
    var mappaWidth = mappaPannelDim.right - mappaPannelDim.left - 40;
    var mappaHeigth = 400;
    //dimensione reale dei pixel
    var dimPixelx = Math.floor(mappaWidth / nPixelX);
    var dimPixely = Math.floor(mappaHeigth / nPixelY);
    pixelDim = (dimPixelx < dimPixely) ? dimPixelx : dimPixely;
    //dimensioni esatte dei canvas
    document.getElementById("myCanvas").height = nPixelY * pixelDim;
    document.getElementById("myCanvas").width = nPixelX * pixelDim;
    document.getElementById("selectionCanvas").height = nPixelY * pixelDim;
    document.getElementById("selectionCanvas").width = nPixelX * pixelDim;
    var ctx = document.getElementById('myCanvas').getContext('2d'); //contesto del canvas
    if (xMaxRange - xMinRange >= channelDepth) {
        var max; //massimo relativo o assoluto
        if (rePrint)
            max = findMax(nOfCounts, pixel1, pixel2);
        else
            max = maxAbsolute;
        max = (max * document.getElementById("SaturationSlider").value) / 100;
        //max = (max * parseInt($("#SaturationSlider").attr("value")))/100 ; //saturazione
        drawCanvas(nOfCounts, max); //disegno
    }
    else {
        var xMinRangeCh = Math.floor((((xMinRange * 1000) + b) / a) - 1); //16
        var xMaxRangeCh = Math.floor((((xMaxRange * 1000) + b) / a) - 1); //16371
        //calcolo il numero di conteggi solo dei canali selezionati
        var nOfCountsRelative;
        nOfCountsRelative = new Array(xDim);
        for (var i = 0; i < xDim; i++) {
            nOfCountsRelative[i] = new Array(yDim);
            for (var j = 0; j < yDim; j++) {
                nOfCountsRelative[i][j] = sumVect(DataMatrix[i][j], xMinRangeCh, xMaxRangeCh);
            }
        }
        //calcolo il massimo
        var max;
        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;
        //max = (max * parseInt($("#SaturationSlider").attr("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 = 1 - (document.getElementById("TrasparencySlider").value / 100);
        //var setTrsp: number = 1-(parseInt($("#TrasparencySlider").attr("value"))/100);
        //scorro tutti i pixel: ne determino il colore e li disegno      
        var color = "";
        for (var i = pixel1.xp; i <= pixel2.xp; i++) {
            for (var j = pixel1.yp; j <= pixel2.yp; j++) {
                var intensity = noc[i][j] / max;
                if (intensity < 1 / 5)
                    color = "rgba(0, 0, " + Math.floor(intensity * 5 * 255) + "," + setTrsp + ")";
                else if (1 / 5 <= intensity && intensity < 2 / 5)
                    color = "rgba(0, " + Math.floor((intensity - 1 / 5) * 5 * 255) + ",255, " + setTrsp + ")";
                else if (2 / 5 <= intensity && intensity < 3 / 5)
                    color = "rgba(0, 255, " + (255 - Math.floor((intensity - 2 / 5) * 5 * 255)) + ", " + setTrsp + ")";
                else if (3 / 5 <= intensity && intensity < 4 / 5)
                    color = "rgba(" + Math.floor((intensity - 3 / 5) * 5 * 255) + ",255,0," + setTrsp + ")";
                else
                    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
        zoomRect();
    }
    $("#SaturationSlider").mouseup(function () {
        drawImg(pixel1, pixel2, xMinRange, xMaxRange);
    });
    $("#rePlot").click(function () {
        rePrint = true;
        document.getElementById("SaturationSlider").value = "100";
        drawImg(pixel1, pixel2, xMinRange, xMaxRange);
    });
    $("#TrasparencySlider").mouseup(function () {
        drawImg(pixel1, pixel2, xMinRange, xMaxRange);
    });
    $(".reset").click(function () {
        newOrigin = { xp: 0, yp: 0 };
        rePrint = false;
        calibrated = false;
        globalxMinRange = 0;
        globalxMaxRange = channelDepth;
        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, channelDepth);
        drawChart({ xp: 0, yp: 0 }, { xp: xDim - 1, yp: yDim - 1 }, 0, channelDepth);
    });
    $("#ExportImage").click(function () {
        var img = document.getElementById("myCanvas").toDataURL("image/png");
        $("#ExportLink").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, pixel2, xMinRange, xMaxRange) {
    //definisco la variabile "grafico", i bottoni relativi al grafico, il tag
    //select e le due spinbox con il relativo botton
    var g;
    var box1 = document.getElementById("spinBoxMin");
    var box2 = document.getElementById("spinBoxMax");
    //disegno il grafico completo
    if (pixel1.xp == 0 && pixel1.yp == 0 && pixel2.xp == xDim - 1 && pixel2.yp == yDim - 1) {
        if (!calibrated) {
            var chartTitle = "Chart from (0, 0) to (" + (xDim - 1) + ", " + (yDim - 1) + ")";
            g = setChart(dataCompleteChart, chartTitle);
        }
        else {
            var chartTitle = "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 = new Array(depth);
        for (var i = 0; i < depth; i++) {
            dataForChart[i] = 0;
        }
        for (var i = pixel1.xp; i <= pixel2.xp; i++) {
            for (var j = pixel1.yp; j <= pixel2.yp; j++) {
                for (var k = 0; k < depth; k++) {
                    dataForChart[k] += DataMatrix[i][j][k];
                }
            }
        }
        if (!calibrated) {
            var dataChart = "Channel,Counts\n";
            for (var i = 0; i < depth; i++) {
                dataChart += i + "," + dataForChart[i] + "\n";
            }
            if (pixel1.xp == pixel2.xp && pixel1.yp == pixel2.yp) {
                var chartTitle = "Chart pixel (" + pixel1.xp + ", " + (yDim - pixel1.yp - 1) + ")";
            }
            else {
                var chartTitle = "Chart from (" + pixel1.xp + "," + pixel2.xp + ") to (" +
                    (yDim - pixel1.yp - 1) + ", " + (yDim - pixel2.yp - 1) + ")";
            }
            g = setChart(dataChart, chartTitle);
        }
        else {
            var dataChartCalibrated = "Energy,Counts\n";
            for (var i = 0; i < depth; i++) {
                dataChartCalibrated += round3(((i + 1) * a - b) / 1000) + "," + dataForChart[i] + "\n";
            }
            if (pixel1.xp == pixel2.xp && pixel1.yp == pixel2.yp) {
                var chartTitle = "Calibrated chart pixel (" + pixel1.xp + ", " + (yDim - pixel1.yp - 1) + ")";
            }
            else {
                var chartTitle = "Calibrated chart from (" + pixel1.xp + ", " + pixel2.xp +
                    ") to (" + (yDim - pixel1.yp - 1) + ", " + (yDim - pixel2.yp - 1) + ")";
            }
            g = setChart(dataChartCalibrated, chartTitle);
        }
    }
    $('#setlinearButton').on('click', function () {
        g.updateOptions({ logscale: false });
    });
    $('#setlogButton').on('click', function () {
        g.updateOptions({ logscale: true });
    });
    $('#setEnergyButton').on('click', function () {
        calibrated = true;
        drawChart(pixel1, pixel2, 0, channelDepth);
        box1.setAttribute("value", "0");
        box2.setAttribute("value", "channelDepth");
    });
    $('#setChannelsButton').on('click', function () {
        calibrated = false;
        drawChart(pixel1, pixel2, 0, channelDepth);
        box1.setAttribute("value", "-");
        box2.setAttribute("value", "-");
    });
    $('#ExportGraph').on('click', function () {
        var img = document.getElementById("chartToImg");
        Dygraph.Export.asPNG(g, img);
        $("#ExportGraph").attr("href", img.src.replace('image/png', 'image/octet-stream'));
    });
    $('#readSpinbox').on('click', function () {
        peackSelection(0, 0);
    });
    $('#chart').on('click', function () {
        var r;
        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 () {
        var element = 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, channelDepth);
                box1.setAttribute("value", "0");
                box2.setAttribute("value", "channelDepth");
                break;
        }
    });
    //la funzione setChart riceve in input i dati e il titolo del grafico da disegnare
    //il quale è restituito il output
    function setChart(dataString, charTitle) {
        var xArrayRange; //estremi asse x da visualizzare
        var xLab;
        if (!calibrated) {
            xArrayRange = [0, depth];
            xLab = "ADC Channel";
        }
        else {
            xArrayRange = [xMinRange, xMaxRange];
            xLab = "Energy (keV)";
        }
        //dimensioni grafico
        var chartDim = document.querySelector('#chart-pannel').getBoundingClientRect();
        var chartWidth = chartDim.right - chartDim.left - 50;
        $('#chart').css('width', chartWidth);
        $('#chart').css('height', "400");
        //disegno il grafico
        var graphs = new Dygraph(document.getElementById("chart"), dataString, {
            title: charTitle,
            ylabel: 'Counts',
            xlabel: xLab,
            //legend: 'always',
            labelsDivStyles: { 'textAlign': 'right' },
            dateWindow: xArrayRange,
            showRangeSelector: true,
            logscale: false
        });
        return graphs;
    }
    //la funzione, dati gli estremi dell'intervallo da rappresentare, aggiorna mappa e grafico
    function peackSelection(xMinRange, xMaxRange) {
        //se l'intervallo è [0, 0] devo leggere dalle i valori dalle spinbox
        if (xMinRange == 0 && xMaxRange == 0) {
            xMinRange = parseInt(box1.value);
            xMaxRange = parseInt(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);
    }
}