Giter Club home page Giter Club logo

dicom-to-cnn's People

Contributors

salimkanoun avatar thomast3563 avatar wendyrvllr avatar

Stargazers

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

dicom-to-cnn's Issues

Lecture de la coupe au niveau instance

Lire la coupe au niveau instance et appliquer la fonction affine avant de retourner la matrice

Valeur pixel = (valeur row pixel * resclale slope) + rescale intercept

SK Dans series faudra surement indexer les position des coupes.

Data à recupérer lors du scan des dicoms

Data Patient :
Patient ID
Patient Name
"PatientBirthDate"
PatientSex"
Patient Weight
Patient Height

Data Study :
"AccessionNumber"
"InstitutionName"
"StudyDate"
"StudyDescription"
"StudyID"
"StudyInstanceUID"
"StudyTime"
Acqusition Time

DataSeries :

"ImageOrientationPatient" :
"Manufacturer" :
"Modality" (SK Ici probabkement faire une Enum et match avec sop class uid?)
"SeriesDate"
"SeriesDescription"
"SeriesInstanceUID"
"SeriesNumber"
"SeriesTime"

  • Le path de la series

Si TEP => Ajout des données
=> ces info sans dans un module
https://dicom.innolitics.com/ciods/pet-image/pet-isotope (groupe 0054,0016 et 0018,0026 ou tu va trouver des séquence de tag dicoms c'est une array de tag dicom dans un tag dicom)

  • Half Life (sec) (0018,1075)
  • Total Dose (Bq) (0018,1074)
  • Radiopharmaceutical Start DateTime (0018,1078)
  • Decay Correction : 0054,1102 ; 3 valeur possible "NONE", "START", "ADMIN" => dans PET series module attribute
  • Unit (0054,1001) voir http://dicomlookup.com/lookup.asp?sw=Tnumber&q=(0054,1001)
  • Si philips : Conversion SUV 7053,1000 (tag privé)
  • Si Philips : conversion Bqml 7053,1009 (tag privé)

Nb : Attention tous ne seront pas présent, si absent probabelement afficher "undefined"
En gras les clé unique qui vont etre utilisé pour indexer les data

Lecture des metadonnées

Prendre 10 DICOM tests de differentes modalities : PT, CT, SC, SR, RTSS, ...
et faire un test pour lecture de tags

StructureSetROISequence pas une sequence ?

Dans Dcmjs le rtss d'olivier le StructureSetROISequence n'est pas une séquence alors que ca devrait etre une séquence de 1 item.
Pourtant voir une sequence dans dicom parser

Calcul de SUV

Calcul du SUV

Data à recupérer :

  • Patient Height (m)

  • Patient Weight (Kg)

  • Series Time

  • Acquisition Time

  • Modality (Voir methode de thomas avec le SOP Class UID)

  • Manufacturer

  • Half Life (sec) (0018,1075)

  • Total Dose (Bq) (0018,1074)

  • Radiopharmaceutical Start DateTime (0018,1078)

  • Decay Correction : 0054,1102 ; 3 valeur possible "NONE", "START", "ADMIN" => dans PET series module attribute

  • Unit (0054,1001) voir http://dicomlookup.com/lookup.asp?sw=Tnumber&q=(0054,1001)

  • Si philips : Conversion SUV 7053,1000 (tag privé)

  • Si Philips : conversion Bqml 7053,1009 (tag privé)

Check :

  1. Si unit different de GML : Pas de calcul de SUV si manque un des parametre suivant
    Total dose, serie acquisition date, patient weight, Half life
    (SK a voir si on ajout une exception pour philips)

  2. Pas de SUL si pas de patient Height

  3. Si Philips le private tag 7053,1009 doit etre présent

Algo :

  1. Si Unit est GML => le facture de conversion est de 1, on est déjà en SUV

