[Dcmlib] gdcm proposal

Benoit Regrain benoit.regrain at creatis.insa-lyon.fr
Mon May 2 09:09:05 CEST 2005


----- Original Message ----- 
From: "Mathieu Malaterre" <mathieu.malaterre at kitware.com>
To: "Benoit Regrain" <benoit.regrain at creatis.insa-lyon.fr>
Cc: "Mailing list gdcm" <dcmlib at creatis.insa-lyon.fr>
Sent: Friday, April 29, 2005 5:02 PM
Subject: Re: [Dcmlib] gdcm proposal


> Document:
>    Representation direct du fichier DICOM
>    Idealement il ne charge pas les bin etrny > 4-96
>    Mais: si je fais GetEntry(0x7fe0,0010) il est capable (ala VTK) de 
> recharcher le fichier pour me retourner l'entree binaire (flux non decode)
>    L'utilisation de cette classe est en gros pour permettre a l'util a 
> acceder a des custom entry (genre Hopital Name ... )
>
> Image: (ou ImageInterpreter)
>    Prend en entree un Document
>    Retourne un volume proprement decompresser/reorganiser
>    Il sait acceder au champ 7fe0 , il devrait echouer sur un Document
>    qui n'a pas cette entry.
>
>
> La separation de ces classes permet de separer Information (light data) de 
> l'Image (Heavy Data). En admettant avoir un pipeline ala VTK, ca permet de 
> constuire une mini app qui ne fais qu'afficher les informations d'une 
> image DICOM. Ca laisse aussi la possibilite a un util de manipuler le 
> volume RAW directement si ca lui chante. Et cela tout en laissant la 
> possibilite a un utilisateur de construire une Image pour son viewer a 
> partir d'un Document lu.
>
> Je tiens a cette separation dans le future je voudrais d'autre type 
> d'interpreter:
>
> OverlayInterpreter:
>    Prend un Document en Entree
>    Retourn un Overlay (une image 2D je suppose)
Oki


> StringInterpreter et VectorDoubleInterperter VectorIntInterpretre sont un 
> peu different des Interpeter au dessus. Ca serait plus pour python ou on 
> pourrait renvoyer un type python (list) a partir d'une chaine separer par 
> des \.
Heuuu... cela me gene un peu d'avoir une utilisation Python différente de 
celle
en C++. Je pense qu'on peut éviter cela en réfléchissant mieux au problème.
Mais pour l'instant, je n'ai pas encore de solution



