Skip to content
Snippets Groups Projects
draw.ts 18.3 KiB
Newer Older
// require() is ES5 and allows modifying global variables
// ES6's `from` does not
import G = require("./globals");
import * as $ from "jquery";
import * as Dygraph  from "dygraphs";
import * as Help from "./helper"
Francesco Giacomini's avatar
Francesco Giacomini committed

//la funzione drawImg disegna il canvas con l'immagine desiderata ed è responsabile
//della gestione di tutti gli eventi ad essa associati
export function drawImg(image: G.Image, pixel1: G.coordinates, pixel2: G.coordinates, xMinRange: number, xMaxRange: number, callback?: () => void)
Francesco Giacomini's avatar
Francesco Giacomini committed
{

  //alert("disegno in corso");

  //numero di pixel per dimensione
  let nPixelX: number = pixel2.x - pixel1.x + 1;
  let nPixelY: number = pixel2.y - pixel1.y + 1;
Francesco Giacomini's avatar
Francesco Giacomini committed

  //dimensione dei canvas
  let mappaPannelDim: any = document.querySelector('#mappa-pannel').getBoundingClientRect();
  let mappaWidth: number = mappaPannelDim.right - mappaPannelDim.left - 40;
  let mappaHeigth: number = 400;

  //dimensione reale dei pixel
  let dimPixelx: number = Math.floor(mappaWidth / nPixelX);
  let dimPixely: number = Math.floor(mappaHeigth / nPixelY);
  image.pixelDim = (dimPixelx < dimPixely) ? dimPixelx : dimPixely;
Francesco Giacomini's avatar
Francesco Giacomini committed

  //dimensioni esatte dei canvas
  (<HTMLCanvasElement>document.getElementById("myCanvas")).height = nPixelY * image.pixelDim;
  (<HTMLCanvasElement>document.getElementById("myCanvas")).width = nPixelX * image.pixelDim;
  (<HTMLCanvasElement>document.getElementById("selectionCanvas")).height = nPixelY * image.pixelDim;
  (<HTMLCanvasElement>document.getElementById("selectionCanvas")).width = nPixelX * image.pixelDim;
Francesco Giacomini's avatar
Francesco Giacomini committed
  let ctx = (<HTMLCanvasElement>document.getElementById('myCanvas')).getContext('2d'); //contesto del canvas

  if (xMaxRange - xMinRange >= image.channelDepth) { //range completo
Francesco Giacomini's avatar
Francesco Giacomini committed
    let max: number; //massimo relativo o assoluto
    if (image.rePrint) {
      max = Help.findMax(image.nOfCounts, pixel1, pixel2);
Francesco Giacomini's avatar
Francesco Giacomini committed
    } else {
      max = image.maxAbsolute;
Francesco Giacomini's avatar
Francesco Giacomini committed
    }
    max = (max * $("#SaturationSlider").val()) / 100;
    drawCanvas(image, image.nOfCounts, max);
Francesco Giacomini's avatar
Francesco Giacomini committed

  } else { //range parziale (solo alcuni canali)
    let xMinRangeCh: number = Math.floor((((xMinRange * 1000) + G.Image.getInstance().calibration.b) / G.Image.getInstance().calibration.a) - 1); //16
    let xMaxRangeCh: number = Math.floor((((xMaxRange * 1000) + G.Image.getInstance().calibration.b) / G.Image.getInstance().calibration.a) - 1); //16371
    console.log(G.Image.getInstance().calibration.a);
Francesco Giacomini's avatar
Francesco Giacomini committed
    //calcolo il numero di conteggi solo dei canali selezionati
    let nOfCountsRelative: number[][];
Francesco Giacomini's avatar
Francesco Giacomini committed
    nOfCountsRelative = new Array(image.width);
    for (let i: number = 0; i < image.width; i++) {
      nOfCountsRelative[i] = new Array(image.height);
      for (let j: number = 0; j < image.height; j++) {
        nOfCountsRelative[i][j] = Help.sumVect(image.DataMatrix[i][j], xMinRangeCh, xMaxRangeCh);
Francesco Giacomini's avatar
Francesco Giacomini committed
      }
    }
    //calcolo il massimo
    let max: number;
    if (image.rePrint) {
      max = Help.findMax(nOfCountsRelative, pixel1, pixel2);
Francesco Giacomini's avatar
Francesco Giacomini committed
    } else {
      max = Help.findMax(nOfCountsRelative, { x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 });
Francesco Giacomini's avatar
Francesco Giacomini committed
    }
    max = (max * $("#SaturationSlider").val()) / 100;
Francesco Giacomini's avatar
Francesco Giacomini committed
    drawCanvas(image, nOfCountsRelative, max);
Francesco Giacomini's avatar
Francesco Giacomini committed
  }

  //La funzione, ricevuti dati e massimo, disegna la mappa nel canvas
Francesco Giacomini's avatar
Francesco Giacomini committed
  function drawCanvas(image: G.Image, noc, max)
Francesco Giacomini's avatar
Francesco Giacomini committed
  {

Francesco Giacomini's avatar
Francesco Giacomini committed
    //controllo il valore della trasparenza
Francesco Giacomini's avatar
Francesco Giacomini committed
    let setTrsp: number = 1 - ($("#TrasparencySlider").val() / 100);
    //let setTrsp: number = 1-(parseInt($("#TrasparencySlider").attr("value"))/100);

Francesco Giacomini's avatar
Francesco Giacomini committed
    //scorro tutti i pixel: ne determino il colore e li disegno
Francesco Giacomini's avatar
Francesco Giacomini committed
    let color: string = "";
    for (let i: number = pixel1.x; i <= pixel2.x; i++) {
      for (let j: number = pixel1.y; j <= pixel2.y; j++) {
Francesco Giacomini's avatar
Francesco Giacomini committed
        let 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 + ")";
Francesco Giacomini's avatar
Francesco Giacomini committed
        else if (3 / 5 <= intensity && intensity < 4 / 5) //verde + rosso
Francesco Giacomini's avatar
Francesco Giacomini committed
          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.x) * image.pixelDim, (j - pixel1.y) * image.pixelDim, image.pixelDim, image.pixelDim);
Francesco Giacomini's avatar
Francesco Giacomini committed
      }
    }
    image.rePrint = false; //annullo rePrint