2)Definition de l'heure d'acquisition
Definition de l'heure d'acqusisition = Series time
Si acquisition Time présent et < à seriesTimes et si unité en BQML => Heure d'acqusition = Acquisition time

  1. Si Philips
    Multipiler l'image par 7053,1009 pour avoir l'image en BQML (meme si l'image est en unit BQML, philips donne de fausse info, ce sont des counts)

  2. correction de decroissance
    Si 0054,1102 n'est pas "ADMIN" => Faire la correction de decroissante (calculer un facteur de decroissance)
    Si 0054,1102 est "ADMIN" => pas de correction de decroissance, le facteur de decroissance est de 1

  • Calcul du facteur de decroissance :
    Difference en secondes entre InjectionTinme et l'heure d'acquisition définir dans l'étape 2)
    Checker que cette difference est positive (Acquisition Time Unix - InjectionTinme Unix est positive) cad di Acquisition Time est posterieure a l'injection Time
    (si ce n'est pas le cas pas de SUV, ce cas n'est pas possible)
    Faire la comparaison en dateTime (tenant en compte du jour car il peut y avoir des acquisition faites le landemin, parser l'ensemble de la dateTime)
    Facteur de décroissance = Math.exp(-(DeltaTempsCalculé)*ln(2)/halfLife);

  • Calcul du Facteur SUV
    SUV = valeurVoxel(Bq/Ml) / [ (totalDose * facteur de decroissance) / poids patient ]

Translation de ROI CSV

3 types de ROIS

Type 1 :Polygone, les coordonnées sont les "arretes"
Type 11 : Sphere ou Elipse : Les coordonnées sont Centre, Est et Nord
Num Point : Pixel inclus 1 à 1

Reconnaissance des PT Corrige d'attenuation

Tag 0028,0051
Si Corrigé il y a l'attribut "ATTN"

Parser et diviser en tableau avec \ et regarder si l'attribue est dans la liste

Exemple

Corrigé
0028,0051 Corrected Image: DECY\ATTN\SCAT\DTIM\RANSNG\DCAL\SLSENS\NORM

Non Corrigé
0028,0051 Corrected Image: DECY\DTIM\RANSNG\DCAL\SLSENS\NORM

A implementer dans SeriesPT un is_corrected_attenuation

Methodes de Thomas à transferer

=> Pour lire les matrice image des DICOM
Ici faudra surement dissocier la partie pyDICOM read qui va renvoyer une image
et la deuxieme ligne qui va ordoner les coupes par position qui doit etre faite dans Series

def __GatherSlices(self):
    """ called by convert_to_NIFTI """
    self.slices = [pydicom.dcmread(s) for s in self.filenames]
    self.slices.sort(key=lambda x:int(x.ImagePositionPatient[2]),reverse=True)

=> Les deux methode suivante permettent d'appliquer la fonction affine pour avoir des valeurs interrpretable dans les matrice, à encapsuler dan la classe Instance

def __getPixelData(self):
    """ called by convert_to_NIFTI """
    pixel_data = [self.__RescaleSlope_PixelData(ds) for ds in self.slices]
    return pixel_data

def __RescaleSlope_PixelData(self,ds):
    """ called by __getPixelData """
    return ds.pixel_array*float(ds.RescaleSlope)+float(ds.RescaleIntercept)

=> Premet de verifier que l'épaisseur de coupe est constante dans la series, à mettre dans methode Series
SK : Peut etre modifier par une methode verifiant qu'il n'y a pas de gap dans l'espace d'acquisition?

def __getZSpacing(self):
    """ called by __getMetadata """
    Z_positions = [ds.ImagePositionPatient[2] for ds in self.slices]
    
    initial_z_spacing = Z_positions[0]-Z_positions[1]
    for i in range(1,len(Z_positions)):
        z_spacing = Z_positions[i-1]-Z_positions[i]
        if (z_spacing!=initial_z_spacing):
            warnings.warn("Z axis Spacing is not constant : %s / %s" % (z_spacing,initial_z_spacing))
    return initial_z_spacing

=> info sur la postion et taill des voxel de la coupe, dans classe Instance

def __getMetadata(self):
    """ called by convert_to_NIFTI """
    Direction = (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0) #hard coded
    Origin = (self.slices[-1].ImagePositionPatient[0],self.slices[-1].ImagePositionPatient[1],self.slices[-1].ImagePositionPatient[2])
    Spacing = (self.slices[-1].PixelSpacing[0],self.slices[-1].PixelSpacing[1],self.__getZSpacing())
    return (Direction,Origin,Spacing)

=> creation du Nifti, ici ca sera a adapter en fonction de la modalité (ajouter SUV etc...) mais cette partie de code permet d'assigner les voxel au repere Nifti et de generer le Nifti

def convert_to_NIFTI(self,filename=None):
""" Generates .nii files from the DICOM serie """

    self.__GatherSlices()
    (Direction,Origin,Spacing) = self.__getMetadata()
    
    Array = np.stack(self.__getPixelData(),axis=0).astype(self.output_format)
    
    sitk_img = sitk.GetImageFromArray(Array)
    
    sitk_img.SetDirection(Direction)
    sitk_img.SetOrigin(Origin)
    sitk_img.SetSpacing(Spacing)
    #sitk_img.SetMetaData()
    
    sitk.WriteImage(sitk_img,filename)

Nifti sera en 16bits pour CT et 32 bits pour SUV (c'est la num py array qui doit avoir le bon format (exemple :self.output_format = np.int16)

RTSS_Reader

Renommer RTSS_Reader en Instance_RTSS
Cette classe doit heriter de Instance (pour la partie commune a tous les DICOM) et ajoute les méthode spécifiques aux RTSS.

Dans le model mettre un sous repertoire "reader" pour y mettre les classe qui lisent les dicom Instance et Instance_RTSS

Calcul SUL

Le calcul du SUL part de la valeur de SUV

Possible que si le SUV est dispo avec le sexe et la taille du patient

BMI = weight/Math.pow(height, 2);

	if( isFemale) {
		SULFactor  9270 / (8780 + 244*BMI);
	} else {
		SULFactor  9270 / (6680 + 216*BMI);
	}

Sk verif formul jenhmassian

L'image en SUL est l'image en SUV * SUL Factor

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.