Coder Social home page Coder Social logo

salimkanoun / orthanc-tools-js Goto Github PK

View Code? Open in Web Editor NEW
86.0 7.0 37.0 28.6 MB

New web-based version of Orthanc Tools : GUI and high level DICOMs tools based on Orthanc APIs

License: GNU Affero General Public License v3.0

JavaScript 97.80% HTML 0.22% Dockerfile 0.13% SCSS 1.85%

orthanc-tools-js's Introduction

Orthanc Tools JS

License: AGPL v3

Rewriting of Orthanc Tools in React and NodeJS.

Orthanc Tools JS is mainly a React Frontend for the powerfull Orthanc APIs but also include a Backend for authentication purpose, role management and automations.

Warning : Orthanc Tools JS is still in beta version, this software is not release ready

Current Features :

  • Users identifications local and Active directory with definitions of roles (custom rigth access to orthanc Apis)
  • Search ressources in Orthanc
  • Import DICOM file into Orthanc using drag and drop
  • Dicom creation (image or pdf)
  • Batch Anonymizaion
  • Batch Export Local (local, ZIP, AET)
  • Batch Export to Remote endpoints (Orthanc Peers, FTP, SFTP, Webdav)
  • Batch Delete
  • Manual Query and Retrieve
  • Dicom Tag Edition
  • Dicom ressource labelling
  • Automatic Retrieve : Define a list of studies /Series to retrieve and schedule a robot for automatic retrieval
  • CD Burner Management (Epson and Primera)
  • Administration panel : Declaration and echo of AETs, Orthanc Peers, Jobs management

Documentation : https://github.com/salimkanoun/Orthanc-Tools-JS/blob/master/Documentation/Orthanc-Tools-JS-Documentation.pdf

Roadmap :

  • Auto Routing => To Be Restaured
  • Tag collection (in Elastic Search)
  • Prefecthing
  • Remote AET Monitoring

orthanc-tools-js's People

Contributors

beber32 avatar delphinedecap avatar dependabot[bot] avatar exploff avatar juliendavidou avatar leocouderc avatar oxabz avatar salimkanoun avatar tagzk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

orthanc-tools-js's Issues

Problème d'affichage OrthancContent

Lorsqu'on import un patient avec plusieurs Studies avec le module d'import toutes les studies sont affichées. Mais lorsqu'on cherche le patient avec OrthancContent, seul 1 study est affichée.

Taille colonne maximale

Si le patient a un nom tres long
ou si le study description est tres long,
Les tables prennet trop de largeur.

Il faudrait fixer la taille maximal d'une colonne, voir si y a des mode de visualisation d'une cellule qui n'afficherai pas tout (au survol par exemple)

Faudrait definir une solution et l'appliquer à toutes les tables

Bug Overlay

Parfois les Overlay ne repondent pas au click sur les tools et il faut cliquer plusieurs fois pour réussir à les declancer

et dans la console il y a cette erreur qui apprait à l'ouverture d'orthanctoolsjs

index.js:1 Warning: Failed prop type: The prop onHide is marked as required in Overlay, but its value is undefined.

Display Series necessite 2 click sur study

Dans le Content,
Peut etre que le 1er click correpond au focus sur la sous table study et le 2eme click declanche le listener.
Dans ce cas suffirai de passer le listener on click par OnFocus

Table Niveau Series