Francesco Giacomini's avatar
Francesco Giacomini committed
    zoomRect();
  }

  $("#SaturationSlider").mouseup(function ()
  { //Slider della saturazione
Francesco Giacomini's avatar
Francesco Giacomini committed
    drawImg(image, pixel1, pixel2, xMinRange, xMaxRange);
Francesco Giacomini's avatar
Francesco Giacomini committed
  });

  $("#rePlot").click(function ()
  { //bottone per colorare con il max relativo
    alert("replot");
    image.rePrint = true;
Francesco Giacomini's avatar
Francesco Giacomini committed
    (<HTMLInputElement>document.getElementById("SaturationSlider")).value = "100";
Francesco Giacomini's avatar
Francesco Giacomini committed
    drawImg(image, pixel1, pixel2, xMinRange, xMaxRange);
Francesco Giacomini's avatar
Francesco Giacomini committed
  });

  $("#TrasparencySlider").mouseup(function ()
  { //Slider della trasparenza
Francesco Giacomini's avatar
Francesco Giacomini committed
    drawImg(image, pixel1, pixel2, xMinRange, xMaxRange);
Francesco Giacomini's avatar
Francesco Giacomini committed
  });

  $("#reset").click(function ()
  { //bottone per il reset dell'applicazione
    let image = G.Image.getInstance();
    image.newOrigin = { x: 0, y: 0 };
    image.rePrint = false;
    G.Chart.getInstance().calibrated = false;
    image.globalxMinRange = 0;
    image.globalxMaxRange = image.channelDepth;
Francesco Giacomini's avatar
Francesco Giacomini committed
    (<HTMLInputElement>document.getElementById("SaturationSlider")).value = "100";
    (<HTMLInputElement>document.getElementById("TrasparencySlider")).value = "0";
    document.getElementById("spinBoxMin").setAttribute("value", "-");
    document.getElementById("spinBoxMax").setAttribute("value", "-");
    drawImg(image, { x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 }, 0, image.channelDepth);
    drawChart(image, { x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 }, 0, image.channelDepth);
Francesco Giacomini's avatar
Francesco Giacomini committed
  });

  $("#ExportImage").click(function ()
  { //esportazione immagine
    let img = (<HTMLCanvasElement>document.getElementById("myCanvas")).toDataURL("image/png");
    $("#ExportLink").attr("href", img);
    //document.write('<img src="'+img+'"/>');
  });
