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 (30)
node_modules
*.map
*.js
coverage
.vscode
package-lock.json
\ No newline at end of file
# This file is a template, and might need editing before it works on your project.
# Full project: https://gitlab.com/pages/plain-html
before_script:
- curl --silent --location https://rpm.nodesource.com/setup_8.x | bash -
- yum -y install nodejs
- npm install -g typescript
- npm install --save @types/jquery
pages:
stage: deploy
script:
- mkdir .public
- tsc --target es2017 start.ts || true
- tsc --target es2017 loaddir.ts || true
# - tsc --target es2017 LoadFile.ts || true
- cp -r * .public
- mv .public public
artifacts:
paths:
- public
only:
- master
......@@ -11,3 +11,19 @@ This application allows to load an image from a remote digital library and to pr
The application is written in typescript.
The dependencies are specified in `package.json` and can simply be installed running `npm install` from the project root directory. The dependencies are installed locally in the `node_modules` subdirectory.
### Reading list
- [Typescript - Javascript that scales](https://www.typescriptlang.org)
- [Creating a TypeScript library with a minimal setup](https://michalzalecki.com/creating-typescript-library-with-a-minimal-setup/)
- [Browserify](http://browserify.org/)
- [Handbook](https://github.com/substack/browserify-handbook)
- [Introduction](http://superbigtree.tumblr.com/post/54873453939/introduction-to-browserify)
- [Webpack](http://webpack.github.io/), an alternative to Browserify
- [Jest - Deligthful JavaScript Testing](https://facebook.github.io/jest/) and [ts-jest](https://github.com/kulshekhar/ts-jest)
- [VS Code - Editing TypeScript](https://code.visualstudio.com/docs/languages/typescript)
\ No newline at end of file
class CallbackManager {
constructor() {
}
public showElement(elementID: string, show: boolean): void {
if (show) {
document.getElementById(elementID).style.display = "inline";
}
else {
document.getElementById(elementID).style.display = "none";
}
}
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 };
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 {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");
lines = content.toString().split('\n');
numbers = lines.map(Number);
});
test("get_metadata", () =>
{
let metadata = filesys.get_metadata(image, numbers);
expect(metadata).toEqual({
xMin: 50088000,
xMax: 50103000,
yMin: 60086000,
yMax: 60111000,
step: 500,
direction: 'c'
});
})
test("readImage", () =>
{
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
})
// Copyright 2017 Istituto Nazionale di Fisica Nucleare
//
// Licensed under the EUPL
import * as $ from "jquery";
import * as Utility from "./utility";
import { Image } from "./image";
import { Chart } from "./chart";
enum ReadDirection {
u,// lettura non definita
r,//lettura per righe
c//lettura per colonne
}
class Fs {
xMin: number = 0;
xMax: number = 0;
yMin: number = 0;
yMax: number = 0;
step: number = 0;
direction: ReadDirection = ReadDirection.u;
constructor() { };
generateTree(xmlDoc: Document) {
let tree: any = [];
let first = true;
let oldFolderParent: string = "";
let oldFolder: string = "";
//inizio leggendo tutti gli elementi da inserire nell'albero (caratterizzati
//dall'avere un url di riferimento)
let entry = $("D:href", xmlDoc);
//per ogni elemento controllo se si tratta di una cartella o di un documento
for (let i: number = 0; i < entry.length; i++) {
let path: string[] = entry[i].childNodes[0].nodeValue.split("");
//cartella, creo l'oggetto corrsipondente
if (path[path.length - 1] == "/") {
let folderName: string[] = entry[i].childNodes[0].nodeValue.split("/");
let Folder = { text: folderName[folderName.length - 2], nodes: [] };
//posiziono la radice del file system, ne memorizzo il path e il padre
if (first) {
tree.push(Folder);
first = false;
oldFolder = entry[i].childNodes[0].nodeValue;
oldFolderParent = oldFolder.slice(0, oldFolder.lastIndexOf(folderName[folderName.length - 2]));
//per ogni cartella determino la relazione con la cartella precedente
} else {
let newFolder: string = entry[i].childNodes[0].nodeValue;
let newFolderParent: string = newFolder.slice(0, newFolder.lastIndexOf(folderName[folderName.length - 2]));
//cartella sorella con quella memorizzata
if (newFolderParent == oldFolderParent) {
oldFolder = newFolder;
this.insertOBJinFS(Folder, tree, folderName, 0);
//cartella figlia di quella memorizzata
} else if (newFolderParent == oldFolder) {
oldFolder = newFolder;
oldFolderParent = newFolderParent;
this.insertOBJinFS(Folder, tree, folderName, 0);
//nessuno dei casi precedenti
} else {
//arretro nell'albero fino a trovare lo stesso padre. Per fare questo
//tolgo al padre memorizzato in precedenza prima "/" poi il nome dell'
//ultima cartella
while (newFolderParent != oldFolderParent) {
oldFolderParent = oldFolderParent.slice(0, oldFolderParent.length - 1);
oldFolderParent = oldFolderParent.slice(0, oldFolderParent.lastIndexOf("/") + 1);
}
oldFolder = newFolder;
this.insertOBJinFS(Folder, tree, folderName, 0);
}
}
//documento, creo l'oggetto corrispondente e lo inserisco nell'albero
} else {
let fileName: string[] = entry[i].childNodes[0].nodeValue.split("/");
let filePath: string = entry[i].childNodes[0].nodeValue;
let File = {
text: fileName[fileName.length - 1], icon: "glyphicon glyphicon-file", selectedIcon: "glyphicon glyphicon-file", url: filePath
};
this.insertOBJinFS(File, tree, fileName, 1);
}
}
return tree;
}
//funzione che posiziona l'oggetto passato in input nell'albero
private insertOBJinFS(objfs, tree, objfsName, type) {
//determino la profondità dell'oggetto (se è un file devo aggiungere 1 a causa di "/")
let depth: number = objfsName.length;
if (type) depth++;
//in base alla profondità determino a quale oggetto agganciare quello in input
let treePosition: any;
let l: number = tree.length - 1;
switch (depth) {
case 6:
treePosition = tree;
break;
case 7:
treePosition = tree[l].nodes;
break;
case 8:
treePosition = tree[l].nodes[tree[l].nodes.length - 1].nodes;
break;
case 9:
treePosition = tree[l].nodes[tree[l].nodes.length - 1].nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes.length - 1].nodes;
break;
case 10:
treePosition = tree[l].nodes[tree[l].nodes.length - 1].nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes.length - 1]
.nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes.length - 1].nodes.length - 1].nodes;
break;
default:
break;
}
treePosition[treePosition.length - 1].nodes.push(objfs);
}
//funzione che dato l'url di un file, lo apre e lo legge passandone il contenuto
//alla funzione readData(). Questa funzione è invocata quando viene selezionato
//un file dall'albero
openFileFromServer(url) {
let fileName: string[] = url.split("/");
console.log("Try to open " + fileName[fileName.length - 1] + " ...");
let txtFile: any = new XMLHttpRequest();
txtFile.open("GET", url, true);
txtFile.onreadystatechange = function () {
if (txtFile.readyState === 4) {
if (txtFile.status === 200) {
this.readImage(txtFile.responseText);
}
}
};
txtFile.send(null);
}
// version working on an array of numbers, obtained from the array of string lines
private get_metadata_num(image: Image, lines: number[]): void {
//let image = G.Image.getInstance();
this.xMin = 0;
this.yMin = 0;
this.xMax = 0;
this.yMax = 0;
this.step = 0; //dimensione di un pixel in micorn
this.direction = ReadDirection.u; //direzione di lettura
//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 (let i = 0; i < lines.length; i++) {
if (Utility.isAnXHeader(lines[i], image)) {
if (this.xMin == 0) {
//se sono alla prima intestazione salvo la x e la y
this.xMin = lines[i];
this.yMin = lines[i + 1];
i++;
} else {
//definisco passo e direzione di scansione dalla seconda intestazione
if (lines[i] == this.xMin) {
this.direction = ReadDirection.c;
this.step = Math.abs(this.yMin - lines[i + 1]); // the unary + converts to number
//se sto leggendo per colonne determino this.xMax leggendo dalla fine
for (let j: number = lines.length; j > i; j--) {
//se la riga è "intestazione x" memorizzo this.xMax e lo confronto con this.xMin
if (Utility.isAnXHeader(lines[j], image)) {
this.xMax = lines[j];
if (this.xMax < this.xMin) {
let t: number = this.xMax;
this.xMax = this.xMin;
this.xMin = t;
}
break;
}
}
} else {
this.direction = ReadDirection.r;
this.step = Math.abs(this.xMin - lines[i]); // the unary + converts to number
//se sto leggendo per righe determino this.yMax leggendo dalla fine
for (let j: number = lines.length; j > i; j--) {
//se la riga è "intestazione y" memorizzo this.yMax e lo confronto con this.yMin
if (Utility.isAnYHeader(lines[j], image)) {
this.yMax = lines[j];
if (this.yMax < this.yMin) {
let t: number = this.yMax;
this.yMax = this.yMin;
this.yMin = t;
}
break;
}
}
}
break;
}
}
}
//A seconda della direzione di lettura determino o this.yMin e this.yMax, o this.xMin e this.xMax
for (let i: number = 2; i < lines.length; i++) {
if (this.direction == ReadDirection.c) {
//se leggo per colonne devo deterinare this.yMin e this.yMax
//mi soffermo sulle righe "intestazione y"
if (Utility.isAnYHeader(lines[i], image)) {
if (this.yMin > lines[i]) {
this.yMin = lines[i];
}
if (this.yMax < lines[i]) {
this.yMax = lines[i];
}
}
//alla terza colonna posso uscire perché ho già tutte le informazioni
if (lines[i] == this.xMin + this.step * 2) {
break;
}
} else {
//se leggo per righe devo deterinare this.xMin e this.xMax
//mi soffermo sulle righe "intestazione x"
if (Utility.isAnXHeader(lines[i], image)) {
if (this.xMin > lines[i]) {
this.xMin = lines[i];
}
if (this.xMax < lines[i]) {
this.xMax = lines[i];
}
}
//alla terza colonna posso uscire perché ho già tutte le informazioni
if (lines[i] == this.yMin + 2000) {
break;
}
}
}
}
get_metadata(image: Image, lines: number[]): void {
try {
this.get_metadata_num(image, lines);
}
catch (e) {
throw new Error(e);
}
}
// La funzione readImage() 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.
readImage(image: Image, chart: Chart, content: any): Image {
let lines = content.split("\n").map(Number);
this.get_metadata(image, lines);
// Risolvo gli shift
for (let i = 0; i < lines.length; i++) {
if (Utility.isAnXHeader(lines[i], image)) {
// this is an x-coordinate
if (this.direction == ReadDirection.c && (lines[i] / 1000) % 2 != 0) {
// increment the y-coordinate of odd columns
lines[i + 1] += this.step;
} else if (this.direction == ReadDirection.r && (lines[i + 1] / 1000) % 2 != 0) {
// increment the x-coordinate of even rows
lines[i] += this.step;
}
}
}
//Definisco le dimensioni della matrice DataMatrix e la inizializzo
let xDim: number;
let yDim: number;
if (this.direction == ReadDirection.c) {
xDim = (this.xMax - this.xMin) / this.step + 1;
yDim = (this.yMax - this.yMin) / this.step - 2;
} else {
xDim = (this.xMax - this.xMin) / this.step - 2;
yDim = (this.yMax - this.yMin) / this.step + 1;
}
image.width = xDim;
image.height = yDim;
image.DataMatrix = new Array(xDim);
for (let i: number = 0; i < xDim; i++) {
image.DataMatrix[i] = new Array(yDim);
for (let j: number = 0; j < yDim; j++) {
image.DataMatrix[i][j] = new Array(image.depth);
for (let k: number = 0; k < image.depth; k++) {
image.DataMatrix[i][j][k] = 0;
}
}
}
//riempio la matrice DataMatrix eliminando i bordi
let x: number, y: number;
let write: boolean;
for (let i = 0; i < lines.length; i++) {
//riga "intestazione x": memorizzo le x e le y del punto e avanzo al conteggio
if (Utility.isAnXHeader(lines[i], image)) {
x = lines[i] - this.xMin;
y = lines[i + 1] - this.yMin;
if (x != 0) {
x /= this.step;
}
if (y != 0) {
y /= this.step;
}
i++;
//non è un pixel del bordo e sto leggendo per colonne: i successivi valori
//sono da considerare
if (this.direction == ReadDirection.c && y != 0 && y != 1 && y != (this.yMax - this.yMin) / this.step &&
y != (this.yMax - this.yMin) / this.step + 1) {
write = true;
y -= 2; //aggiorno la y con i bordi tagliati
} else if (
this.direction == ReadDirection.r && x != 0 && x != 1 && x != (this.xMax - this.xMin) / this.step &&
x != (this.xMax - this.xMin) / this.step + 1) {
//non è un pixel del bordo e sto leggendo per righe: i successivi valori
//sono da considerare
write = true;
x -= 2; //aggiorno la x con i bordi tagliati
} else {
//pixel del bordo: i valori successivi sono da ignorare
write = false;
}
//conteggio da considerare (non del bordo)
} else if (lines[i] < image.headerSetValue && write == true) {
image.DataMatrix[xDim - x - 1][yDim - y - 1][lines[i]] += 1;
}
}
//console.log(image.DataMatrix);
image.nOfCounts = new Array(xDim);
for (let i: number = 0; i < xDim; i++) {
image.nOfCounts[i] = new Array(yDim);
for (let j: number = 0; j < yDim; j++) {
image.nOfCounts[i][j] = Utility.sumVect(image.DataMatrix[i][j], 0, image.DataMatrix[i][j].length);
}
}
//console.log(image.nOfCounts);
image.maxAbsolute = Utility.findMax(image.nOfCounts, { x: 0, y: 0 }, { x: xDim - 1, y: yDim - 1 });
Utility.setDataForCompleteChart(image, chart);
return image;
}
}
export { Fs }
\ No newline at end of file
interface coordinates
{
xp: number;
yp: number;
}
let a: number = 3.36275; //costante moltiplicativa per la calibrazione
let b: number = 58.2353; //costante additiva per la calibrazione
let pixelDim: number; //dimensione dei pixel responsive
let maxAbsolute: number; //massimo conteggio della matrice nOfCounts
// number of pixels in the two dimensions
let xDim: number = 0;
let yDim: number = 0;
let DataMatrix: number[][][], nOfCounts: number[][]; //matrici con i dati
let rePrint: boolean = false; //variabile per ricolorare con il max relativo
let newOrigin: coordinates; //nuovo origine nel caso di zoom
let zPixel1: coordinates; //pixel1 dello zoom
let zPixel2: coordinates; //pixel2 dello zoom
let dataCompleteChart: string = "Channel,Counts\n";
let dataCompleteChartCalibrated: string = "Energy,Counts\n";
let calibrated: boolean = false; //variabile per il controllo sulla calibrazione
let depth: number = 8000; //profondità massima della matrice
let channelDepth: number = round3(((depth + 1) * a - b) / 1000); //profondità massima in canali
let globalxMinRange: number = 0, globalxMaxRange: number = channelDepth;
// round to the 3rd decimal digit
function round3(val: number)
{
return (Math.round(val * Math.pow(10, 3)) / Math.pow(10, 3));
}
// sum the elements of the array in the range [from, to]
function sumVect(vect: number[], from: number, to: number)
{
let sum: number = 0;
for (let i: number = from; i < to; i++) { sum += vect[i]; }
return sum;
}
// find the max in the sub-matrix specified by the two coordinates
function findMax(matrix: number[][], pixel1: coordinates, pixel2: coordinates)
{
let max = 0;
for (let i = pixel1.xp; i <= pixel2.xp; i++) {
for (let j = pixel1.yp; j <= pixel2.yp; j++) {
if (matrix[i][j] > max) {
max = matrix[i][j];
}
}
}
return max;
}
// prepara i dati per il grafico completo
function setDataForCompleteChart()
{
// per ogni pixel sommo i conteggi di tutti i canali rilevati
let dataForChart: number[] = new Array(depth);
for (let i = 0; i < depth; i++) {
dataForChart[i] = 0;
}
for (let i = 0; i < xDim; i++) {
for (let j = 0; j < yDim; j++) {
for (let k = 0; k < depth; k++) {
dataForChart[k] += DataMatrix[i][j][k];
}
}
}
// riempio le stringhe con i dati per il grafico
for (let i = 0; i < depth; i++) {
dataCompleteChart += (i + 1) + "," + dataForChart[i] + "\n";
dataCompleteChartCalibrated += round3(((i + 1) * a - b) / 1000) + "," + dataForChart[i] + "\n";
}
}
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,12 +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/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>
......@@ -48,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>
......@@ -70,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>
......@@ -90,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>
......@@ -98,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>
......@@ -115,9 +121,9 @@
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-content" id="importPanel">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<button id="btnCloseModal" type="button" class="close" data-dismiss="modal">&times;</button>
<h3 class="modal-title">Import File</h3>
</div>
<div class="modal-body">
......@@ -147,8 +153,8 @@
<h2>XRF Image</h2>
<!-- canvas -->
<div style="position: relative; height=400px;">
<canvas id="selectionCanvas" height="400px" width="360px" onmousedown="findPosDown(event);" onmouseup="findPosUp(event);"></canvas>
<div style="position: relative; height: 400px;">
<canvas id="selectionCanvas" height="400px" width="360px"></canvas>
<canvas id="myCanvas" height="400px" width="360px"></canvas>
</div>
<!-- ./canvas -->
......@@ -242,18 +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="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="loaddir.js"></script>
<script type="text/javascript" src="start.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>
<!-- ./Librerie -->
<!-- /.collapsable-page -->
</body>
</html>
"use strict";
// Copyright 2017 Istituto Nazionale di Fisica Nucleare
//
// Licensed under the EUPL
exports.__esModule = true;
var $ = require("jquery");
//funzione che definisce tutti gli elementi responsabili dell'apertura di un file.
//Sono definiti quindi l'albero e il bottone per l'importazione da locale
function setImportFile() {
//genero e leggo il contenuto della directory "filesystem"
var xmlDoc;
var xmlListingFile = new XMLHttpRequest();
xmlListingFile.open("PROPFIND", "CHNET/", false);
xmlListingFile.setRequestHeader("Depth", "infinity");
xmlListingFile.onreadystatechange = function () {
if (xmlListingFile.readyState === 4) {
if (xmlListingFile.status === 207) {
var 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
$('#FileTreeview').treeview({ data: generateTree(xmlDoc) });
$('#FileTreeview').on('nodeSelected', function (e, node) {
if (node['url'] != undefined) {
$("#load-spinner").css("display", "inline");
openFileFromServer(node['url']);
}
});
//bottone per l'importazione locale
var fileInputButton = document.getElementById('myImport');
fileInputButton.onchange = function () {
$("#load-spinner").css("display", "inline");
var fileName = fileInputButton.files[0];
var readerObject = new FileReader();
readerObject.readAsBinaryString(fileName);
readerObject.onload = function () {
var fileString = readerObject.result;
readData(fileString);
};
};
}
//funzione che genera automaticamente l'albero
function generateTree(xmlDoc) {
var tree = [];
var first = true;
var oldFolderParent = "";
var oldFolder = "";
//inizio leggendo tutti gli elementi da inserire nell'albero (caratterizzati
//dall'avere un url di riferimento)
var entry = xmlDoc.getElementsByTagName("D:href");
//per ogni elemento controllo se si tratta di una cartella o di un documento
for (var i = 0; i < entry.length; i++) {
var path = entry[i].childNodes[0].nodeValue.split("");
//cartella, creo l'oggetto corrsipondente
if (path[path.length - 1] == "/") {
var folderName = entry[i].childNodes[0].nodeValue.split("/");
var Folder = {
text: folderName[folderName.length - 2],
nodes: []
};
//posiziono la radice del file system, ne memorizzo il path e il padre
if (first) {
tree.push(Folder);
first = false;
oldFolder = entry[i].childNodes[0].nodeValue;
oldFolderParent =
oldFolder.slice(0, oldFolder.lastIndexOf(folderName[folderName.length - 2]));
//per ogni cartella determino la relazione con la cartella precedente
}
else {
var newFolder = entry[i].childNodes[0].nodeValue;
var newFolderParent = newFolder.slice(0, newFolder.lastIndexOf(folderName[folderName.length - 2]));
//cartella sorella con quella memorizzata
if (newFolderParent == oldFolderParent) {
oldFolder = newFolder;
insertOBJinFS(Folder, tree, folderName, 0);
//cartella figlia di quella memorizzata
}
else if (newFolderParent == oldFolder) {
oldFolder = newFolder;
oldFolderParent = newFolderParent;
insertOBJinFS(Folder, tree, folderName, 0);
//nessuno dei casi precedenti
}
else {
//arretro nell'albero fino a trovare lo stesso padre. Per fare questo
//tolgo al padre memorizzato in precedenza prima "/" poi il nome dell'
//ultima cartella
while (newFolderParent != oldFolderParent) {
oldFolderParent = oldFolderParent.slice(0, oldFolderParent.length - 1);
oldFolderParent = oldFolderParent.slice(0, (oldFolderParent.lastIndexOf("/") + 1));
}
oldFolder = newFolder;
insertOBJinFS(Folder, tree, folderName, 0);
}
}
//documento, creo l'oggetto corrispondente e lo inserisco nell'albero
}
else {
var fileName = entry[i].childNodes[0].nodeValue.split("/");
var filePath = entry[i].childNodes[0].nodeValue;
var File = {
text: fileName[fileName.length - 1],
icon: "glyphicon glyphicon-file",
selectedIcon: "glyphicon glyphicon-file",
url: filePath
};
insertOBJinFS(File, tree, fileName, 1);
}
}
return tree;
}
//funzione che posiziona l'oggetto passato in input nell'albero
function insertOBJinFS(objfs, tree, objfsName, type) {
//determino la profondità dell'oggetto (se è un file devo aggiungere 1 a causa di "/")
var depth = objfsName.length;
if (type)
depth++;
//in base alla profondità determino a quale oggetto agganciare quello in input
var treePosition;
var l = tree.length - 1;
switch (depth) {
case 6:
treePosition = tree;
break;
case 7:
treePosition = tree[l].nodes;
break;
case 8:
treePosition =
tree[l].nodes[tree[l].nodes.length - 1].nodes;
break;
case 9:
treePosition =
tree[l].nodes[tree[l].nodes.length - 1].nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes.length - 1].nodes;
break;
case 10:
treePosition =
tree[l].nodes[tree[l].nodes.length - 1].nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes.length - 1].nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes.length - 1].nodes.length - 1].nodes;
break;
default: break;
}
treePosition[treePosition.length - 1].nodes.push(objfs);
}
//funzione che dato l'url di un file, lo apre e lo legge passandone il contenuto
//alla funzione readData(). Questa funzione è invocata quando viene selezionato
//un file dall'albero
function openFileFromServer(url) {
var fileName = url.split("/");
console.log("Try to open " + fileName[fileName.length - 1] + " ...");
var txtFile = new XMLHttpRequest();
txtFile.open("GET", url, true);
txtFile.onreadystatechange = function () {
if (txtFile.readyState === 4) {
if (txtFile.status === 200) {
readData((txtFile.responseText));
}
}
};
txtFile.send(null);
}
// Copyright 2017 Istituto Nazionale di Fisica Nucleare
//
// Licensed under the EUPL
import * as $ from "jquery";
import assert from "assert";
import "./globals";
import * as img from "./draw";
//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
export function setImportFile() {
//genero e leggo il contenuto della directory "filesystem"
let xmlDoc: any;
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: any = 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
$('#FileTreeview').treeview({ data: generateTree(xmlDoc) });
$('#FileTreeview').on('nodeSelected', function (e, node) {
if (node['url'] != undefined) {
$("#load-spinner").css("display", "inline");
openFileFromServer(node['url']);
}
});
//bottone per l'importazione locale
let fileInputButton: any = document.getElementById('myImport');
fileInputButton.onchange = function () {
$("#load-spinner").css("display", "inline");
let fileName: string = fileInputButton.files[0];
let readerObject: any = new FileReader();
readerObject.readAsBinaryString(fileName);
readerObject.onload = function () {
let fileString: string = readerObject.result;
readData(fileString);
}
}
}
//funzione che genera automaticamente l'albero
function generateTree(xmlDoc) {
let tree: any = [];
let first: boolean = true;
let oldFolderParent: string = "";
let oldFolder: string = "";
//inizio leggendo tutti gli elementi da inserire nell'albero (caratterizzati
//dall'avere un url di riferimento)
let entry: string[] = xmlDoc.getElementsByTagName("D:href");
//per ogni elemento controllo se si tratta di una cartella o di un documento
for (let i: number = 0; i < entry.length; i++) {
let path: string[] = entry[i].childNodes[0].nodeValue.split("");
//cartella, creo l'oggetto corrsipondente
if (path[path.length - 1] == "/") {
let folderName: string[] = entry[i].childNodes[0].nodeValue.split("/");
let Folder = {
text: folderName[folderName.length - 2],
nodes: []
}
//posiziono la radice del file system, ne memorizzo il path e il padre
if (first) {
tree.push(Folder);
first = false;
oldFolder = entry[i].childNodes[0].nodeValue;
oldFolderParent =
oldFolder.slice(0, oldFolder.lastIndexOf(folderName[folderName.length - 2]));
//per ogni cartella determino la relazione con la cartella precedente
} else {
let newFolder: string = entry[i].childNodes[0].nodeValue;
let newFolderParent: string =
newFolder.slice(0, newFolder.lastIndexOf(folderName[folderName.length - 2]));
//cartella sorella con quella memorizzata
if (newFolderParent == oldFolderParent) {
oldFolder = newFolder;
insertOBJinFS(Folder, tree, folderName, 0);
//cartella figlia di quella memorizzata
} else if (newFolderParent == oldFolder) {
oldFolder = newFolder;
oldFolderParent = newFolderParent;
insertOBJinFS(Folder, tree, folderName, 0);
//nessuno dei casi precedenti
} else {
//arretro nell'albero fino a trovare lo stesso padre. Per fare questo
//tolgo al padre memorizzato in precedenza prima "/" poi il nome dell'
//ultima cartella
while (newFolderParent != oldFolderParent) {
oldFolderParent = oldFolderParent.slice(0, oldFolderParent.length - 1);
oldFolderParent = oldFolderParent.slice(0, (oldFolderParent.lastIndexOf("/") + 1));
}
oldFolder = newFolder;
insertOBJinFS(Folder, tree, folderName, 0);
}
}
//documento, creo l'oggetto corrispondente e lo inserisco nell'albero
} else {
let fileName: string[] = entry[i].childNodes[0].nodeValue.split("/");
let filePath: string = entry[i].childNodes[0].nodeValue;
let File = {
text: fileName[fileName.length - 1],
icon: "glyphicon glyphicon-file",
selectedIcon: "glyphicon glyphicon-file",
url: filePath
}
insertOBJinFS(File, tree, fileName, 1);
}
}
return tree;
}
//funzione che posiziona l'oggetto passato in input nell'albero
function insertOBJinFS(objfs, tree, objfsName, type) {
//determino la profondità dell'oggetto (se è un file devo aggiungere 1 a causa di "/")
let depth: number = objfsName.length;
if (type) depth++;
//in base alla profondità determino a quale oggetto agganciare quello in input
let treePosition: any;
let l: number = tree.length - 1;
switch (depth) {
case 6: treePosition = tree; break;
case 7: treePosition = tree[l].nodes; break;
case 8: treePosition =
tree[l].nodes[tree[l].nodes.length - 1].nodes; break;
case 9: treePosition =
tree[l].nodes[tree[l].nodes.length - 1].nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes.length - 1].nodes;
break;
case 10: treePosition =
tree[l].nodes[tree[l].nodes.length - 1].nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes.length - 1].nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes.length - 1].nodes.length - 1].nodes;
break;
default: break;
}
treePosition[treePosition.length - 1].nodes.push(objfs);
}
//funzione che dato l'url di un file, lo apre e lo legge passandone il contenuto
//alla funzione readData(). Questa funzione è invocata quando viene selezionato
//un file dall'albero
function openFileFromServer(url) {
let fileName: string[] = url.split("/");
console.log("Try to open " + fileName[fileName.length - 1] + " ...");
let txtFile: any = new XMLHttpRequest();
txtFile.open("GET", url, true);
txtFile.onreadystatechange = function () {
if (txtFile.readyState === 4) {
if (txtFile.status === 200) {
readData((txtFile.responseText));
}
}
}
txtFile.send(null);
}
// 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.
export function readData(fileString: string)
{
let newOrigin = { xp: 0, yp: 0 }; //origine nel caso di zoom
let passo: number = 0; //dimensione di un pixel in micorn
let readMode: string = 'u'; //direzione di lettura
//coordinate minime e massime in entrambe le dimensioni
let xMin: number = 0, yMin: number = 0, xMax: number = 0, yMax: number = 0;
//array con il contenuto del file di input suddiviso per righe
let fileStringArray: any = fileString.split("\n");
//scorro l'array soffermandomi solo sulle righe "intestazione delle x". Devo
//determinare ascisse e cordinate minime e massime, il passo e la direzione di
//scansione
for (let i: number = 0; i < fileStringArray.length; i++) {
if (parseInt(fileStringArray[i]) > 17000 && fileStringArray[i][0] == '5') {
if (xMin == 0) { //se sono alla prima intestazione salvo la x e la y
xMin = parseInt(fileStringArray[i]);
yMin = parseInt(fileStringArray[i + 1]);
i++;
} else { //definisco passo e direzione di scansione dalla seconda intestazione
if (parseInt(fileStringArray[i]) == xMin) {
readMode = 'c';
passo = Math.abs(yMin - fileStringArray[i + 1]);
//se sto leggendo per colonne determino xMax leggendo dalla fine
for (let j: number = fileStringArray.length; j > i; j--) {
//se la riga è "intestazione x" memorizzo xMax e lo confronto con xMin
if (parseInt(fileStringArray[j]) > 17000 && fileStringArray[j][0] == '5') {
xMax = parseInt(fileStringArray[j]);
if (xMax < xMin) { let t: number = xMax; xMax = xMin; xMin = t; }
break;
}
}
} else {
readMode = 'r';
passo = Math.abs(xMin - fileStringArray[i]);
//se sto leggendo per righe determino yMax leggendo dalla fine
for (let j: number = fileStringArray.length; j > i; j--) {
//se la riga è "intestazione y" memorizzo yMax e lo confronto con yMin
if (parseInt(fileStringArray[j]) > 17000 && fileStringArray[j][0] == '6') {
yMax = parseInt(fileStringArray[j]);
if (yMax < yMin) { let t: number = yMax; yMax = yMin; yMin = t; }
break;
}
}
}
break;
}
}
} //alert(xMin + " " + xMax + " " + yMin + " " + yMax + " " + passo);
assert.notEqual(readMode, 'p');
//A seconda della direzione di lettura determino o yMin e yMax, o xMin e xMax
for (let i: number = 2; i < fileStringArray.length; i++) {
if (readMode == 'c') { //se leggo per colonne devo deterinare yMin e yMax
//mi soffermo sulle righe "intestazione y"
if (parseInt(fileStringArray[i]) > 17000 && fileStringArray[i][0] == '6') {
if (yMin > parseInt(fileStringArray[i])) {
yMin = parseInt(fileStringArray[i]);
}
if (yMax < parseInt(fileStringArray[i])) {
yMax = parseInt(fileStringArray[i]);
}
}
//alla terza colonna posso uscire perché ho già tutte le informazioni
if (parseInt(fileStringArray[i]) == xMin + (passo * 2)) { break; }
} else { //se leggo per righe devo deterinare xMin e xMax
//mi soffermo sulle righe "intestazione x"
if (parseInt(fileStringArray[i]) > 17000 && fileStringArray[i][0] == '5') {
if (xMin > parseInt(fileStringArray[i])) {
xMin = parseInt(fileStringArray[i]);
}
if (xMax < parseInt(fileStringArray[i])) {
xMax = parseInt(fileStringArray[i]);
}
}
//alla terza colonna posso uscire perché ho già tutte le informazioni
if (parseInt(fileStringArray[i]) == yMin + 2000) { break; }
}
} //alert(xMin + " " + xMax + " " + yMin + " " + yMax + " " + passo);
//Risolvo gli shift
for (let i: number = 0; i < fileStringArray.length; i++) {
//se leggo per colonne allora aggiungo 1 alle y di tutte le colonne dispari
if (readMode == 'c' && parseInt(fileStringArray[i]) > 17000 &&
fileStringArray[i][0] == '5' && (parseInt(fileStringArray[i]) / 1000) % 2 != 0) {
fileStringArray[i + 1] = (parseInt(fileStringArray[i + 1]) + passo).toString();
}
//se leggo per righe allora aggiungo 1 alle x di tutte le righe dispari
else if (readMode == 'r' && parseInt(fileStringArray[i]) > 17000 &&
fileStringArray[i][0] == '5' && (parseInt(fileStringArray[i + 1]) / 1000) % 2 != 0) {
fileStringArray[i] = (parseInt(fileStringArray[i]) + passo).toString();
}
}
//Definisco le dimensioni della matrice DataMatrix e la inizializzo
if (readMode == 'c') {
xDim = (xMax - xMin) / passo + 1;
yDim = (yMax - yMin) / passo - 2;
} else {
xDim = (xMax - xMin) / passo - 2;
yDim = (yMax - yMin) / passo + 1;
}
//alert(xDim + " " + yDim);
//determino la profondità del problema: mi soffermo solo sui conteggi e tengo
//il massimo
// for(let 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 (let i: number = 0; i < xDim; i++) {
DataMatrix[i] = new Array(yDim);
for (let j: number = 0; j < yDim; j++) {
DataMatrix[i][j] = new Array(depth);
for (let k: number = 0; k < depth; k++) {
DataMatrix[i][j][k] = 0;
}
}
}
//riempio la matrice DataMatrix eliminando i bordi
for (let i: number = 0; i < fileStringArray.length; i++) {
let x: number, y: number;
var write: boolean;
//riga "intestazione x": memorizzo le x e le y del punto e avanzo al conteggio
if (parseInt(fileStringArray[i]) > 17000 && fileStringArray[i][0] == '5') {
x = (parseInt(fileStringArray[i]) - xMin);
y = (parseInt(fileStringArray[i + 1]) - yMin);
if (x != 0) { x /= passo; }
if (y != 0) { y /= passo; }
i++;
//non è un pixel del bordo e sto leggendo per colonne: i successivi valori
//sono da considerare
if (readMode == 'c' && y != 0 && y != 1 && y != (yMax - yMin) / passo &&
y != (yMax - yMin) / passo + 1) {
write = true;
y -= 2; //aggiorno la y con i bordi tagliati
}
//non è un pixel del bordo e sto leggendo per righe: i successivi valori
//sono da considerare
else if (readMode == 'r' && x != 0 && x != 1 && x != (xMax - xMin) / passo &&
x != (xMax - xMin) / passo + 1) {
write = true;
x -= 2; //aggiorno la x con i bordi tagliati
}
//pixel del bordo: i valori successivi sono da ignorare
else { write = false; }
//conteggio da considerare (non del bordo)
} else if (parseInt(fileStringArray[i]) < 17000 && write == true) {
//inserisco il conteggio nella matrice (occhio all'orientamento)
DataMatrix[xDim - x - 1][yDim - y - 1][parseInt(fileStringArray[i])] += 1;
}
}
//calcolo il numero di conteggi per pixel e li salvo nella matrice nOfCounts
nOfCounts = new Array(xDim);
for (let i: number = 0; i < xDim; i++) {
nOfCounts[i] = new Array(yDim);
for (let j: number = 0; j < yDim; j++) {
nOfCounts[i][j] = sumVect(DataMatrix[i][j], 0, DataMatrix[i][j].length);
}
}
//calcolo il conteggio massimo della matrice
maxAbsolute = findMax(nOfCounts, { xp: 0, yp: 0 }, { xp: xDim - 1, yp: yDim - 1 });
//definisco i dati per il grafico completo
setDataForCompleteChart();
console.log("File open with succes");
img.drawImg({ xp: 0, yp: 0 }, { xp: xDim - 1, yp: yDim - 1 }, 0, channelDepth);
img.drawChart({ xp: 0, yp: 0 }, { xp: xDim - 1, yp: yDim - 1 }, 0, channelDepth);
$("#load-spinner").css("display", "none");
}
This diff is collapsed.
{
"name": "chnet-xrf",
"version": "0.1.0",
"scripts": {
"test": "jest"
},
"dependencies": {
"jquery": "^3.2.1",
"assert": "latest",
"bootstrap": "v3.3.7",
"bootstrap-select": "^1.12.4",
"bootstrap-slider": "^10.0.0",
"bootstrap-tooltip": "^3.1.1",
"dygraphs": "^2.0.0",
"assert": "latest"
"jquery": "^3.3.1"
},
"description": "Web application to analyse XRF images",
"license": "EUPL",
"repository": {
"url": "https://baltig.infn.it/chnet/XRF-App"
"type": "git",
"url": "https://baltig.infn.it/chnet/XRF-App.git"
},
"devDependencies": {
"@types/dygraphs": "^1.1.8",
"@types/jest": "^21.1.6",
"@types/jquery": "^3.3.4",
"@types/node": "^8.10.18",
"jest": "^21.2.1",
"ts-jest": "^21.2.2",
"ts-md5": "^1.2.2",
"ts-node": "^6.1.0",
"typescript": "^2.9.1"
},
"jest": {
"testEnvironment": "node",
"transform": {
"^.+\\.ts?$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},
"testRegex": "^.+\\.test\\.ts$",
"moduleFileExtensions": [
"ts",
"js"
]
}
}
/*!
* 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.