Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • faproietti/XRF-App
  • chnet/XRF-App
2 results
Show changes
Commits on Source (13)
Showing
with 1696 additions and 7608 deletions
......@@ -3,3 +3,4 @@ node_modules
*.js
coverage
.vscode
package-lock.json
\ No newline at end of file
import * as $ from "jquery";
export class CallbackManager
{
private static _instance: CallbackManager = new CallbackManager();
private constructor(){
if(CallbackManager._instance) {
throw new Error("Error: Image object is already instantiated");
}
else{
CallbackManager._instance = this;
}
}
public static getInstance(): CallbackManager {
return CallbackManager._instance;
}
class CallbackManager {
constructor() {
}
public showElement(elementID: string, show: boolean): void {
if(show){
$(elementID).css("display", "inline");
if (show) {
document.getElementById(elementID).style.display = "inline";
}
else
{
$(elementID).css("display", "none");
else {
document.getElementById(elementID).style.display = "none";
}
}
public closeBootstrapModel(elementID: string): void{
$(elementID).click();
public closeBootstrapModel(elementID: string): void {
document.getElementById(elementID).click();
}
}
export { CallbackManager };
\ No newline at end of file
import { Image, coordinates } from "./image";
import * as Utility from "./utility";
import "dygraphs"
class Chart {
graphic: any;
private readonly chartElementID: string = "chart";
private setLinearButton: HTMLAnchorElement;
private setLogButton: HTMLAnchorElement;
private setEnergyButton: HTMLAnchorElement;
private setChannelButton: HTMLAnchorElement;
private exportgraph: HTMLAnchorElement;
private readSpinBox: HTMLButtonElement;
private chartElement: HTMLElement;
private elementSelect: HTMLSelectElement;
public spinBoxMin: HTMLInputElement;
public spinBoxMax: HTMLInputElement;
dataCompleteChart: string = "Channel,Counts\n";
dataCompleteChartCalibrated: string = "Energy,Counts\n";
calibrated: boolean = false; //variabile per il controllo sulla calibrazione
constructor() {
this.chartElement = <HTMLElement>document.getElementById(this.chartElementID);
this.spinBoxMin = <HTMLInputElement>document.getElementById("spinBoxMin");
this.spinBoxMax = <HTMLInputElement>document.getElementById("spinBoxMax");
}
drawChart(image: Image, 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
//disegno il grafico completo
if (pixel1.x == 0 && pixel1.y == 0 && pixel2.x == image.width - 1 && pixel2.y == image.height - 1) {
if (!this.calibrated) {
//canali
let chartTitle: string = "Chart from (0, 0) to (" + (image.width - 1) + ", " + (image.height - 1) + ")";
this.graphic = this.setChart(image, this.dataCompleteChart, chartTitle, xMinRange, xMaxRange);
} else {
//energie
let chartTitle: string = "Calibrated chart from (0, 0) to (" + (image.width - 1) + ", " + (image.height - 1) + ")";
this.graphic = this.setChart(image, this.dataCompleteChartCalibrated, chartTitle, xMinRange, xMaxRange);
}
//disegno il grafico parzialmente
} else {
//determino i conteggi dei pixel da disegnare
let dataForChart: number[] = new Array(image.depth);
for (let i: number = 0; i < image.depth; i++) {
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 < image.depth; k++) {
dataForChart[k] += image.DataMatrix[i][j][k];
}
}
}
if (!this.calibrated) {
//disegno in canali
let dataChart: string = "Channel,Counts\n";
for (let i: number = 0; i < image.depth; i++) {
dataChart += i + "," + dataForChart[i] + "\n";
}
let chartTitle: string;
if (pixel1.x == pixel2.x && pixel1.y == pixel2.y) {
chartTitle = "Chart pixel (" + pixel1.x + ", " + (image.height - pixel1.y - 1) + ")";
} else {
chartTitle = "Chart from (" + pixel1.x + "," + pixel2.x + ") to (" + (image.height - pixel1.y - 1) + ", " + (image.height - pixel2.y - 1) + ")";
}
this.graphic = this.setChart(image, dataChart, chartTitle, xMinRange, xMaxRange);
} else {
//disegno in energie
let dataChartCalibrated: string = "Energy,Counts\n";
for (let i: number = 0; i < image.depth; i++) {
dataChartCalibrated += Utility.round3(((i + 1) * image.calibration.a - image.calibration.b) / 1000) + "," + dataForChart[i] + "\n";
}
let chartTitle: string;
if (pixel1.x == pixel2.x && pixel1.y == pixel2.y) {
chartTitle = "Calibrated chart pixel (" + pixel1.x + ", " + (image.height - pixel1.y - 1) + ")";
} else {
chartTitle = "Calibrated chart from (" + pixel1.x + ", " + pixel2.x + ") to (" + (image.height - pixel1.y - 1) + ", " + (image.height - pixel2.y - 1) + ")";
}
this.graphic = this.setChart(image, dataChartCalibrated, chartTitle, xMinRange, xMaxRange);
}
}
}
//la funzione setChart riceve in input i dati e il titolo del grafico da disegnare
//il quale è restituito il output
setChart(image: Image, dataString: string, charTitle: string, xMinRange: number, xMaxRange: number): Dygraph {
let xArrayRange: number[]; //estremi asse x da visualizzare
let xLab: string;
if (!this.calibrated) {
xArrayRange = [0, image.depth];
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;
this.chartElement.setAttribute("width", chartWidth.toString());
this.chartElement.setAttribute("height", "400");
//disegno il grafico
this.graphic = new Dygraph(this.chartElement, dataString,
{
title: charTitle,
ylabel: "Counts",
xlabel: xLab,
// labelsDivStyles: {
// "text-align": "right"
// },
//legend: 'always',
dateWindow: xArrayRange,
showRangeSelector: true,
logscale: false,
});
return this.graphic;
}
//la funzione, dati gli estremi dell'intervallo da rappresentare, aggiorna mappa e grafico
peackSelection(xMinRange: number, xMaxRange: number, image: Image) {
//se l'intervallo è [0, 0] devo leggere dalle i valori dalle spinbox
if (xMinRange == 0 && xMaxRange == 0) {
xMinRange = parseInt((this.spinBoxMin).value);
xMaxRange = parseInt((this.spinBoxMax).value);
}
image.globalxMinRange = xMinRange;
image.globalxMaxRange = xMaxRange;
image.newOrigin = { x: 0, y: 0 };
image.rePrint = false;
this.calibrated = true;
image.drawImg({ x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 }, image.globalxMinRange, image.globalxMaxRange);
this.drawChart(image, { x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 }, image.globalxMinRange, image.globalxMaxRange);
}
}
export { Chart };
// 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"
//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)
{
//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;
//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;
//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;
let ctx = (<HTMLCanvasElement>document.getElementById('myCanvas')).getContext('2d'); //contesto del canvas
if (xMaxRange - xMinRange >= image.channelDepth) { //range completo
let max: number; //massimo relativo o assoluto
if (image.rePrint) {
max = Help.findMax(image.nOfCounts, pixel1, pixel2);
} else {
max = image.maxAbsolute;
}
max = (max * $("#SaturationSlider").val()) / 100;
drawCanvas(image, image.nOfCounts, max);
} 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);
//calcolo il numero di conteggi solo dei canali selezionati
let nOfCountsRelative: number[][];
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);
}
}
//calcolo il massimo
let max: number;
if (image.rePrint) {
max = Help.findMax(nOfCountsRelative, pixel1, pixel2);
} else {
max = Help.findMax(nOfCountsRelative, { x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 });
}
max = (max * $("#SaturationSlider").val()) / 100;
drawCanvas(image, nOfCountsRelative, max);
}
//La funzione, ricevuti dati e massimo, disegna la mappa nel canvas
function drawCanvas(image: G.Image, noc, max)
{
//controllo il valore della trasparenza
let setTrsp: number = 1 - ($("#TrasparencySlider").val() / 100);
//let setTrsp: number = 1-(parseInt($("#TrasparencySlider").attr("value"))/100);
//scorro tutti i pixel: ne determino il colore e li disegno
let color: string = "";
for (let i: number = pixel1.x; i <= pixel2.x; i++) {
for (let j: number = pixel1.y; j <= pixel2.y; j++) {
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 + ")";
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.x) * image.pixelDim, (j - pixel1.y) * image.pixelDim, image.pixelDim, image.pixelDim);
}
}
image.rePrint = false; //annullo rePrint
zoomRect();
}
$("#SaturationSlider").mouseup(function ()
{ //Slider della saturazione
drawImg(image, pixel1, pixel2, xMinRange, xMaxRange);
});
$("#rePlot").click(function ()
{ //bottone per colorare con il max relativo
alert("replot");
image.rePrint = true;
(<HTMLInputElement>document.getElementById("SaturationSlider")).value = "100";
drawImg(image, pixel1, pixel2, xMinRange, xMaxRange);
});
$("#TrasparencySlider").mouseup(function ()
{ //Slider della trasparenza
drawImg(image, pixel1, pixel2, xMinRange, xMaxRange);
});
$("#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;
(<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);
});
$("#ExportImage").click(function ()
{ //esportazione immagine
let img = (<HTMLCanvasElement>document.getElementById("myCanvas")).toDataURL("image/png");
$("#ExportLink").attr("href", img);
//document.write('<img src="'+img+'"/>');
});
callback();
}
//la funzione drawChart (input: estremi dell'immagine, estremi dell'intervallo)
//disegna il grafico richiesto relativo alla mappa visualizzata
export function drawChart(image: G.Image, pixel1: G.coordinates, pixel2: G.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
let g: any;
let box1 = <HTMLElement>document.getElementById("spinBoxMin");
let box2 = <HTMLElement>document.getElementById("spinBoxMax");
//disegno il grafico completo
if (pixel1.x == 0 && pixel1.y == 0 && pixel2.x == image.width - 1 && pixel2.y == image.height - 1) {
if (!G.Chart.getInstance().calibrated) { //canali
let chartTitle: string = "Chart from (0, 0) to (" + (image.width - 1) + ", " + (image.height - 1) + ")";
g = setChart(G.Chart.getInstance().dataCompleteChart, chartTitle);
} else { //energie
let chartTitle: string = "Calibrated chart from (0, 0) to (" + (image.width - 1) + ", " + (image.height - 1) + ")";
g = setChart(G.Chart.getInstance().dataCompleteChartCalibrated, chartTitle);
}
//disegno il grafico parzialmente
} 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++) {
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++) {
dataForChart[k] += image.DataMatrix[i][j][k];
}
}
}
if (!G.Chart.getInstance().calibrated) { //disegno in canali
let dataChart: string = "Channel,Counts\n";
for (let i: number = 0; i < G.Image.getInstance().depth; i++) {
dataChart += i + "," + dataForChart[i] + "\n";
}
let chartTitle: string;
if (pixel1.x == pixel2.x && pixel1.y == pixel2.y) {
chartTitle = "Chart pixel (" + pixel1.x + ", " + (image.height - pixel1.y - 1) + ")";
} else {
chartTitle = "Chart from (" + pixel1.x + "," + pixel2.x + ") to (" +
(image.height - pixel1.y - 1) + ", " + (image.height - pixel2.y - 1) + ")";
}
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";
}
let chartTitle: string;
if (pixel1.x == pixel2.x && pixel1.y == pixel2.y) {
chartTitle = "Calibrated chart pixel (" + pixel1.x + ", " + (image.height - pixel1.y - 1) + ")";
} else {
chartTitle = "Calibrated chart from (" + pixel1.x + ", " + pixel2.x +
") to (" + (image.height - pixel1.y - 1) + ", " + (image.height - pixel2.y - 1) + ")";
}
g = setChart(dataChartCalibrated, chartTitle);
}
}
console.log("ci sono");
$('#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);
box1.setAttribute("value", "0");
box2.setAttribute("value", "image.channelDepth");
});
$('#setChannelsButton').on('click', function ()
{ //selezione canali
G.Chart.getInstance().calibrated = false;
drawChart(image, pixel1, pixel2, 0, image.channelDepth);
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);
} else {
r[0] = Help.round3(r[0]);
r[1] = Help.round3(r[1]);
box1.setAttribute("value", r[0].toString());
box2.setAttribute("value", r[1].toString());
}
image.globalxMinRange = r[0];
image.globalxMaxRange = r[1];
drawImg(image, pixel1, pixel2, r[0], r[1]);
});
$('#elementSelect').on('change', function ()
{ //selezione elemento
let element: string = (<HTMLInputElement>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, image.channelDepth);
box1.setAttribute("value", "0");
box2.setAttribute("value", "image.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: 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];
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',
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();
//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);
}
}
//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;
// 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); });
}
import { Image } from "./image"
import { Chart } from "./chart"
import * as Utility from "./utility"
import "dygraphs"
class Events {
private image: Image;
private chart: Chart;
//////////////////// Chart ///////////////////////////
private readonly setLinearButtonID: string = "setlinearButton";
private readonly setLogButtonID: string = "setlogButton";
private readonly setEnergyButtonID: string = "setEnergyButton";
private readonly setChannelButtonID: string = "setChannelsButton";
private readonly exportGraphID: string = "ExportGraph";
private readonly readSpinBoxID: string = "readSpinbox";
private readonly chartElementID: string = "chart";
private readonly elementSelectID: string = "elementSelect";
private setLinearButton: HTMLAnchorElement;
private setLogButton: HTMLAnchorElement;
private setEnergyButton: HTMLAnchorElement;
private setChannelButton: HTMLAnchorElement;
private exportgraph: HTMLAnchorElement;
private readSpinBox: HTMLButtonElement;
private chartElement: HTMLElement;
private elementSelect: HTMLSelectElement;
public spinBoxMin: HTMLInputElement;
public spinBoxMax: HTMLInputElement;
//////////////////// Image ///////////////////////////
private startX: number;
private startY: number;
private mouseX: number;
private mouseY: number;
private readonly saturationSliderID: string = "SaturationSlider";
private readonly replotButtonID: string = "rePlot";
private readonly transparencySliderID: string = "TrasparencySlider";
private readonly resetID: string = "reset";
private readonly exportImageID: string = "ExportImage";
private readonly selectionCanvasID: string = "selectionCanvas";
private readonly myCanvasID: string = "myCanvas";
private saturationSlider: HTMLInputElement;
private replotButton: HTMLButtonElement;
private transparencySlider: HTMLInputElement;
private reset: HTMLDivElement;
private exportImage: HTMLDivElement;
private selectionCanvas: HTMLCanvasElement;
private myCanvas: HTMLCanvasElement;
private ctx;
private isDown = false;
constructor(image: Image, chart: Chart) {
this.image = image;
this.chart = chart;
//////////////////// Chart ///////////////////////////
this.setLinearButton = <HTMLAnchorElement>document.getElementById(this.setLinearButtonID);
this.setLinearButton.addEventListener("click", this.setLinearButtonClick, false);
this.setLogButton = <HTMLAnchorElement>document.getElementById(this.setLogButtonID);
this.setLogButton.addEventListener("click", this.setLogButtonClick, false);
this.setEnergyButton = <HTMLAnchorElement>document.getElementById(this.setEnergyButtonID);
this.setEnergyButton.addEventListener("click", this.setEnergyButtonClick, false);
this.setChannelButton = <HTMLAnchorElement>document.getElementById(this.setChannelButtonID);
this.setChannelButton.addEventListener("click", this.setChannelButtonClick, false);
this.exportgraph = <HTMLAnchorElement>document.getElementById(this.exportGraphID);
this.exportgraph.addEventListener("click", this.exportGraphClick, false);
this.readSpinBox = <HTMLButtonElement>document.getElementById(this.readSpinBoxID);
this.readSpinBox.addEventListener("click", this.readSpinBoxClick, false);
this.chartElement = <HTMLElement>document.getElementById(this.chartElementID);
this.chartElement.addEventListener("mouseup", this.chartClick, false);
this.elementSelect = <HTMLSelectElement>document.getElementById(this.elementSelectID);
this.elementSelect.addEventListener("select", this.elementSelectEvent, false);
//////////////////// Image ///////////////////////////
this.selectionCanvas = <HTMLCanvasElement>document.getElementById(this.selectionCanvasID);
this.ctx = this.selectionCanvas.getContext("2d");
this.myCanvas = <HTMLCanvasElement>document.getElementById(this.myCanvasID);
this.saturationSlider = <HTMLInputElement>document.getElementById(this.saturationSliderID);
this.replotButton = <HTMLButtonElement>document.getElementById(this.replotButtonID);
this.transparencySlider = <HTMLInputElement>document.getElementById(this.transparencySliderID);
this.reset = <HTMLDivElement>document.getElementById(this.resetID);
this.exportImage = <HTMLDivElement>document.getElementById(this.exportImageID);
this.saturationSlider.addEventListener("mouseup", this.saturationSliderMouseUp, false);
this.replotButton.addEventListener("click", this.replotButtonClick, false);
this.transparencySlider.addEventListener("mouseup", this.trasparencySliderMouseUp, false);
this.reset.addEventListener("click", this.resetClick, false);
this.exportImage.addEventListener("click", this.exportImageClick, false);
this.selectionCanvas.addEventListener("mousedown", this.selectionCanvasMouseDown, false);
this.selectionCanvas.addEventListener("mouseup", this.clickdown, false);
this.selectionCanvas.addEventListener("mousemove", this.selectionCanvasMouseMove, false);
this.selectionCanvas.addEventListener("mouseup", this.selectionCanvasMouseUp, false);
this.selectionCanvas.addEventListener("mouseout", this.selectionCanvasMouseOut, false);
}
private saturationSliderMouseUp = (event: MouseEvent): void => {
this.image.drawImg(this.image.pixel1, this.image.pixel2, this.image.globalxMinRange, this.image.globalxMaxRange);
};
private replotButtonClick = (event: MouseEvent) => {
//bottone per colorare con il max relativo
this.image.rePrint = true;
this.saturationSlider.value = "100";
// opacity value?
this.image.drawImg(this.image.pixel1, this.image.pixel2, this.image.globalxMinRange, this.image.globalxMaxRange);
};
private trasparencySliderMouseUp = (event: MouseEvent) => {
this.image.drawImg(this.image.pixel1, this.image.pixel2, this.image.globalxMinRange, this.image.globalxMaxRange);
};
private resetClick = (event: MouseEvent) => {
this.image.newOrigin = { x: 0, y: 0 };
this.image.rePrint = false;
this.chart.calibrated = false;
this.image.globalxMinRange = 0;
this.image.globalxMaxRange = this.image.channelDepth;
this.saturationSlider.value = "100";
this.transparencySlider.value = "0";
this.chart.spinBoxMin.setAttribute("value", "-");
this.chart.spinBoxMax.setAttribute("value", "-");
this.image.drawImg({ x: 0, y: 0 }, { x: this.image.width - 1, y: this.image.height - 1 }, 0, this.image.channelDepth);
this.chart.drawChart(this.image, { x: 0, y: 0 }, { x: this.image.width - 1, y: this.image.height - 1 }, 0, this.image.channelDepth);
};
private exportImageClick = (event: MouseEvent) => {
//esportazione immagine
let img = this.selectionCanvas.toDataURL("image/png");
this.selectionCanvas.setAttribute("href", img.replace("image/png", "image/octet-stream"));
document.getElementById("ExportLink").setAttribute("href", img);
};
private clickdown = (event: MouseEvent): void => {
this.image.setPosition(event, this.image.zPixel2, this.selectionCanvasID);
let tmp: number;
if (this.image.zPixel1.y > this.image.zPixel2.y) {
tmp = this.image.zPixel1.y;
this.image.zPixel1.y = this.image.zPixel2.y;
this.image.zPixel2.y = tmp;
}
//se è stato cliccato un punto disegno il grafico, altrimenti disegno anche il
//canvas e aggiorno l'origine
if (this.image.zPixel1.x != this.image.zPixel2.x || this.image.zPixel1.y != this.image.zPixel2.y) {
this.image.newOrigin = { x: this.image.zPixel1.x, y: this.image.zPixel1.y };
this.image.drawImg(this.image.zPixel1, this.image.zPixel2, this.image.globalxMinRange, this.image.globalxMaxRange);
}
this.chart.drawChart(this.image, this.image.zPixel1, this.image.zPixel2, this.image.globalxMinRange, this.image.globalxMaxRange);
};
private selectionCanvasMouseDown = (event: MouseEvent) => {
event.preventDefault();
event.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 = event.clientX + scrollLEFT;
let allY: number = event.clientY + scrollTOP;
let elParent: any = this.myCanvas;
let objX: number = 0, objY: number = 0;
while (elParent) {
objX += elParent.offsetLeft;
objY += elParent.offsetTop;
elParent = elParent.offsetParent;
}
this.startX = allX - objX;
this.startY = allY - objY;
// set a flag indicating the drag has begun
this.isDown = true;
};
private selectionCanvasMouseUp = (event: MouseEvent) => {
event.preventDefault();
event.stopPropagation();
// the drag is over, clear the dragging flag
this.isDown = false;
//this.ctx.clearRect(0, 0, this.selectionCanvas.width, this.selectionCanvas.height);
};
private selectionCanvasMouseMove = (event: MouseEvent) => {
event.preventDefault();
event.stopPropagation();
// if we're not dragging, just return
if (!this.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 = event.clientX + scrollLEFT;
let allY: number = event.clientY + scrollTOP;
let elParent: any = this.myCanvas;
let objX: number = 0, objY: number = 0;
while (elParent) {
objX += elParent.offsetLeft;
objY += elParent.offsetTop;
elParent = elParent.offsetParent;
}
this.mouseX = allX - objX;
this.mouseY = allY - objY;
// clear the canvas
//this.ctx.clearRect(0, 0, this.selectionCanvas.width, this.selectionCanvas.height);
// calculate the rectangle width/height based
// on starting vs current mouse position
let width = this.mouseX - this.startX;
let height = this.mouseY - this.startY;
// draw a new rect from the start position
// to the current mouse position
this.ctx.fillRect(this.startX, this.startY, width, height);
};
private selectionCanvasMouseOut = (event: MouseEvent) => {
event.preventDefault();
event.stopPropagation();
// the drag is over, clear the dragging flag
this.isDown = false;
//this.ctx.clearRect(0, 0, this.selectionCanvas.width, this.selectionCanvas.height);
};
private setLinearButtonClick = (event: MouseEvent) => {
this.chart.graphic.updateOptions({ logscale: false });
};
private setLogButtonClick = (event: MouseEvent) => {
this.chart.graphic.updateOptions({ logscale: true });
};
private setEnergyButtonClick = (event: MouseEvent) => {
this.chart.calibrated = true;
this.chart.drawChart(this.image, this.image.pixel1, this.image.pixel2, 0, this.image.channelDepth);
this.spinBoxMin.setAttribute("value", "0");
this.spinBoxMax.setAttribute("value", this.image.channelDepth.toString());
};
private setChannelButtonClick = (event: MouseEvent) => {
this.chart.calibrated = false;
this.chart.drawChart(this.image, this.image.pixel1, this.image.pixel2, 0, this.image.channelDepth);
this.spinBoxMin.setAttribute("value", "-");
this.spinBoxMax.setAttribute("value", "-");
};
private exportGraphClick = (event: MouseEvent) => {
let img = <HTMLImageElement>document.getElementById("chartToImg");
//Dygraph..asPNG(this.chart.graphic, img);
this.exportgraph.setAttribute("href", img.src.replace("image/png", "image/octet-stream"));
};
private readSpinBoxClick = (event: MouseEvent) => {
//esportazione grafico
console.log("readspinbox");
this.chart.peackSelection(0, 0, this.image);
};
private chartClick = (event: MouseEvent) => {
//zoom manuale sul grafico
console.log("chartClick");
let r: number[];
r = this.chart.graphic.xAxisRange();
if (!this.chart.calibrated) {
r[0] = Math.floor(((r[0] + 1) * this.image.calibration.a - this.image.calibration.b) / 1000);
r[1] = Math.floor(((r[1] + 1) * this.image.calibration.a - this.image.calibration.b) / 1000);
} else {
r[0] = Utility.round3(r[0]);
r[1] = Utility.round3(r[1]);
this.spinBoxMin.setAttribute("value", r[0].toString());
this.spinBoxMax.setAttribute("value", r[1].toString());
}
this.image.globalxMinRange = r[0];
this.image.globalxMaxRange = r[1];
this.image.drawImg(this.image.pixel1, this.image.pixel2, r[0], r[1]);
};
private elementSelectEvent = (event: MouseEvent) => {
//selezione elemento
let element: string = this.elementSelect.value;
switch (element) {
case "1": //Ca
this.chart.peackSelection(3.6, 3.8, this.image);
this.spinBoxMin.setAttribute("value", "3.60");
this.spinBoxMax.setAttribute("value", "3.80");
break;
case "2": //Pb
this.chart.peackSelection(10.4, 10.7, this.image);
this.spinBoxMin.setAttribute("value", "10.40");
this.spinBoxMax.setAttribute("value", "10.70");
break;
case "3": //Hg
this.chart.peackSelection(9.8, 10.15, this.image);
this.spinBoxMin.setAttribute("value", "9.80");
this.spinBoxMax.setAttribute("value", "10.15");
break;
case "4": //Fe
this.chart.peackSelection(6.3, 6.5, this.image);
this.spinBoxMin.setAttribute("value", "6.30");
this.spinBoxMax.setAttribute("value", "6.50");
break;
case "5": //Cu
this.chart.peackSelection(7.85, 8.2, this.image);
this.spinBoxMin.setAttribute("value", "7.85");
this.spinBoxMax.setAttribute("value", "8.20");
break;
case "6": //Zn
this.chart.peackSelection(8.5, 8.72, this.image);
this.spinBoxMin.setAttribute("value", "8.50");
this.spinBoxMax.setAttribute("value", "8.72");
break;
case "7": //Ti
this.chart.peackSelection(4.35, 4.65, this.image);
this.spinBoxMin.setAttribute("value", "4.35");
this.spinBoxMax.setAttribute("value", "4.65");
break;
case "8": //K
this.chart.peackSelection(3.2, 3.42, this.image);
this.spinBoxMin.setAttribute("value", "3.20");
this.spinBoxMax.setAttribute("value", "3.42");
break;
case "9": //Co
this.chart.peackSelection(6.8, 7.05, this.image);
this.spinBoxMin.setAttribute("value", "6.80");
this.spinBoxMax.setAttribute("value", "7.05");
break;
default:
this.chart.peackSelection(0, this.image.channelDepth, this.image);
this.spinBoxMin.setAttribute("value", "0");
this.spinBoxMax.setAttribute("value", this.image.channelDepth.toString());
break;
}
};
}
export { Events };
\ No newline at end of file
import G = require("./globals");
import * as gfs from "./fs";
import {Fs} from "./fs";
import * as fs from "fs";
import * as md5 from "ts-md5/dist/md5";
import { Image } from "./image";
import { Chart } from "./chart";
let content: Buffer;
let lines: string[];
let numbers: number[];
let image: Image = new Image();
let chart: Chart = new Chart();
let filesys: Fs = new Fs();
beforeAll(() =>
{
content = fs.readFileSync("XRF-File-System/Pergamena-Medioevale/codapavone_500.txt");
......@@ -16,7 +21,7 @@ beforeAll(() =>
test("get_metadata", () =>
{
let metadata = gfs.get_metadata(numbers);
let metadata = filesys.get_metadata(image, numbers);
expect(metadata).toEqual({
xMin: 50088000,
xMax: 50103000,
......@@ -29,14 +34,7 @@ test("get_metadata", () =>
test("readImage", () =>
{
let image = gfs.readImage(content.toString());
expect(md5.Md5.hashAsciiStr(JSON.stringify(image))).toBe("0a77bca5eb4c9bdd137c753a21b98545"); // coda_pavone_500
let readImage = filesys.readImage(image, chart, content.toString());
expect(md5.Md5.hashAsciiStr(JSON.stringify(readImage))).toBe("0a77bca5eb4c9bdd137c753a21b98545"); // coda_pavone_500
//expect(md5.Md5.hashAsciiStr(JSON.stringify(image))).toBe("b9e7fb96f36452cc3c2350d6132b50c6"); // coda_pavone_250
})
/* test("readImage_lc", () =>
{
let image = gfs.readImage_lc(content.toString());
console.log(md5.Md5.hashAsciiStr(JSON.stringify(image));
})
*/
This diff is collapsed.
export interface coordinates
{
x: number;
y: number;
}
export class Calibration
{
a: number;
b: number;
}
export enum ReadDirection {
u,// lettura non definita
r,//lettura per righe
c//lettura per colonne
}
export class Metadata
{
private static _instance: Metadata = new Metadata();
private constructor() {
if(Metadata._instance) {
throw new Error("Error: Image object is already instantiated");
}
else {
Metadata._instance = this;
}
}
xMin: number = 0;
xMax: number = 0;
yMin: number = 0;
yMax: number = 0;
step: number = 0;
direction: ReadDirection = ReadDirection.u;
public static getInstance(): Metadata {
return Metadata._instance;
}
}
export class Image
{
private static _instance: Image = new Image();
private constructor() {
if(Image._instance)
{
throw new Error ("Error: Image object is already instantiated");
}
else
{
Image._instance = this;
}
}
DataMatrix: number[][][];
width: number;
height: number;
readonly calibration: Calibration = {a: 3.36275, b: 58.2353};
readonly depth: number = 8000;
readonly maxCoordValueX = 60000000;
readonly headerSetValue = 17000;
readonly xCoordHeaderFirstValue = 5; //instestazione X
readonly yCoordHeaderFirstValue = 6; //intestazione y
channelDepth: number = require("./helper").round3(((this.depth + 1) * this.calibration.a - this.calibration.b) / 1000); //profondità massima in canali
globalxMinRange: number = 0;
globalxMaxRange: number = this.channelDepth;
zPixel1: coordinates;
zPixel2: coordinates; //pixel2 dello zoom
newOrigin: coordinates = { x: 0, y: 0}; //nuovo origine nel caso di zoom
maxAbsolute: number; //massimo conteggio della matrice nOfCounts
pixelDim: number; //dimensione dei pixel responsive
nOfCounts: number[][]; //matrici con i dati
rePrint: boolean = false; //variabile per ricolorare con il max relativo
public static getInstance(): Image
{
return Image._instance;
}
}
export class Chart {
private static _instance: Chart = new Chart();
private constructor()
{
if(Chart._instance)
{
throw new Error("Error: Image object is already instantiated");
}
else
{
Chart._instance = this;
}
}
dataCompleteChart: string = "Channel,Counts\n";
dataCompleteChartCalibrated: string = "Energy,Counts\n";
calibrated: boolean = false; //variabile per il controllo sulla calibrazione
public static getInstance(): Chart
{
return Chart._instance;
}
}
import * as Utility from "./utility";
interface coordinates // used in multiple files
{
x: number;
y: number;
}
class Calibration //used in multiple files
{
a: number;
b: number;
}
class Image {
private readonly saturationSliderID: string = "SaturationSlider";
private readonly transparencySliderID: string = "TrasparencySlider";
private readonly selectionCanvasID: string = "selectionCanvas";
private readonly myCanvasID: string = "myCanvas";
private context: CanvasRenderingContext2D;
private saturationSlider: HTMLInputElement;
private transparencySlider: HTMLInputElement;
pixel1: coordinates;
pixel2: coordinates;
private xMinRange: number;
private xMaxRange: number;
private selectionCanvas: HTMLCanvasElement;
private myCanvas: HTMLCanvasElement;
private ctx;
private isDown = false;
DataMatrix: number[][][];
width: number;
height: number;
readonly calibration: Calibration = { a: 3.36275, b: 58.2353 };
readonly depth: number = 8000;
channelDepth: number = Utility.round3(((this.depth + 1) * this.calibration.a - this.calibration.b) / 1000); //profondità massima in canali
readonly maxCoordValueX = 60000000; // to check
readonly headerSetValue = 17000;
readonly xCoordHeaderFirstValue = 5; //instestazione X
readonly yCoordHeaderFirstValue = 6; //intestazione y
globalxMinRange: number = 0;
globalxMaxRange: number = this.channelDepth;
zPixel1: coordinates;
zPixel2: coordinates; //pixel2 dello zoom
newOrigin: coordinates = { x: 0, y: 0 }; //nuovo origine nel caso di zoomù
maxAbsolute: number; //massimo conteggio della matrice nOfCounts
pixelDim: number; //dimensione dei pixel responsive
nOfCounts: number[][]; //matrici con i dati
rePrint: boolean = false; //variabile per ricolorare con il max relativo
constructor() {
this.selectionCanvas = <HTMLCanvasElement>document.getElementById(this.selectionCanvasID);
this.ctx = this.selectionCanvas.getContext("2d");
this.myCanvas = <HTMLCanvasElement>document.getElementById(this.myCanvasID);
this.saturationSlider = <HTMLInputElement>document.getElementById(this.saturationSliderID);
this.transparencySlider = <HTMLInputElement>document.getElementById(this.transparencySliderID);
}
//Il metodo findPosition definisce la posizione del cursore del mouse
//relativa al canvas nel momento in cui avviene l'evento passato in input
setPosition(event: any, pixel: coordinates, canvasID: string) {
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 = event.clientX + scrollLEFT;
let allY: number = event.clientY + scrollTOP;
let elParent: any = document.getElementById(canvasID);
let objX: number = 0,
objY: number = 0;
while (elParent) {
objX += elParent.offsetLeft;
objY += elParent.offsetTop;
elParent = elParent.offsetParent;
}
pixel.x = Math.floor((allX - objX - 1) / this.pixelDim) + this.newOrigin.x;
pixel.y = Math.floor((allY - objY - 1) / this.pixelDim) + this.newOrigin.y;
}
drawImg(pixel1: coordinates, pixel2: coordinates, xMinRange: number, xMaxRange: number, callback?: () => void) {
this.pixel1 = pixel1;
this.pixel2 = pixel2;
//alert("disegno in corso");
//numero di pixel per dimensione
let nPixelX: number = this.pixel2.x - this.pixel1.x + 1;
let nPixelY: number = this.pixel2.y - this.pixel1.y + 1;
//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);
this.pixelDim = dimPixelx < dimPixely ? dimPixelx : dimPixely;
//dimensioni esatte dei canvas
this.myCanvas.height = nPixelY * this.pixelDim;
this.myCanvas.width = nPixelX * this.pixelDim;
this.selectionCanvas.height = nPixelY * this.pixelDim;
this.selectionCanvas.width = nPixelX * this.pixelDim;
let ctx = this.myCanvas.getContext("2d"); //contesto del canvas
if (xMaxRange - xMinRange >= this.channelDepth) {
//range completo
let max: number = 0; //massimo relativo o assoluto
if (this.rePrint) {
max = Utility.findMax(this.nOfCounts, this.pixel1, this.pixel2);
} else {
max = this.maxAbsolute;
}
max *= parseInt(this.saturationSlider.value) / 100;
this.drawCanvas(this.nOfCounts, max);
} else {
//range parziale (solo alcuni canali)
let xMinRangeCh: number = Math.floor((xMinRange * 1000 + this.calibration.b) / this.calibration.a - 1); //16
let xMaxRangeCh: number = Math.floor((xMaxRange * 1000 + this.calibration.b) / this.calibration.a - 1); //16371
//calcolo il numero di conteggi solo dei canali selezionati
let nOfCountsRelative: number[][];
nOfCountsRelative = new Array(this.width);
for (let i: number = 0; i < this.width; i++) {
nOfCountsRelative[i] = new Array(this.height);
for (let j: number = 0; j < this.height; j++) {
nOfCountsRelative[i][j] = Utility.sumVect(this.DataMatrix[i][j], xMinRangeCh, xMaxRangeCh);
}
}
//calcolo il massimo
let max: number = 0;
if (this.rePrint) {
max = Utility.findMax(nOfCountsRelative, this.pixel1, this.pixel2);
} else {
max = Utility.findMax(nOfCountsRelative, { x: 0, y: 0 }, { x: this.width - 1, y: this.height - 1 });
}
max *= parseInt(this.saturationSlider.value) / 100;
if (max == 0)
alert("WARNING: max value is 0");
else
this.drawCanvas(nOfCountsRelative, max);
}
if (typeof (callback) != typeof (undefined))
callback();
}
private drawCanvas(noc, max) {
//controllo il valore della trasparenza
let setTrsp: number = 1 - parseInt(this.transparencySlider.value) / 100;
//scorro tutti i pixel: ne determino il colore e li disegno
let color: string = "";
for (let i: number = this.pixel1.x; i <= this.pixel2.x; i++) {
for (let j: number = this.pixel1.y; j <= this.pixel2.y; j++) {
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 + ")";
else if (3 / 5 <= intensity && intensity < 4 / 5)
//verde + rosso
color = "rgba(" + Math.floor((intensity - 3 / 5) * 5 * 255) + ",255,0," + setTrsp + ")";
//rosso -verde
else
color = "rgba(255," + (255 - Math.floor((intensity - 4 / 5) * 5 * 255)) + ", 0, " + setTrsp + ")";
this.ctx.fillStyle = color;
this.ctx.fillRect((i - this.pixel1.x) * this.pixelDim, (j - this.pixel1.y) * this.pixelDim, this.pixelDim, this.pixelDim);
}
}
//console.log(color);
this.rePrint = false; //annullo rePrint
this.ctx.fillStyle = "rgba(0, 110, 255, 0.25)";
this.isDown = false;
}
}
export { coordinates, Calibration, Image };
import { Image } from "./image";
import { Chart } from "./chart";
import { Fs } from "./fs";
import { CallbackManager } from "./callbacks"
import $ = require("jquery");
class ImportFile {
private image: Image;
private chart: Chart;
private fs: Fs;
private callbackManager: CallbackManager;
constructor(drawImage: Image, drawChart: Chart) {
this.image = drawImage;
this.chart = drawChart;
this.fs = new Fs();
this.callbackManager = new CallbackManager();
}
//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
setImportFile() {
// genero e leggo il contenuto della directory "filesystem"
// comment out waiting to properly address the request
// let xmlDoc: Document;
// let xmlListingFile: any = new XMLHttpRequest();
// xmlListingFile.open("PROPFIND", "CHNET/", false);
// xmlListingFile.setRequestHeader("Depth", "infinity");
// xmlListingFile.onreadystatechange = function () {
// if (xmlListingFile.readyState === 4) {
// if (xmlListingFile.status === 207) {
// let parser = new DOMParser();
// xmlDoc = parser.parseFromString(xmlListingFile.responseText, "text/xml");
// }
// }
// }
// xmlListingFile.send(null);
//ora genero l'albero e definisco l'evento in caso di selezione di un nodo
// jQuery(document.getElementById('FileTreeview')).treeview({ data: this.fs.generateTree(xmlDoc) });
// $('#FileTreeview').on('nodeSelected', (e, node) => {
// if (node['url'] != undefined) {
// $("#load-spinner").css("display", "inline");
// this.fs.openFileFromServer(node['url']);
// }
// });
// import a local file
let fileInputButton: any = document.getElementById("myImport");
fileInputButton.onchange = () => {
this.callbackManager.showElement("load-spinner", true);
let file: File = fileInputButton.files[0];
let readerObject = new FileReader();
readerObject.onload = () => {
let content = readerObject.result;
let image = this.fs.readImage(this.image, this.chart, content);
this.callbackManager.showElement("load-spinner", false);
this.image.drawImg({ x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 }, 0, image.channelDepth,
() => { this.callbackManager.closeBootstrapModel("btnCloseModal"); });
this.chart.drawChart(image, { x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 }, 0, image.channelDepth);
};
readerObject.readAsText(file);
};
}
//funzione per la compressione della sidenav sx
compressingSidenav() {
let fsLabel = document.getElementById("collapse-symbol");
let isClosedfs = false;
let fsLabel_cross = () => {
if (isClosedfs == true) {
isClosedfs = false;
console.log("closed");
$(".w3-bar-block").css("width", "65px");
$(".text-sidenav").css("display", "none");
document.getElementById("collapse-symbol").title = "Open Sidebar";
document.getElementById("collapse-symbol").classList.replace("fa-angle-double-left", "fa-angle-double-right");
} else {
isClosedfs = true;
$(".w3-bar-block").css("width", "200px");
$(".text-sidenav").css("display", "inline");
document.getElementById("collapse-symbol").title = "Close Sidebar";
document.getElementById("collapse-symbol").classList.replace("fa-angle-double-right", "fa-angle-double-left");
}
};
fsLabel.addEventListener("mousedown", fsLabel_cross, false);
}
//funzione che definisce l'area su cui si può eseguire il drag&drop
makeDroppable(droppableArea) {
//creo l'elemento "input type file" non visibile e lo aggiungo a "droppableArea"
let input: any = document.createElement("input");
input.type = "file";
input.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");
this.callback(e.dataTransfer.files, this.image, this.chart);
});
}
//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()
private callback(files, drawImage: Image, drawChart: Chart, fs: Fs) {
this.callbackManager.showElement("load-spinner", true);
let file: File = files[files.length - 1];
console.log("Try to open " + file.name + " ...");
let readerObject = new FileReader();
readerObject.onload = () => {
let content = readerObject.result;
fs.readImage(drawImage, drawChart, content);
this.callbackManager.showElement("load-spinner", false);
};
readerObject.readAsText(file);
}
}
export { ImportFile };
\ No newline at end of file
......@@ -9,13 +9,18 @@
<title>XRF analysis viewer</title>
<!-- CSS -->
<link href="src/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link rel="stylesheet" type="text/css" href="style.css">
<link rel="stylesheet" type="text/css" href="src/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="src/bootstrap-treeview/dist/bootstrap-treeview.min.css">
<link rel="stylesheet" type="text/css" href="src/bootstrap-select/dist/bootstrap-select.min.css">
<link rel="stylesheet" type="text/css" href="src/font-awesome/dist/font-awesome.min.css">
<!-- CSS -->
<link rel="stylesheet" type="text/css" href="style.css">
<link rel="stylesheet" type="text/css" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="node_modules/bootstrap-select/dist/css/bootstrap-select.min.css">
<link rel="stylesheet" type="text/css" href="src/font-awesome/dist/font-awesome.min.css">
<!-- Librerie -->
<script type="text/javascript" src="node_modules/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script type="text/javascript" src="node_modules/dygraphs/dist/dygraph.min.js"></script>
<script type="text/javascript" src="xrf.js"></script>
<!-- ./Librerie -->
</head>
......@@ -49,7 +54,7 @@
} else {
echo "<img src=\"./default-avatar.png\" class=\"img-circle\" width=\"25\">";
}
// echo " ".ucfirst($_SERVER["OIDC_CLAIM_name"]);
//echo " ".ucfirst($_SERVER["OIDC_CLAIM_name"]);
?>
<span class="glyphicon glyphicon-chevron-down"></span>
</a>
......@@ -71,7 +76,7 @@
<!-- ./navbar -->
<!-- Sidenav -->
<div class="w3-bar-block w3-border">
<div class="w3-bar-block w3-border" id="sidenav">
<div class="w3-bar-item w3-button">
<a href="">
<i class="fa fa-home" data-toggle="tooltip" data-placement="right" title="Home"></i>
......@@ -91,7 +96,7 @@
<span class="text-sidenav" style="display:none">Refresh</span>
</div>
<div class="w3-bar-item w3-button">
<a id="ExportLink" download="Canvas.jpg" href="#" class="w3-bar-item w3-button">
<a id="ExportLink" download="Canvas.png" href="#" class="w3-bar-item w3-button">
<div id="ExportImage">
<i class="fa fa-file-image-o" data-toggle="tooltip" data-placement="right" title="Export Map"></i>
<span class="text-sidenav" style="display:none">Export Map</span>
......@@ -99,7 +104,7 @@
</a>
</div>
<div class="w3-bar-item w3-button">
<a href="#" id="ExportGraph" download="Spectrum.jpg" class="w3-bar-item w3-button">
<a href="#" id="ExportGraph" download="Spectrum.png" class="w3-bar-item w3-button">
<i class="fa fa-bar-chart" data-toggle="tooltip" data-placement="right" title="Export Chart"></i>
<span class="text-sidenav" style="display:none">Export Chart</span>
</a>
......@@ -148,7 +153,7 @@
<h2>XRF Image</h2>
<!-- canvas -->
<div style="position: relative; height=400px;">
<div style="position: relative; height: 400px;">
<canvas id="selectionCanvas" height="400px" width="360px"></canvas>
<canvas id="myCanvas" height="400px" width="360px"></canvas>
</div>
......@@ -243,17 +248,7 @@
</div>
<!-- ./riga 1 -->
</div>
<!-- /.collapsable-page -->
<!-- Librerie -->
<script type="text/javascript" src="src/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="src/js/bootstrap.min.js"></script>
<script type="text/javascript" src="node_modules/bootstrap/js/dist/tooltip.js"></script>
<script type="text/javascript" src="src/bootstrap-treeview/dist/bootstrap-treeview.min.js"></script>
<script type="text/javascript" src="src/bootstrap-select/dist/bootstrap-select.min.js"></script>
<script type="text/javascript" src="src/dygraph/dist/dygraph-combined-dev.js"></script>
<script type="text/javascript" src="src/dygraph/dist/dygraph-extra.js"></script>
<script type="text/javascript" src="xrf.js"></script>
<!-- ./Librerie -->
<!-- /.collapsable-page -->
</body>
</html>
This diff is collapsed.
{
"name": "chnet-xrf",
"version": "0.1.0",
"scripts": {
"test": "jest"
},
"dependencies": {
"assert": "latest",
"bootstrap": "latest",
"bootstrap": "v3.3.7",
"bootstrap-select": "^1.12.4",
"bootstrap-slider": "^10.0.0",
"bootstrap-tooltip": "^3.1.1",
"bootstrap-treeview": "^1.2.0",
"bower": "^1.8.4",
"dygraphs": "^2.0.0",
"jquery": "^3.3.1",
"popper": "^1.0.1",
"popper.js": "^1.14.3"
"jquery": "^3.3.1"
},
"description": "Web application to analyse XRF images",
"scripts": {
"test": "jest"
},
"license": "EUPL",
"repository": {
"type": "git",
"url": "https://baltig.infn.it/chnet/XRF-App.git"
},
"devDependencies": {
"@types/dygraphs": "^1.1.8",
"@types/jest": "^21.1.6",
"@types/node": "^8.0.51",
"@types/jquery": "^3.3.4",
"@types/node": "^8.10.18",
"jest": "^21.2.1",
"ts-jest": "^21.2.2",
"ts-md5": "^1.2.2",
"typescript": "^2.6.1"
"ts-node": "^6.1.0",
"typescript": "^2.9.1"
},
"jest": {
"testEnvironment": "node",
......
/*!
* Bootstrap-select v1.12.4 (http://silviomoreto.github.io/bootstrap-select)
*
* Copyright 2013-2017 bootstrap-select
* Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
*/select.bs-select-hidden,select.selectpicker{display:none!important}.bootstrap-select{width:220px\9}.bootstrap-select>.dropdown-toggle{width:100%;padding-right:25px;z-index:1}.bootstrap-select>.dropdown-toggle.bs-placeholder,.bootstrap-select>.dropdown-toggle.bs-placeholder:active,.bootstrap-select>.dropdown-toggle.bs-placeholder:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder:hover{color:#999}.bootstrap-select>select{position:absolute!important;bottom:0;left:50%;display:block!important;width:.5px!important;height:100%!important;padding:0!important;opacity:0!important;border:none}.bootstrap-select>select.mobile-device{top:0;left:0;display:block!important;width:100%!important;z-index:2}.error .bootstrap-select .dropdown-toggle,.has-error .bootstrap-select .dropdown-toggle{border-color:#b94a48}.bootstrap-select.fit-width{width:auto!important}.bootstrap-select:not([class*=col-]):not([class*=form-control]):not(.input-group-btn){width:220px}.bootstrap-select .dropdown-toggle:focus{outline:thin dotted #333!important;outline:5px auto -webkit-focus-ring-color!important;outline-offset:-2px}.bootstrap-select.form-control{margin-bottom:0;padding:0;border:none}.bootstrap-select.form-control:not([class*=col-]){width:100%}.bootstrap-select.form-control.input-group-btn{z-index:auto}.bootstrap-select.form-control.input-group-btn:not(:first-child):not(:last-child)>.btn{border-radius:0}.bootstrap-select.btn-group:not(.input-group-btn),.bootstrap-select.btn-group[class*=col-]{float:none;display:inline-block;margin-left:0}.bootstrap-select.btn-group.dropdown-menu-right,.bootstrap-select.btn-group[class*=col-].dropdown-menu-right,.row .bootstrap-select.btn-group[class*=col-].dropdown-menu-right{float:right}.form-group .bootstrap-select.btn-group,.form-horizontal .bootstrap-select.btn-group,.form-inline .bootstrap-select.btn-group{margin-bottom:0}.form-group-lg .bootstrap-select.btn-group.form-control,.form-group-sm .bootstrap-select.btn-group.form-control{padding:0}.form-group-lg .bootstrap-select.btn-group.form-control .dropdown-toggle,.form-group-sm .bootstrap-select.btn-group.form-control .dropdown-toggle{height:100%;font-size:inherit;line-height:inherit;border-radius:inherit}.form-inline .bootstrap-select.btn-group .form-control{width:100%}.bootstrap-select.btn-group.disabled,.bootstrap-select.btn-group>.disabled{cursor:not-allowed}.bootstrap-select.btn-group.disabled:focus,.bootstrap-select.btn-group>.disabled:focus{outline:0!important}.bootstrap-select.btn-group.bs-container{position:absolute;height:0!important;padding:0!important}.bootstrap-select.btn-group.bs-container .dropdown-menu{z-index:1060}.bootstrap-select.btn-group .dropdown-toggle .filter-option{display:inline-block;overflow:hidden;width:100%;text-align:left}.bootstrap-select.btn-group .dropdown-toggle .caret{position:absolute;top:50%;right:12px;margin-top:-2px;vertical-align:middle}.bootstrap-select.btn-group[class*=col-] .dropdown-toggle{width:100%}.bootstrap-select.btn-group .dropdown-menu{min-width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .dropdown-menu.inner{position:static;float:none;border:0;padding:0;margin:0;border-radius:0;-webkit-box-shadow:none;box-shadow:none}.bootstrap-select.btn-group .dropdown-menu li{position:relative}.bootstrap-select.btn-group .dropdown-menu li.active small{color:#fff}.bootstrap-select.btn-group .dropdown-menu li.disabled a{cursor:not-allowed}.bootstrap-select.btn-group .dropdown-menu li a{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.bootstrap-select.btn-group .dropdown-menu li a.opt{position:relative;padding-left:2.25em}.bootstrap-select.btn-group .dropdown-menu li a span.check-mark{display:none}.bootstrap-select.btn-group .dropdown-menu li a span.text{display:inline-block}.bootstrap-select.btn-group .dropdown-menu li small{padding-left:.5em}.bootstrap-select.btn-group .dropdown-menu .notify{position:absolute;bottom:5px;width:96%;margin:0 2%;min-height:26px;padding:3px 5px;background:#f5f5f5;border:1px solid #e3e3e3;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05);pointer-events:none;opacity:.9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .no-results{padding:3px;background:#f5f5f5;margin:0 5px;white-space:nowrap}.bootstrap-select.btn-group.fit-width .dropdown-toggle .filter-option{position:static}.bootstrap-select.btn-group.fit-width .dropdown-toggle .caret{position:static;top:auto;margin-top:-1px}.bootstrap-select.btn-group.show-tick .dropdown-menu li.selected a span.check-mark{position:absolute;display:inline-block;right:15px;margin-top:5px}.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text{margin-right:34px}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle{z-index:1061}.bootstrap-select.show-menu-arrow .dropdown-toggle:before{content:'';border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid rgba(204,204,204,.2);position:absolute;bottom:-4px;left:9px;display:none}.bootstrap-select.show-menu-arrow .dropdown-toggle:after{content:'';border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;bottom:-4px;left:10px;display:none}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:before{bottom:auto;top:-3px;border-top:7px solid rgba(204,204,204,.2);border-bottom:0}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:after{bottom:auto;top:-3px;border-top:6px solid #fff;border-bottom:0}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:before{right:12px;left:auto}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:after{right:13px;left:auto}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:after,.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:before{display:block}.bs-actionsbox,.bs-donebutton,.bs-searchbox{padding:4px 8px}.bs-actionsbox{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-actionsbox .btn-group button{width:50%}.bs-donebutton{float:left;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-donebutton .btn-group button{width:100%}.bs-searchbox+.bs-actionsbox{padding:0 8px 4px}.bs-searchbox .form-control{margin-bottom:0;width:100%;float:none}
\ No newline at end of file
This diff is collapsed.
.hljs{display:block;overflow-x:auto;padding:0.5em;color:#333;background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:bold}.hljs-number,.hljs-literal,.hljs-variable,.hljs-template-variable,.hljs-tag .hljs-attr{color:#008080}.hljs-string,.hljs-doctag{color:#d14}.hljs-title,.hljs-section,.hljs-selector-id{color:#900;font-weight:bold}.hljs-subst{font-weight:normal}.hljs-type,.hljs-class .hljs-title{color:#458;font-weight:bold}.hljs-tag,.hljs-name,.hljs-attribute{color:#000080;font-weight:normal}.hljs-regexp,.hljs-link{color:#009926}.hljs-symbol,.hljs-bullet{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:bold}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.