>> DocEntry : comme le DocEntry actuel (contient gr|elem + VR + value)
>>                  dérivé en ValEntry, BinEntry, SeqEntry
>> SQItem : comme le SQItem actuel, données contenant une liste de DocEntry.
>
> beurk, pourquoi une liste?  je veux mon acces en O(1) garanti -ou presque- 
> de partout. Faut que je vois avec brad, mais pour moi on doit pouvoir 
> avoir une hash<string, hash<string, DocEntry>>
SQItem est réellement une liste et donne un accès en O(1). dans une 
séquence,
il y a N fois le meme ensemble de DocEntry. Et on accède à chaque ensemble
en connaissant sa place dans la liste (dont l'ordre dépend). Je ne vois donc 
pas
comment tu veux utiliser ta hash table.


>> Document : données contenant une liste de DocEntry.
>>                   gère une image Dicom. Contient des méthodes facilitant 
>> l'accès aux
>>                   informations de l'image : taille, spacing, origin, 
>> orientation, etc.
>
> non. Document c'est vraiment l'image DICOM. Si le spacing est code sur 3 
> float, il me renvoi cette chaine de caractere. Il ne sait pas interpreter 
> la notion de spacing. Pourquoi mettre un spacing ici alors que DicomDir 
> derive de Document ...
Je n'avais pas dans l'idée que DicomDir derive de Document lorsque j'ai 
écrit cela
Je crois que Document n'etait pas le bon nom.
Pour moi, je pensais à 2 structure différentes entre Document et DicomDir. 
Les 2
dérivant d'une structure Data (par exemple)


>> DicomDir : données contenant une arborescence
>>                  DicomDirPatient / DicomDirStudy / DicomDirSerie / 
>> DicomDirImage
>>                  (qui sont aussi des données dérivant de SQItem)
>> Image : donnée image Dicom décompressée + Document ?
> je vous laisse DicomDir faut que je lise la norme la dessus.
oki


>> Reader : traitement qui permet de lire un fichier au format Dicom
>> DocReader : traitement qui permet de lire un fichier Dicom contenant un 
>> Document
>>                        retourne un Document
>>                       derive de Reader
>> DicomDirReader : traitement qui permet de lire un fichier Dicom contenant 
>> un DicomDir
>>                       retourne un DicomDir
>>                       derive de Reader
>
>
> Pour moi un DicomDir derive de Document donc dans les deux cas, le reader 
> renvoi un Document
>
>> Writer : traitement qui permet d'ecrire un fichier au format Dicom
>> DocWriter : traitement qui permet d'ecrire un fichier au format Dicom à 
>> partir d'un Document
>> DicomV3Writer : traitement qui permet d'ecrire un fichier au format 
>> DicomV3
>>                       prend un Document en entrée    derive de DocWriter
>> LibidoWriter : traitement qui permet d'ecrire un fichier au format Libido
>>                       prend un Document en entrée    derive de DocWriter
>> AcrNemaWriter : traitement qui permet d'ecrire un fichier au format 
>> ACR-NEMA
>>                       prend un Document en entrée    derive de DocWriter
>> DicomDirWriter : traitement qui permet d'ecrire un fichier au format 
>> Dicom à partir d'un DicomDir
>>                       prend un DicomDir en entrée    derive de Writer
>
> ok
>
>> DocValidator : traitement qui verifie la structure d'un Document
>>                       prend un Document en entrée
>>                       retourne du texte
>
> retourne un Document valide. produit du texte (dans un log?). Ce que tu 
> veux vraiment c'est etre sur que tu ecrives ton spacing sur 2 float...
>
>> DicomDirValidator : traitement qui verifie la structure d'un DicomDir
>>                       prend un DicomDir en entrée
>>                       retourne du texte
>
> idem, produit un Document valide
>
>> SerieOrder : traitement ordonnant une serie de Document
>>                      prend une liste de Document en entrée
>>                      retourne l'ordre de ces documents (sous quelle forme 
>> ?)
>
> prend en entree un filepath d'un repertoire.
> retourne une liste de fichiers (vector<string>), qui est passer a un 
> SerieReader.
> Je tiens a tout prix a cette separation, l'utilisateur doit a tout moment 
> lire ces fichiers dans l'order qu'il veut (cas ou les heuristiques de 
> SewrieOrder, mais l'utili lui seul sait dans quel order les lire).
La, j'ai pas tout compris moi...


> Maintenant pour les gens qui craignent de lire plusieurs fois la meme 
> image et que performance reason blabla... j'ai pas de solution tout faite 
> a presenter. J'aimerais etudier un peu plus la notion de parser vs reader 
> en XML. J'aimerais -je sais pas si c possible- avoir un mini parser qui ne 
> lise qu'un nombre restreint de tag (ImagePosition, ImageOrientation, UID 
> et qui sache s'arreter des qu'il les a trouver).
>
>> Decompress : traitement decompressant l'image d'un Document
>>                      prend un Document en entrée
>>                      retourne une Image
>> Document2DicomDirImage : tranforme un Document en DicomDirImage
>>                      prend un Document en entrée
>>                      retourne un DicomDirImage
>> DicomDirImage2Document : tranforme un DicomDirImage en Document
>>                      prend un DicomDirImage en entrée
>>                      retourne un Document
>
> je vous laisse ca.
>
>> On voit donc apparaitre une dérivation comme suit (incomplète bien sur) :
>> Data
>>  - Document
>>  - DicomDir
>>  - Image
>> Process
>>  - Reader
>>     - DicomDirReader
>>     - DocReader
>>  - Writer
>>     - DicomDirWriter
>>     - DocWriter
>>        - DicomV3Writer
>>        - LibidoWriter
>>        - DicomV3Writer
>>  - Validator
>>     - DicomDirValidator
>>     - DocValidator
>>  - SerieOrder
>>  - Decompress
>>  - Document2DicomDirImage
>>  - DicomDirImage2Document
>
>
> Base (Print)
>  - Document (== ElementSet)
>    - DicomDir
>  - Image
> Process
>  - Reader
>     - DicomDirReader
>     - DocReader
>        - DicomV3Reader
>          - BustedSiemens
>          - BustedGE (13 length hack)
>        - LibidoReader
>        - ACRNemaReader
>  - Writer
>     - DicomDirWriter
>     - DocWriter
>        - DicomV3Writer
>        - LibidoWriter
>        - ACRWriter
>  - Validator
>     - DicomDirValidator
>     - DocValidator
>  - SerieOrder
>  - Interpeter
>    - ImageInterperter (7fe0)
>    - OverlayInterpeter
>
> J'introduis les sous class BustedSiemens et BustedGE, en theorie si on ne 
> travaille que sur des IRM philips on ne devrait pas avoir a traiter ces 
> cas vraiment particulier. J'aimerais garder l'archi gdcm propre de ces 
> hack et laisser a l'util le choix de ne pas compiler ces sous classes...
Mais comment l'utilisateur peut savoir d'avance quel type d'image il a à 
lire ?
Si son image n'est pas lisible par le DicomV3Reader, il devra essayer les 
autre 1
par 1 ? Je ne pense pas que ce soit la bonne solution. Pour rester poli, ca
risque de faire chier l'utilisateur de cette librairie...