Composant stateless (pour l'instant)

  • Series Orthanc ID : Champ caché et clé unique (key)
  • Series Description
  • Modality
  • instances (nombre)
  • Serie number (nombre)
  • Colonne action où on mettra le drow down

Sera fill par api
/series/{id}
data dans MainDicomTag

Pagnitation Content Table

Mettre une pagination pour la table du content (la patient + study nested)
On peut avoir potentiellement beaucoup de resultats à ce niveau
Voir Les table query et result de la fonction autoquery ou j'ai utilisé des pagination

DropDown Delete

Dans les tables Patients / Study / Series
Ajouter un entrée "Delete" (voir si un class name danger marche pour le faire en rouge cet item)

Le click sur cet item declanche une requete DELETE sur les apis suivantes :

  • Pour le niveau Patient : /patients/{id}
  • Pour le niveau study : /studies/{id}
  • Pour le niveau serie : /series/{id}

Les DELETE n'ont pas de payload.
Il faut ouvrir la route au niveau du backend avec un reverse proxy DELETE

Le delete est une opération potentiellement longue.
A la fin du delete il faudrait rafraichir les data => faudrait peut etre faire passer un listener onReferesh qui serait défini dans le parent et qui serait éxecuté par la table quand la delete action est finie (donc à la dernière étape de la promise quand on a la réponse d'Orthanc).

Comme ca dans le Search on va pouvoir relancer une requete Search pour rafraichir les données et dans les autres endroits ou on mettra cette table on pourra définir une autre routine de refresh.

Composant Export

Ici on va travailler avec le level series

Quand on va ajouter des ressource au redux on le fera soit au niveau study soit au niveau series.

Quand on ajoute une ressource niveau study il font donc appeler l'API /series/ID?expand d'Orthanc pour avoir les data series

Dans le redux du composant export on stockera tout au niveau series (les info series auront le parent study id ce qui nous permettra de trier lors de l'affichage comme pour le composante delete).

Affichage 2 tables :
Une table study a gauche
Une table series à droite
Table non imbriquée
=> Ca serait bien d'avoir en fait 2 affichage, quand on est sur le tool flotant on a une table imbriquée studies/series avec un boutton remove par ligne
Il y aura un boutton "Open Export Tool" on utilise la main div (en dessous de la nav bar) pour afficher un affichage complet avec 2 table study et series (2 colonnes) (faudra faire une route pour ca)
quand on clique sur study, la table series affiche le series de la study selectionnées.

Dans ces tables on retrouve la possibilité d'enlever une study ou une series.

En dessous de la table il y aura plusieurs boutton d'action pour envoyer la ressource vers une destination (uniquement dans la full view)

  • Un boutton "Download" qui va faire venir les images vers le navigateur
  • Un select de Orthanc Peers avec un boutton "Send to Peer"
  • Un select de Modalities avec un boutton "Send to Modality"
  • Un select de nom de FTP/sFTP avec un boutton "Send to FTP"
  • Un select de nom de WebDav avec un boutton "Send to WebDav"

Les Orthanc Peers et Modalities sont simplement à fectcher d'Orthanc (c'est ce qu'on a déclaré dans le panel d'option), les transferts sont gérés par Orthanc (je te donnerai les routes).
Le FTP/SFTP, Webdav est plus touchy, ils seront déclarés dans le backend, et c'est le backend qui va s'assurer du transfert (il va recupérer les dicom depuis Orthanc et les envoyer vers l'adresse FTP/SFTP/WebDAV grace à un client, il faudra donc aussi un menu dans les options pour déclarer les adresses distantes autorisées)

Dans tous les cas on va envoyer vers les APIs un array de OrthancSeriesID à envoyer

La aussi l'opération est longue, faudra gerer un feedback

Formulaire Ajouter des preset de Dates

Ajouter un menu deroulant avec des preset de dates suivante (dans le form query / search)

  • Today
  • Yesterday
  • Last Week
  • Last Month
  • Last 3 months
  • Last Year

Normalement il suffit de calculer les dates correspondante avec les outils de Javascript
La librairie Moment est déjà dans le projet (https://momentjs.com/) et permet facilement de calculer les delai (cf methode substract)
Voir class Autoquery/Connected_Component/CSVLoader pour un example d'appel de Moment
et injecter les bonnes string dans le state (et les input date devraient s'updater)

Si l'utisateur change l'input date alors il faut faire revenir le select à un "None" par defaut (listener dans les deux sens)

Enlever les HOC

Sortir les composant HOC comme des composant classiques
(Dans repertoire Common Composant)

Sortie des Overlay

Serait il possible de fermer les overlay automatiquement quand ils ont plus le focus ou qcch comme ca.
Ou si la souris est sortie de l'overlay ?

L'idée serait de pas avoir à recliquer sur le boutton pour fermer l'overlay.

SelectAll fonctionne mal

Lorsqu'on séléctionne tout les patients/studies avec le selectAll et qu'on envoie à la deleteList, seul le dernier est réellement envoyé.

Créer Nouvelle section : "Orthanc Content"

Créer une nouvelle section dans OrthancToolsJS au meme titre que Authentification, AutoQuery ou Options
Nécésssite :

  • Declarer un nouveau link dans le nav du haut
  • Créer une nouvelle route dans le routeur React
  • Créer un Root panel pour ce nouveau composant qui va avoir plusieurs sous composant à afficher

Abstraire Formulaire de Recherche

L'affichage du formulaire est le meme entre Query et Search

Seul change :

  • Le titre
  • Les bouttons de soumission (un seul pour formulaire et un par AET pour Query)
  • Le post traitement

Peut etre abstraire le formulaire avec une methode validate qui retournerai le contenu du formulaire (qui correspond au state du formalaire) dans le parent pour etre traité spécifiquement suivant que l'on est dans le search ou query

Table Niveau study

Composant stateless (pour l'instant)
Colonnes :

  • Study Orthanc ID (champ caché, est une clé unique à utiliser comme key)
  • Study Date (fomat date)
  • Study Description
  • Accession Number
  • Colonne action où on mettra notre drop down

sera fill par
/studies/{id} => MainDicomTag

La table series ne se refresh pas après un delete

Après un delete la table serie ne se refresh pas (la serie delete reste visible)
Et si on re delete un delete ca devrait renvoyer une erreur alors que qu'on a popover success "series undefined has been deleted"

Module Orthanc Content

Module Anon

L'import des ressource se fait au niveau study

Design :

2 Tables une table Patient et une table Study
Meme presentation que export full view

Table Patient comporte
Original Name (a fill avec ce qui vient de la ressource)
Original ID (a fill avec ce qui vient de la ressource)
New Name (c'est le nom anonymisé que l'utilisateur va choisir)
New ID (l'id anonymisé que l'utilisateur va choisir)

la table study comporte les element habituel de notre table study (comme dans export full view)

Ici on a besoin de table editable (cf example de code dans auto query composant query)

Les colonnes éditables sont

  • Sur la table patient : New ID et New Name
  • Sur la table Study : Study Description

Quand l'utilisateur clique sur un patient tu refresh la table study pour montrer les study de ce patient.

En dessous de la table les boutons suivant

Un select avec Anonymisation profile : Pour l'instant on va mettre "Full" et "Default"
Un boutton "Anonymize"

Pour chaque study on va envoyer une requete au back.
On va faire une API spéciale sur notre back pour s'implifier l'anonymisation (car c'est assez verbeux de base sur Orthanc).
Ca va etre un truc du genre /studies/ID/anonymize
et dans le payload on va passer
newName :
newID :
newStudyDescription:
anonProfile:

L'API renverra un nouvel Orthanc ID qui correspond à l'ID anonymisé
On fera probablement une deuxieme tab dans cet onglet anonymized ou on mettra les "Anonymized study" qui va etre une interface de visualisation très simple qui te permettra de suivre la progression de l'anonymisation (au fur et a mesure qu'on avance dans les requette on affiche les ressource anonymisés) et c'est via cette interface de visualisation qu'on pourra selectionner et envoyer les ressource aux autres modules.
(je pense qu'on fera les meme table patient / study)
Y aura aussi une fonction pour extraire la clé d'anonymisation un fichier CSV qui aura la correspondance vrai noms et nom anonymisés (sorte de rapport d'anonymisation)

Composant Delete

Composant Delete :

Ouvert au click du composant delete en haut à droite
=> Soit dans un Modal soit dans la div principale

  1. Dans l'action button ajouter un item "Send To Delete List"
  2. Le listener de cet item doit passer par Redux => Formation à voir sur Udemy
  3. Le composant Delete List consomme la liste des ressource à effacer depuis le reducer
  4. L'interface affiche 3 table (non nested) Patients, Studies, Series qui affiche les ressources affichées aux differents niveaux
  5. On fera surement un outil pour voir le detail des Patient et studies (à relechir)
  6. Un button rouge "Delete" avec un message de confirmation pour lancer la suppression des ressources
  7. Les API delete sont celles qu'on connait /niveau/ID methode DELETE.
  8. Deux facons de proceder possible :
  • Faire les appels un à un depuis le frontEnd => Facile mais nécessite que le front reste ouvert pour que la pile s'execute
  • Faire une API sur le backEnd qui accepte une liste de ressource à supprimer, qui va ouvrir un robot delete. Le front requetera le robotDelete pour suivre la progression du Delete => Sexy mais plus lourd à implementer, nécéssite de faire du TDD.

Color Selection Nested table

Le changement pour le composant Patient et Study nested marche mais le probleme est que quand on passe a une study d'un autre patient la couleur du composant patient ne suis pas.

Il faut refactor, la solution est assez simple :

Il faut passer les gestion des click et des couleur des deux tables dans le TablePatientNestedStudy.
et reflechir comment faire communiquer les deux.
La peut etre qu'il faut utiliser la méthode de coloration du parent => a reflechir

Import Progress

Les fails ne sont pas pris en compte dans la progression de l'import

Formulaire de recherche dans Orthanc

Utilise API /tools/find
cf capture
Le menu deroulant contient PatientID/PatientName/Accession Nb
Reutiliser le select modalities déjà présent dans le autoquery pour le selcteur de modalité
Le first name n'est dispo que si PatientName est selectionné dans le menu deroulant.

Ajouter confirmation avant restart et shutdown

Faire une popup quand on clique sur restart et shutdown dans le main option tab.
Ici il y a un composant boostrap pour faire ca.
Regarder cette doc : https://react-bootstrap.github.io/components/modal/#modal-vertically-centered
Le module react bootstrap est déjà installé dans le projet.
Dans l'example de la doc ils utilisent des composant de la libraririe alors que jusqu'ici j'utilisait des balise simple HTLM ou j'ajoutais les className de bootstrap pour avoir la stylisation de Bootstrap.

Essayer de suivre l'exemple de la doc avec leur elements pour voir si ca marche.

Reutilisation des composants Patients / Study / Series dans la tab import

Module d'import des DICOMs fait ici : https://github.com/salimkanoun/Orthanc-Tools-JS/blob/Sylvain/FrontEnd/src/components/Import/Import.js

Il utilise Uppy : https://uppy.io/docs

A chaque Dicom envoyé à Orthanc on recupère l'even 'upload-success' à la ligne 38.
A chaque fois qu'on a envoyé un DICOM à Orthanc, celui ci nous répond les ID de sa series parent, de sa study parente, et de son patient parent. (L'import se fait au niveau instance).

L'idée est de reaficher les table Patient / Study / Serie qu'on utilise dans Orthanc Content pour afficher le resultat de ce qui a été importé.

Pour ceci :
Il faut monitorer les ParentPatient de chaque Upload de Dicom.
A chaque nouveau parent patient ID il faut modifier la liste de patient affiché au niveau patient et le signaler à la table patient.

Ici il y a des differences avec le search,

  • On a que l'ID patient et pas les details associés au patients
  • On a pas les details des study dans le patient.

Donc probablement, dans la class import, fait un GET sur l'API /patients/{id} d'Orthanc pour récupérer le detail du patient qui vient d'apparaitre.
Envoyer la meme stucture de data que via le search (array d'object avec le patientID comme clé et les meme détails associés).
Ici par contre le niveau study ne sera pas disponible donc il faudra dans le render du study faire un check, soit les details des study sont deja fournie (cas du search) et on affiche les data déjà en mémoire.
Soit les study ne sont pas fournie dans ce cas au moment de mount la nested table study on fait un call sur /patients/{id}/studies?expand pour avoir les details des studies pour ce patient.
Ensuite la table series va suivre la meme logique que dans Orthanc Content et s'updater quand on clique sur un niveau study.

=> Ici le defi va etre d'abstraire ces tables Patients / study / series pour qu'elle puisse s'inclure dans des environement differents avec des sources de data differentes.
On reutilisera encore ces tables dans d'autres parties du logiciel donc c'est une étape importante.

=> A faire qu'après avoir stabilité le Orthanc Content.

Option : Peer

  • Peer listing
  • Peer Declaration
  • Peer Echo
  • Peer Delete
  • Route Declaration in Backend using reverse proxy GET, PUT and DELETE (with admin midelware)

Orthanc APIs:

GET /peers?expand
PUT /peers/{name}
DELETE /peers/{name}
GET /peers/{name}/system

Faire que les tables soit triable

Activer le sort sur les colonnes visible => Table Patient, Study, Series
Example dans TableQuery et TableResult de AutoQuery (sauf qu'ici on fera pas de filter, juste un sort)
(suffit d'ajouter la propriété sort:true dans les colonnes affichées de ces 3 tables)

Warning a apparition Overlay

A l'apparition de l'overlay on a le warning suivant

Popper: CSS "margin" styles cannot be used to apply padding between the popper and its reference element or boundary. To replicate margin, use the offset modifier, as well as the padding option in the preventOverflow and flip modifiers.
in Overlay (created by Overlay)
in Overlay (at AnonTool.js:44)
in AnonTool (created by ConnectFunction)
in ConnectFunction (at ToolsPanel.js:74)
in ToolsPanel (created by ConnectFunction)
in ConnectFunction (at NavBar.js:36)
in NavBar (at App.js:51)
in App (at src/​index.js:19)

Change Orthanc Verbosity

Dans menu Generic des options
Entre le formulaire connexion d'Orthanc et les boutton reset et shutdown que tu va crer
Faire un Select https://react-select.com/home (cf class SelectModalities dans componant/autoquery/component)
Les valeurs du select : "default", "verbose", "trace"
Quand le composant se monte il faut recupérer la verbosité courante des logs dans Orthanc via API /tools/log-level GET
Avec un listener onChange, changer la valeur de la verbosité via l'API /tools/log-level PUT payload = une des 3 valeurs en String

Attention ! Ici Orthanc ne répond pas en JSON, il repond en plain text (et le PUT se fait en plain text)
=> J'ouvre un autre ticket

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.