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 (122)
Showing
with 2323740 additions and 1779 deletions
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
pages:
stage: deploy
script:
- mkdir .public
- cp -r * .public
- mv .public public
artifacts:
paths:
- public
only:
- master
Digilab2.png

3.23 MiB

EUROPEAN UNION PUBLIC LICENCE v. 1.2
EUPL © the European Union 2007, 2016
This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined below) which is provided under the
terms of this Licence. Any use of the Work, other than as authorised under this Licence is prohibited (to the extent such
use is covered by a right of the copyright holder of the Work).
The Work is provided under the terms of this Licence when the Licensor (as defined below) has placed the following
notice immediately following the copyright notice for the Work:
Licensed under the EUPL
or has expressed by any other means his willingness to license under the EUPL.
1.Definitions
In this Licence, the following terms have the following meaning:
— ‘The Licence’:this Licence.
— ‘The Original Work’:the work or software distributed or communicated by the Licensor under this Licence, available
as Source Code and also as Executable Code as the case may be.
— ‘Derivative Works’:the works or software that could be created by the Licensee, based upon the Original Work or
modifications thereof. This Licence does not define the extent of modification or dependence on the Original Work
required in order to classify a work as a Derivative Work; this extent is determined by copyright law applicable in
the country mentioned in Article 15.
— ‘The Work’:the Original Work or its Derivative Works.
— ‘The Source Code’:the human-readable form of the Work which is the most convenient for people to study and
modify.
— ‘The Executable Code’:any code which has generally been compiled and which is meant to be interpreted by
a computer as a program.
— ‘The Licensor’:the natural or legal person that distributes or communicates the Work under the Licence.
— ‘Contributor(s)’:any natural or legal person who modifies the Work under the Licence, or otherwise contributes to
the creation of a Derivative Work.
— ‘The Licensee’ or ‘You’:any natural or legal person who makes any usage of the Work under the terms of the
Licence.
— ‘Distribution’ or ‘Communication’:any act of selling, giving, lending, renting, distributing, communicating,
transmitting, or otherwise making available, online or offline, copies of the Work or providing access to its essential
functionalities at the disposal of any other natural or legal person.
2.Scope of the rights granted by the Licence
The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, sublicensable licence to do the following, for
the duration of copyright vested in the Original Work:
— use the Work in any circumstance and for all usage,
— reproduce the Work,
— modify the Work, and make Derivative Works based upon the Work,
— communicate to the public, including the right to make available or display the Work or copies thereof to the public
and perform publicly, as the case may be, the Work,
— distribute the Work or copies thereof,
— lend and rent the Work or copies thereof,
— sublicense rights in the Work or copies thereof.
Those rights can be exercised on any media, supports and formats, whether now known or later invented, as far as the
applicable law permits so.
In the countries where moral rights apply, the Licensor waives his right to exercise his moral right to the extent allowed
by law in order to make effective the licence of the economic rights here above listed.
The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to any patents held by the Licensor, to the
extent necessary to make use of the rights granted on the Work under this Licence.
3.Communication of the Source Code
The Licensor may provide the Work either in its Source Code form, or as Executable Code. If the Work is provided as
Executable Code, the Licensor provides in addition a machine-readable copy of the Source Code of the Work along with
each copy of the Work that the Licensor distributes or indicates, in a notice following the copyright notice attached to
the Work, a repository where the Source Code is easily and freely accessible for as long as the Licensor continues to
distribute or communicate the Work.
4.Limitations on copyright
Nothing in this Licence is intended to deprive the Licensee of the benefits from any exception or limitation to the
exclusive rights of the rights owners in the Work, of the exhaustion of those rights or of other applicable limitations
thereto.
5.Obligations of the Licensee
The grant of the rights mentioned above is subject to some restrictions and obligations imposed on the Licensee. Those
obligations are the following:
Attribution right: The Licensee shall keep intact all copyright, patent or trademarks notices and all notices that refer to
the Licence and to the disclaimer of warranties. The Licensee must include a copy of such notices and a copy of the
Licence with every copy of the Work he/she distributes or communicates. The Licensee must cause any Derivative Work
to carry prominent notices stating that the Work has been modified and the date of modification.
Copyleft clause: If the Licensee distributes or communicates copies of the Original Works or Derivative Works, this
Distribution or Communication will be done under the terms of this Licence or of a later version of this Licence unless
the Original Work is expressly distributed only under this version of the Licence — for example by communicating
‘EUPL v. 1.2 only’. The Licensee (becoming Licensor) cannot offer or impose any additional terms or conditions on the
Work or Derivative Work that alter or restrict the terms of the Licence.
Compatibility clause: If the Licensee Distributes or Communicates Derivative Works or copies thereof based upon both
the Work and another work licensed under a Compatible Licence, this Distribution or Communication can be done
under the terms of this Compatible Licence. For the sake of this clause, ‘Compatible Licence’ refers to the licences listed
in the appendix attached to this Licence. Should the Licensee's obligations under the Compatible Licence conflict with
his/her obligations under this Licence, the obligations of the Compatible Licence shall prevail.
Provision of Source Code: When distributing or communicating copies of the Work, the Licensee will provide
a machine-readable copy of the Source Code or indicate a repository where this Source will be easily and freely available
for as long as the Licensee continues to distribute or communicate the Work.
Legal Protection: This Licence does not grant permission to use the trade names, trademarks, service marks, or names
of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and
reproducing the content of the copyright notice.
6.Chain of Authorship
The original Licensor warrants that the copyright in the Original Work granted hereunder is owned by him/her or
licensed to him/her and that he/she has the power and authority to grant the Licence.
Each Contributor warrants that the copyright in the modifications he/she brings to the Work are owned by him/her or
licensed to him/her and that he/she has the power and authority to grant the Licence.
Each time You accept the Licence, the original Licensor and subsequent Contributors grant You a licence to their contributions
to the Work, under the terms of this Licence.
7.Disclaimer of Warranty
The Work is a work in progress, which is continuously improved by numerous Contributors. It is not a finished work
and may therefore contain defects or ‘bugs’ inherent to this type of development.
For the above reason, the Work is provided under the Licence on an ‘as is’ basis and without warranties of any kind
concerning the Work, including without limitation merchantability, fitness for a particular purpose, absence of defects or
errors, accuracy, non-infringement of intellectual property rights other than copyright as stated in Article 6 of this
Licence.
This disclaimer of warranty is an essential part of the Licence and a condition for the grant of any rights to the Work.
8.Disclaimer of Liability
Except in the cases of wilful misconduct or damages directly caused to natural persons, the Licensor will in no event be
liable for any direct or indirect, material or moral, damages of any kind, arising out of the Licence or of the use of the
Work, including without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, loss
of data or any commercial damage, even if the Licensor has been advised of the possibility of such damage. However,
the Licensor will be liable under statutory product liability laws as far such laws apply to the Work.
9.Additional agreements
While distributing the Work, You may choose to conclude an additional agreement, defining obligations or services
consistent with this Licence. However, if accepting obligations, You may act only on your own behalf and on your sole
responsibility, not on behalf of the original Licensor or any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against such Contributor by
the fact You have accepted any warranty or additional liability.
10.Acceptance of the Licence
The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ placed under the bottom of a window
displaying the text of this Licence or by affirming consent in any other similar way, in accordance with the rules of
applicable law. Clicking on that icon indicates your clear and irrevocable acceptance of this Licence and all of its terms
and conditions.
Similarly, you irrevocably accept this Licence and all of its terms and conditions by exercising any rights granted to You
by Article 2 of this Licence, such as the use of the Work, the creation by You of a Derivative Work or the Distribution
or Communication by You of the Work or copies thereof.
11.Information to the public
In case of any Distribution or Communication of the Work by means of electronic communication by You (for example,
by offering to download the Work from a remote location) the distribution channel or media (for example, a website)
must at least provide to the public the information requested by the applicable law regarding the Licensor, the Licence
and the way it may be accessible, concluded, stored and reproduced by the Licensee.
12.Termination of the Licence
The Licence and the rights granted hereunder will terminate automatically upon any breach by the Licensee of the terms
of the Licence.
Such a termination will not terminate the licences of any person who has received the Work from the Licensee under
the Licence, provided such persons remain in full compliance with the Licence.
13.Miscellaneous
Without prejudice of Article 9 above, the Licence represents the complete agreement between the Parties as to the
Work.
If any provision of the Licence is invalid or unenforceable under applicable law, this will not affect the validity or
enforceability of the Licence as a whole. Such provision will be construed or reformed so as necessary to make it valid
and enforceable.
The European Commission may publish other linguistic versions or new versions of this Licence or updated versions of
the Appendix, so far this is required and reasonable, without reducing the scope of the rights granted by the Licence.
New versions of the Licence will be published with a unique version number.
All linguistic versions of this Licence, approved by the European Commission, have identical value. Parties can take
advantage of the linguistic version of their choice.
14.Jurisdiction
Without prejudice to specific agreement between parties,
— any litigation resulting from the interpretation of this License, arising between the European Union institutions,
bodies, offices or agencies, as a Licensor, and any Licensee, will be subject to the jurisdiction of the Court of Justice
of the European Union, as laid down in article 272 of the Treaty on the Functioning of the European Union,
— any litigation arising between other parties and resulting from the interpretation of this License, will be subject to
the exclusive jurisdiction of the competent court where the Licensor resides or conducts its primary business.
15.Applicable Law
Without prejudice to specific agreement between parties,
— this Licence shall be governed by the law of the European Union Member State where the Licensor has his seat,
resides or has his registered office,
— this licence shall be governed by Belgian law if the Licensor has no seat, residence or registered office inside
a European Union Member State.
Appendix
‘Compatible Licences’ according to Article 5 EUPL are:
— GNU General Public License (GPL) v. 2, v. 3
— GNU Affero General Public License (AGPL) v. 3
— Open Software License (OSL) v. 2.1, v. 3.0
— Eclipse Public License (EPL) v. 1.0
— CeCILL v. 2.0, v. 2.1
— Mozilla Public Licence (MPL) v. 2
— GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
— Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for works other than software
— European Union Public Licence (EUPL) v. 1.1, v. 1.2
— Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong Reciprocity (LiLiQ-R+).
The European Commission may update this Appendix to later versions of the above licences without producing
a new version of the EUPL, as long as they provide the rights granted in Article 2 of this Licence and protect the
covered Source Code from exclusive appropriation.
All other changes or additions to this Appendix require the production of a new EUPL version.
LICENZA PUBBLICA DELL'UNIONE EUROPEA v. 1.2
EUPL © Unione europea 2007, 2016
La presente Licenza Pubblica dell'Unione europea («EUPL») si applica a tutte le opere, come definite di seguito, fornite alle condizioni di cui alla presente licenza. È vietata l'utilizzazione dell'opera in forme diverse da quelle autorizzate dalla presente licenza (nella misura in cui tale utilizzazione sia riservata in via esclusiva al titolare dei diritti d'autore sull'opera). L'opera è fornita alle condizioni della presente licenza se il licenziante (come definito di seguito) ha posto la seguente dicitura immediatamente dopo l'avviso sui diritti d'autore sull'opera:
Concesso in licenza a norma dell'EUPL
o ha espresso con qualunque altro mezzo la propria volontà di cederla in licenza alle condizioni dell'EUPL.
1 Definizioni
Nella presente licenza i seguenti termini sono così definiti:
— Licenza: la presente licenza.
— Opera originaria: l'opera o il software distribuiti o comunicati dal licenziante alle condizioni della presente licenza, disponibile sotto forma di codice sorgente e, a seconda dei casi, anche sotto forma di codice eseguibile.
— Opere derivate: le opere o il software che possono essere creati dal licenziatario sulla base dell'opera originaria o di una sua modificazione. La presente licenza non definisce quale grado di modificazione o di dipendenza rispetto all'opera originaria sia prescritto per caratterizzare un'opera come opera derivata; tale questione è disciplinata dalla legge sul diritto d'autore applicabile nel paese indicato all'articolo 15.
— Opera: l'opera originaria o le opere da essa derivate.
— Codice sorgente: forma leggibile dell'opera che risulta la più appropriata per essere studiata e modificata dall'uomo.
— Codice eseguibile: il codice che in genere è stato compilato e che è destinato a essere eseguito come programma da un computer.
— Licenziante: la persona fisica o giuridica che distribuisce o comunica l'opera secondo i termini della licenza. — Contributore/i:la persona fisica o giuridica che modifica l'opera secondo i termini della licenza o altrimenti contribuisce alla creazione di un'opera derivata.
— Licenziatario :la persona fisica o giuridica che fa uso del programma secondo i termini della licenza.
— Distribuzione o comunicazione: la vendita, la cessione a titolo gratuito, il prestito, la locazione, la distribuzione, la comunicazione, la trasmissione o qualsiasi altro atto finalizzato a mettere copie dell'opera a disposizione di altre persone fisiche o giuridiche, o fornire loro accesso alle sue funzionalità essenziali, online o offline.
2 Estensione dei diritti concessi dalla licenza
Il licenziante concede al licenziatario, per tutta la durata del diritto d'autore sull'opera originaria, una licenza mondiale, gratuita, non esclusiva, a sua volta cedibile in sublicenza, che conferisce il diritto di compiere gli atti seguenti:
— utilizzare l'opera in qualsiasi circostanza e per ogni utilizzo,
— riprodurre l'opera,
— modificare l'opera e creare opere derivate basate su di essa,
— comunicare al pubblico, anche mediante messa a disposizione o esposizione dell'opera o di copie della stessa e, a seconda dei casi, rappresentare l'opera in forma pubblica,
— distribuire l'opera o copie della stessa,
— cedere in prestito e in locazione l'opera o copie della stessa,
— concedere in sublicenza i diritti sull'opera o copie della stessa.
I diritti suddetti possono essere esercitati con qualsiasi mezzo di comunicazione, su qualsiasi supporto e in qualsiasi formato, attualmente noto o che sarà successivamente inventato, nella misura consentita dal diritto applicabile. Nei paesi in cui si applicano i diritti morali di autore, il licenziante rinuncia al diritto di esercitare i suoi diritti morali nella misura consentita dalla legge affinché la cessione in licenza dei diritti patrimoniali sopra indicati possa produrre tutti i suoi effetti. Il licenziante concede al licenziatario, a titolo gratuito e non esclusivo, il diritto di utilizzare qualsiasi brevetto detenuto dal licenziante, nella misura necessaria all'esercizio dei diritti di utilizzazione dell'opera concessi dalla presente licenza.
3 Comunicazione del codice sorgente
Il licenziante può fornire l'opera o sotto forma di codice sorgente o come codice eseguibile. Se l'opera è fornita come codice eseguibile, il licenziante fornisce, in aggiunta, una copia leggibile dall'elaboratore del codice sorgente dell'opera a corredo di ogni copia dell'opera da lui distribuita oppure indica, in un avviso che segue l'avviso sui diritti d'autore apposto sull'opera, un archivio in cui il codice sorgente è facilmente e gratuitamente accessibile per tutto il periodo in cui il licenziante distribuisce o comunica l'opera.
4 Limitazioni del diritto d'autore
Nessuna clausola della presente licenza è finalizzata a impedire al licenziatario di beneficiare di tutte le eccezioni o limitazioni applicabili ai diritti esclusivi dei titolari dei diritti sull'opera, dell'esaurimento di tali diritti o di qualsiasi altra limitazione applicabile.
5 Obblighi del licenziatario
La concessione dei diritti sopra indicati è soggetta ad alcune restrizioni e obblighi in capo al licenziatario. Gli obblighi sono i seguenti:
Diritto di attribuzione: il licenziatario lascia intatti tutti gli avvisi relativi ai diritti d'autore, ai brevetti o ai marchi e tutte le indicazioni che fanno riferimento alla licenza e all'esclusione della garanzia. Ogni copia dell'opera che il licenziatario distribuisce o comunica deve essere corredata di una copia di tali avvisi e di una copia della licenza. Su tutte le opere derivate il licenziatario deve apporre o far apporre avvisi ben visibili indicanti che l'opera è stata modificata e la data della modificazione.
Clausola «copyleft»: se il licenziatario distribuisce o comunica copie delle opere originarie o delle opere derivate, la distribuzione o comunicazione ha luogo nell'osservanza delle clausole della presente licenza o di una sua versione successiva a meno che l'opera originaria venga esplicitamente distribuita solo nel quadro della presente versione della licenza, ad esempio mediante la comunicazione «solo EUPL v. 1.2». Il licenziatario (che in tal caso diventa licenziante) non può offrire né imporre termini o condizioni ulteriori sull'opera o sulle opere derivate che alterino o restringano le condizioni della licenza.
Clausola di compatibilità: se il licenziatario distribuisce o comunica le opere derivate o copie delle opere derivate basate sull'opera e su un'altra opera concessa in licenza secondo le condizioni di una licenza compatibile, la distribuzione o comunicazione può avvenire nell'osservanza delle clausole della licenza compatibile. Ai fini dell'applicazione della presente clausola, l'espressione «licenza compatibile» si riferisce alle licenze enumerate nell'allegato della presente licenza. In caso di conflitto tra gli obblighi del licenziatario a norma della licenza compatibile e i suoi obblighi a norma della presente licenza, prevalgono gli obblighi prescritti dalla licenza compatibile.
Fornitura del codice sorgente: se distribuisce o comunica copie dell'opera, il licenziatario fornirà copia del codice sorgente in formato leggibile dall'elaboratore oppure indicherà un archivio in cui tale codice sorgente è facilmente e liberamente accessibile, per tutto il tempo in cui distribuisce o comunica l'opera.
Tutela dei diritti: la presente licenza non autorizza a fare uso di nomi commerciali, di marchi distintivi di prodotti o servizi o dei nomi dei licenzianti, se non nei limiti necessari ad una utilizzazione ragionevole e conforme agli usi per descrivere l'origine dell'opera e riprodurre il contenuto dell'avviso relativo al diritto d'autore.
6 Autori e contributori
Il licenziante originario garantisce che i diritti d'autore sull'opera originaria concessi a norma della presente licenza sono di sua proprietà ovvero gli sono concessi in licenza e che dispone del diritto e del potere di concedere la licenza. Ciascun contributore garantisce che i diritti d'autore sulle modifiche che egli apporta all'opera sono di sua proprietà o che gli sono concessi in licenza e che dispone del diritto e del potere di concedere la licenza. Ogni volta che il licenziatario accetta la licenza, il licenziante originario e i contributori successivi concedono al licenziatario una licenza sui loro contributi all'opera, secondo le condizioni della presente licenza.
7 Esclusione della garanzia
L'opera è un'opera in divenire, che viene costantemente migliorata grazie all'apporto di diversi contributori. Non si tratta di un'opera finita e può pertanto contenere difetti o errori inerenti a questo tipo di sviluppo. Per tale ragione, l'opera è concessa in licenza «così com'è» e senza garanzie di alcun genere, ivi incluse, tra le altre, quelle relative all'utilizzazione commerciale, all'idoneità a soddisfare una determinata funzione, all'assenza di difetti o errori, all'accuratezza, all'efficacia, alla non violazione di diritti di proprietà intellettuale diversi dal diritto d'autore come indicato all'articolo 6 della presente licenza. La presente esclusione di garanzia costituisce parte integrante della licenza e condizione per la concessione di qualsiasi diritto sull'opera.
8 Esclusione di responsabilità
Salvi i casi di comportamenti dolosi o di danni direttamente arrecati a persone fisiche, in nessun caso il licenziante può essere ritenuto responsabile per i danni, di qualsiasi natura, diretti o indiretti, materiali o morali, derivanti dalla licenza o dall'utilizzazione dell'opera, ivi inclusi, tra gli altri, i danni per perdita di avviamento, interruzione del lavoro, guasto o malfunzionamento del computer, perdita di dati e qualsiasi danno commerciale, anche nel caso in cui il licenziante fosse stato informato che tali danni avrebbero potuto verificarsi. Tuttavia, il licenziante sarà ritenuto responsabile a norma delle leggi sulla responsabilità da prodotto in quanto applicabili all'opera.
9 Altre pattuizioni
All'atto della distribuzione dell'opera, il licenziatario ha facoltà di stipulare pattuizioni aggiuntive, definendo gli obblighi o i servizi compatibili con la presente licenza. Tuttavia, nell'accettare tali obblighi, il licenziatario agisce esclusivamente in nome proprio e sotto propria esclusiva responsabilità, e non in nome del licenziante originario o di qualsiasi altro contributore, e solo subordinatamente all'assunzione dell'impegno a risarcire, difendere e tenere indenne ciascun contributore da eventuali responsabilità o richieste risarcitorie rivolte allo stesso contributore in conseguenza delle garanzie o responsabilità aggiuntive assunte dal licenziatario.
10 Accettazione della licenza Le clausole della presente licenza possono essere accettate cliccando sull'icona «Accetto» posta sotto una finestra che fa apparire il testo della presente licenza o prestando consenso in qualsiasi altro modo simile, conformemente alle disposizioni di legge applicabili. Cliccando su tale icona il licenziatario manifesta la chiara e irrevocabile accettazione della presente licenza e di tutti i suoi termini e condizioni. Analogamente accetta irrevocabilmente la presente licenza e tutti i suoi termini e condizioni esercitando i diritti concessi dall'articolo 2 della presente Licenza, quali l'utilizzazione dell'opera, la creazione di un'opera derivata o la distribuzione o comunicazione dell'opera o di copie della stessa.
11 Informazione del pubblico
Se il licenziatario procede alla distribuzione o comunicazione dell'opera mediante strumenti di comunicazione elettronica (ad esempio, offrendo di scaricare l'opera da un luogo remoto), il canale di distribuzione o i mezzi di comunicazione (ad esempio un sito web) dovranno fornire al pubblico come minimo le informazioni prescritte dalla normativa applicabile in relazione al licenziante, alla licenza e al modo in cui essa può essere resa accessibile, accettata, conservata e riprodotta da parte del licenziatario.
12 Cessazione della licenza
La licenza e i diritti da essa concessi cesseranno automaticamente di avere effetto ove il licenziatario violi una qualsiasi delle condizioni previste dalla licenza. Tale cessazione non comporterà cessazione delle licenze concesse a persone che abbiano ricevuto l'opera dal licenziatario a norma della licenza, sempreché tali persone ottemperino integralmente alle clausole della licenza stessa.
13 Varie
Ferme restando le disposizioni dell'articolo 9, la licenza costituisce l'accordo integrale tra le parti in merito all'opera. Le clausole della licenza che risultino nulle o non possano essere fatte valere in base alla normativa applicabile non incideranno sulla validità o sull'applicabilità della licenza nel suo complesso. Le clausole in questione saranno interpretate o modificate nella misura necessaria a renderle valide e applicabili. La Commissione europea può pubblicare altre versioni linguistiche o nuove versioni della presente licenza o versioni aggiornate dell'Appendice, nella misura in cui ciò sia necessario e ragionevole, senza ridurre la portata dei diritti accordati dalla licenza. Le nuove versioni della licenza saranno pubblicate con un numero di versione univoco. Tutte le versioni linguistiche della presente licenza, approvate dalla Commissione europea, hanno valore identico. Le parti possono utilizzare la versione linguistica di loro scelta.
14 Competenza giurisdizionale
Fatti salvi accordi specifici tra le parti:
— per qualsiasi controversia in ordine all'interpretazione della presente licenza che insorga tra le istituzioni, gli organismi, gli uffici e le agenzie dell'Unione, nella qualità di licenziante, e il licenziatario è competente la Corte di giustizia dell'Unione europea, a norma dell'articolo 272 del trattato sul funzionamento dell'Unione europea;
— per qualsiasi controversia che insorga tra altre parti in ordine all'interpretazione della presente licenza è esclusivamente competente il tribunale del luogo in cui il licenziante risiede o esercita la sua attività principale.
15 Legge applicabile
Fatti salvi accordi specifici tra le parti:
— la presente Licenza è disciplinata dalla legge dello Stato membro dell'Unione europea nel quale il licenziante è stabilito, risiede o ha la propria sede sociale;
— la presente licenza è disciplinata dalla legge belga ove il licenziante non sia stabilito, non risieda o non abbia la propria sede sociale in uno Stato membro dell'Unione europea.
Appendice
«Licenze compatibili» ai sensi dell'articolo 5 EUPL sono le seguenti:
— GNU General Public License (GPL) v. 2, v. 3
— GNU Affero General Public License (AGPL) v. 3
— Open Software License (OSL) v. 2.1, v. 3.0
— Eclipse Public License (EPL) v. 1.0
— CeCILL v. 2.0, v. 2.1
— Mozilla Public Licence (MPL) v. 2
— GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
— Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) per le opere diverse dal software
— European Union Public Licence (EUPL) v. 1.1, v. 1.2
— Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong Reciprocity (LiLiQ-R+).
La Commissione può aggiornare la presente Appendice per tener conto delle versioni più recenti delle licenze summenzionate senza produrre una nuova versione dell'EUPL, purché esse garantiscano i diritti concessi dall'articolo 2 della presente licenza e proteggano il codice sorgente coperto dall'appropriazione esclusiva.
Tutte le altre modifiche o aggiunte a tale Appendice richiedono la produzione di una nuova versione dell'EUPL.
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
Logo-chnet.png

170 KiB

# A web application to process XRF images
XRF-App is a web application for the analysis of XRF images of cultural heritage works.
XRF stands for X-Ray Fluorescence and is a technique that uses X rays to peek at the chemical components used in the manifucturing of the work being scanned.
This application allows to load an image from a remote digital library and to process it directly in the web browser.
## For developers
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 };
default-avatar.png

6.15 KiB

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