>> Si j'ai bien tout compris, Mathieu, on aura une séparation données 
>> traitements (comme dans VTK).
>> Ceci n'est bien sur qu'une ebauche, s'appuyant sur ce qui fonctionne deja 
>> et les morceaux à changer.
>> L'arborescence n'est pas complète, et il y a peut etre des choses fausses 
>> ou a revoir.
>> Mais une question se pose avec cela... on fait comme dans VTK avec un 
>> pipeline mis a jour automatiquement
>> ou pas ? Comment on gere les sorties, comme en VTK avec la meme sortie a 
>> chaque fois ou avec une
>> nouvelle sortie ? Et quand le traitement est détruit, qui détruit la 
>> sortie ?
>> Désolé de ne parler que de VTK, je ne connais pas encore ITK (mais c'est 
>> pour bientot)
>
> Les differences sont minimes si tu compares ITK a VTK < 4.4 (VTK CVS a un 
> nouveau pipeline nettement plus complexe).
> Pour faire encore comme VTK j'aimerais la notion de reference conting dans 
> gdcm.Base. Ca pemettrait de passe le gdcm.Document du reader a 
> gdcm.ImageInterpreter sans se soucier de la redundance.
>
>>  Ce qui me plait pas dans ce que je viens de présenter (et vi, on peut 
>> faire des choses pas belles des
>> le début...) c'est la différence entre Document et DicomDirImage... ce 
>> qui nous oblige apres a avoir
>> des passerelles entre les 2. Mais d'un autre coté, c'est justifiable sur 
>> le fait que les deux n'ont pas
>> tout en commun... mais la question va etre : pourquoi ne pas dire qu'un 
>> DicomDirImage est un Document ?
>
> EXACT !!!! C'est la meme chose c'est un ensemble qui associe une valeur a 
> une clef, c'est tout. Ensuite c'est le role de gdcm.Interpreter de faire 
> un abort()/reboot() si on lui passe un Document qui est en fait un 
> DicomDir...
>
>> et bien tout simplement car dans le DicomDirImage (actuel), on n'a que 
>> les champs correspondant au
>> niveau image du DicomDir, le DicomDirSerie contenant les info de la 
>> serie, idem avec Study et Patient.
>> Or, le Document doit contenir toutes les infos de chaque niveau du 
>> DicomDir (Patient + Study + Serie + Image).
>> Avoir ces convertisseurs obligerait aussi a pouvoir remonter de l'Image 
>> jusqu'au Patient, ce qui n'est pas le cas
>> actuellement (mais rien empeche de le faire ;-) )
>
> Ok la je suis perdu. C'est ou la description de DicomDir ?
Dans la version courante de gdcm :-p
En fait, le DicomDir actuel n'a pas besoin de toute la complexité du
Document... Il a juste besoin de conserver une liste de Patient, qui à son
tour contient une liste de Study qui contient les Serie qui contient les 
Image.


Je crois que je vais commencer à faire un diagramme de classes pour
essayer de poser les choses et partir de la pour les prochaines discussions.
Ainsi que des exemples. J'ai l'impression qu'on se mélange trop les papattes
sur les noms.

Benoit 




More information about the Dcmlib mailing list