Francesco Giacomini's avatar
Francesco Giacomini committed
}

//la funzione drawChart (input: estremi dell'immagine, estremi dell'intervallo)
//disegna il grafico richiesto relativo alla mappa visualizzata
Francesco Giacomini's avatar
Francesco Giacomini committed
export function drawChart(image: G.Image, pixel1: G.coordinates, pixel2: G.coordinates, xMinRange: number, xMaxRange: number)
Francesco Giacomini's avatar
Francesco Giacomini committed
{

  //definisco la variabile "grafico", i bottoni relativi al grafico, il tag
  //select e le due spinbox con il relativo botton
  let g: any;
  let box1 = <HTMLElement>document.getElementById("spinBoxMin");
  let box2 = <HTMLElement>document.getElementById("spinBoxMax");

  //disegno il grafico completo
Francesco Giacomini's avatar
Francesco Giacomini committed
  if (pixel1.x == 0 && pixel1.y == 0 && pixel2.x == image.width - 1 && pixel2.y == image.height - 1) {
    if (!G.Chart.getInstance().calibrated) { //canali
Francesco Giacomini's avatar
Francesco Giacomini committed
      let chartTitle: string = "Chart from (0, 0) to (" + (image.width - 1) + ", " + (image.height - 1) + ")";
      g = setChart(G.Chart.getInstance().dataCompleteChart, chartTitle);
Francesco Giacomini's avatar
Francesco Giacomini committed
    } else { //energie
Francesco Giacomini's avatar
Francesco Giacomini committed
      let chartTitle: string = "Calibrated chart from (0, 0) to (" + (image.width - 1) + ", " + (image.height - 1) + ")";
      g = setChart(G.Chart.getInstance().dataCompleteChartCalibrated, chartTitle);
Francesco Giacomini's avatar
Francesco Giacomini committed
    }

Francesco Giacomini's avatar
Francesco Giacomini committed
    //disegno il grafico parzialmente
Francesco Giacomini's avatar
Francesco Giacomini committed
  } else {
    //determino i conteggi dei pixel da disegnare
    let dataForChart: number[] = new Array(G.Image.getInstance().depth);
    for (let i: number = 0; i < G.Image.getInstance().depth; i++) {
Francesco Giacomini's avatar
Francesco Giacomini committed
      dataForChart[i] = 0;
    }
    for (let i: number = pixel1.x; i <= pixel2.x; i++) {
      for (let j: number = pixel1.y; j <= pixel2.y; j++) {
        for (let k: number = 0; k < G.Image.getInstance().depth; k++) {
Francesco Giacomini's avatar
Francesco Giacomini committed
          dataForChart[k] += image.DataMatrix[i][j][k];
    if (!G.Chart.getInstance().calibrated) { //disegno in canali
Francesco Giacomini's avatar
Francesco Giacomini committed
      let dataChart: string = "Channel,Counts\n";
      for (let i: number = 0; i < G.Image.getInstance().depth; i++) {
Francesco Giacomini's avatar
Francesco Giacomini committed
        dataChart += i + "," + dataForChart[i] + "\n";
      }
      let chartTitle: string;
      if (pixel1.x == pixel2.x && pixel1.y == pixel2.y) {
Francesco Giacomini's avatar
Francesco Giacomini committed
        chartTitle = "Chart pixel (" + pixel1.x + ", " + (image.height - pixel1.y - 1) + ")";
Francesco Giacomini's avatar
Francesco Giacomini committed
      } else {
        chartTitle = "Chart from (" + pixel1.x + "," + pixel2.x + ") to (" +
Francesco Giacomini's avatar
Francesco Giacomini committed
          (image.height - pixel1.y - 1) + ", " + (image.height - pixel2.y - 1) + ")";
Francesco Giacomini's avatar
Francesco Giacomini committed
      }
      g = setChart(dataChart, chartTitle);

    } else { //disegno in energie
      let dataChartCalibrated: string = "Energy,Counts\n";
      for (let i: number = 0; i < G.Image.getInstance().depth; i++) {
        dataChartCalibrated += Help.round3(((i + 1) * G.Image.getInstance().calibration.a - G.Image.getInstance().calibration.b) / 1000) + "," + dataForChart[i] + "\n";
Francesco Giacomini's avatar
Francesco Giacomini committed
      }
      let chartTitle: string;
      if (pixel1.x == pixel2.x && pixel1.y == pixel2.y) {
Francesco Giacomini's avatar
Francesco Giacomini committed
        chartTitle = "Calibrated chart pixel (" + pixel1.x + ", " + (image.height - pixel1.y - 1) + ")";
Francesco Giacomini's avatar
Francesco Giacomini committed
      } else {
        chartTitle = "Calibrated chart from (" + pixel1.x + ", " + pixel2.x +
Francesco Giacomini's avatar
Francesco Giacomini committed
          ") to (" + (image.height - pixel1.y - 1) + ", " + (image.height - pixel2.y - 1) + ")";
Francesco Giacomini's avatar
Francesco Giacomini committed
      }
      g = setChart(dataChartCalibrated, chartTitle);
    }
  }
  console.log("ci sono");
Francesco Giacomini's avatar
Francesco Giacomini committed
  $('#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
    G.Chart.getInstance().calibrated = true;
    drawChart(image, pixel1, pixel2, 0, image.channelDepth);
Francesco Giacomini's avatar
Francesco Giacomini committed
    box1.setAttribute("value", "0");
    box2.setAttribute("value", "image.channelDepth");
Francesco Giacomini's avatar
Francesco Giacomini committed
  });
  $('#setChannelsButton').on('click', function ()
  { //selezione canali
    G.Chart.getInstance().calibrated = false;
    drawChart(image, pixel1, pixel2, 0, image.channelDepth);
Francesco Giacomini's avatar
Francesco Giacomini committed
    box1.setAttribute("value", "-");
    box2.setAttribute("value", "-");
  });
  $('#ExportGraph').on('click', function ()
  { //esportazione grafico
    let img = <HTMLImageElement>document.getElementById("chartToImg");
    Dygraph.Export.asPNG(g, img);
    $("#ExportGraph").attr("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
    let r: number[];
    r = g.xAxisRange();
    if (!G.Chart.getInstance().calibrated) {
      r[0] = Math.floor((((r[0] + 1) * G.Image.getInstance().calibration.a) - G.Image.getInstance().calibration.b) / 1000);
      r[1] = Math.floor((((r[1] + 1) * G.Image.getInstance().calibration.a) - G.Image.getInstance().calibration.b) / 1000);
Francesco Giacomini's avatar
Francesco Giacomini committed
    } else {
      r[0] = Help.round3(r[0]);
      r[1] = Help.round3(r[1]);
Francesco Giacomini's avatar
Francesco Giacomini committed
      box1.setAttribute("value", r[0].toString());
      box2.setAttribute("value", r[1].toString());
    }
    image.globalxMinRange = r[0];
    image.globalxMaxRange = r[1];
Francesco Giacomini's avatar
Francesco Giacomini committed
    drawImg(image, pixel1, pixel2, r[0], r[1]);
Francesco Giacomini's avatar
Francesco Giacomini committed
  });
  $('#elementSelect').on('change', function ()
  { //selezione elemento
    let element: string = (<HTMLInputElement>document.getElementById("elementSelect")).value;
    switch (element) {
Francesco Giacomini's avatar
Francesco Giacomini committed
      case "1": //Ca
Francesco Giacomini's avatar
Francesco Giacomini committed
        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, image.channelDepth);
Francesco Giacomini's avatar
Francesco Giacomini committed
        box1.setAttribute("value", "0");
        box2.setAttribute("value", "image.channelDepth");
Francesco Giacomini's avatar
Francesco Giacomini committed
        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)
  {

    let xArrayRange: number[]; //estremi asse x da visualizzare
    let xLab: string;
    if (!G.Chart.getInstance().calibrated) {
      xArrayRange = [0, G.Image.getInstance().depth];
Francesco Giacomini's avatar
Francesco Giacomini committed
      xLab = "ADC Channel";
    } else {
      xArrayRange = [xMinRange, xMaxRange];
      xLab = "Energy (keV)";
    }

    //dimensioni grafico
    let chartDim: any = document.querySelector('#chart-pannel').getBoundingClientRect();
    let chartWidth = chartDim.right - chartDim.left - 50;
    $('#chart').css('width', chartWidth);
    $('#chart').css('height', "400");

    //disegno il grafico
    let graphs: any = new Dygraph(document.getElementById("chart"), dataString, {
      title: charTitle,
      ylabel: 'Counts',
      xlabel: xLab,
      //legend: 'always',     
Francesco Giacomini's avatar
Francesco Giacomini committed
      dateWindow: xArrayRange,
      showRangeSelector: true,
      logscale: false
    });

    return graphs;

  }

  //la funzione, dati gli estremi dell'intervallo da rappresentare, aggiorna mappa e grafico
  function peackSelection(xMinRange: number, xMaxRange: number)
  {
    //let image = G.Image.getInstance();
Francesco Giacomini's avatar
Francesco Giacomini committed
    //se l'intervallo è [0, 0] devo leggere dalle i valori dalle spinbox
    if (xMinRange == 0 && xMaxRange == 0) {
      xMinRange = parseInt((<HTMLInputElement>box1).value);
      xMaxRange = parseInt((<HTMLInputElement>box2).value);
    }

    image.globalxMinRange = xMinRange;
    image.globalxMaxRange = xMaxRange;
    image.newOrigin = { x: 0, y: 0 };
    image.rePrint = false;
    G.Chart.getInstance().calibrated = true;
    drawImg(image, { x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 }, image.globalxMinRange, image.globalxMaxRange);
    drawChart(image, { x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 }, image.globalxMinRange, image.globalxMaxRange);
Francesco Giacomini's avatar
Francesco Giacomini committed
  }
}

//la funzione disegna il rettangolo durante la selezione di un'area della mappa
function zoomRect()
{
  let selectCanvas = <HTMLCanvasElement>document.getElementById("selectionCanvas");
  let 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
  let isDown = false;

  // these vars will hold the starting mouse position
  let startX: number;
  let startY: number;
  let mouseX: number;
  let mouseY: number;

  // these vars will hold the starting mouse position

  function handleMouseDown(e)
  {
    e.preventDefault();
    e.stopPropagation();

    //calculate mouse position
    let scrollTOP: number = (document.documentElement.scrollTop) ?
      document.documentElement.scrollTop : document.body.scrollTop;
    let scrollLEFT: number = (document.documentElement.scrollLeft) ?
      document.documentElement.scrollLeft : document.body.scrollLeft;
    let allX: number = e.clientX + scrollLEFT;
    let allY: number = e.clientY + scrollTOP;
    let elParent: any = document.getElementById('myCanvas');
    let objX: number = 0, objY: number = 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
    let scrollTOP: number = (document.documentElement.scrollTop) ?
      document.documentElement.scrollTop : document.body.scrollTop;
    let scrollLEFT: number = (document.documentElement.scrollLeft) ?
      document.documentElement.scrollLeft : document.body.scrollLeft;

    let allX: number = e.clientX + scrollLEFT;
    let allY: number = e.clientY + scrollTOP;
    let elParent: any = document.getElementById('myCanvas');
    let objX: number = 0, objY: number = 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
    let width = mouseX - startX;
    let height = mouseY - startY;

Francesco Giacomini's avatar
Francesco Giacomini committed
    // draw a new rect from the start position
Francesco Giacomini's avatar
Francesco Giacomini committed
    // 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); });

}