def test_vessel_particles(): try: # Get the path to the this test so that we can reference the test data this_dir = os.path.dirname(os.path.realpath(__file__)) # Set up the inputs to VesselParticles input_ct = this_dir + '/../../../Testing/Data/Input/vesselgauss.nrrd' input_mask = \ this_dir + '/../../../Testing/Data/Input/vessel_vesselSeedsMask.nrrd' #tmp_dir = this_dir + '/../../../Testing/tmp/' tmp_dir = tempfile.mkdtemp() output_particles = os.path.join(tmp_dir, 'vessel_particles.vtk') print tmp_dir max_scale = 6.0 live_th = -100 seed_th = -80 scale_samples = 10 down_sample_rate = 1.0 min_intensity = -800 max_intensity = 400 # Generate the airway particles vp = VesselParticles(input_ct, output_particles, tmp_dir, input_mask, max_scale, live_th, seed_th, scale_samples, down_sample_rate, min_intensity, max_intensity) vp.execute() # Read in the reference data set for comparison ref_reader = vtk.vtkPolyDataReader() ref_reader.SetFileName(this_dir + \ '/../../../Testing/Data/Input/vessel_particles.vtk') ref_reader.Update() # Now read in the output data set test_reader = vtk.vtkPolyDataReader() test_reader.SetFileName(output_particles) test_reader.Update() pm = ParticleMetrics(ref_reader.GetOutput(), test_reader.GetOutput(), 'vessel') assert pm.get_particles_dice() > 0.97, \ "Vessel particle Dice score lower than expected" finally: #Clear particles cache vp._clean_tmp_dir = True vp.clean_tmp_dir() shutil.rmtree(tmp_dir)
def execute(self): header=nrrd.read_header(open(self._ct_file_name)) max_z=header['sizes'][2] spacing=[header['space directions'][kk][kk] for kk in xrange(3)] if len(crop) < 2: crop_flag = False else: if crop[0]<0: crop[0]=0 elif crop[1]>max_z: crop_flag = False crop_flag = True ct_file_name = self._ct_file_name pl_file_name = self._pl_file_name #Data preprocessing (cropping and/or resampling) before region based analysis if self._justparticles == False: #Crop volume if flag is set ct_file_name_crop = os.path.join(self._tmp_dir,self._case_id + "_crop.nhdr") pl_file_name_crop = os.path.join(self._tmp_dir,self._case_id + "_croppartialLungLabelMap.nhdr") if crop_flag == True: if self._rate == 1: ratestr = "=" else: ratestr = 'x%f' % rate tmpCommand = "unu crop -min 0 0 %(z1)d -max M M %(z2)d -i %(in)s | unu resample -k %(kernel)s -s = = %(ratestr)s -o %(out)s" tmpCommandCT = tmpCommand % {'z1':crop[0],'z2':crop[1],'in':ct_file_name,'out':ct_file_name_crop,'ratestr':ratestr,'kernel':"cubic:1,0"} tmpCommandPL = tmpCommand % {'z1':crop[0],'z2':crop[1],'in':pl_file_name,'out':pl_file_name_crop,'ratestr':ratestr,'kernel':"cheap"} print tmpCommandCT print tmpCommandPL subprocess.call(tmpCommandCT,shell=True) subprocess.call(tmpCommandPL,shell=True) ct_file_name = ct_file_name_crop pl_file_name = pl_file_name_crop #Do resampling to isotropic voxel size to compute accurate scale measurements ct_file_name_resample = os.path.join(self._tmp_dir,self._case_id + "_resample.nhdr") pl_file_name_resample = os.path.join(self._tmp_dir,self._case_id + "_resamplepartialLungLabelMap.nhdr") if self._voxel_size>0: tmpCommand = "unu resample -k %(kernel)s -s x%(f1)f x%(f2)f x%(f3)f -i %(in)s -o %(out)s" tmpCommandCT = tmpCommand % {'in':ct_file_name,'out':ct_file_name_resample,'kernel':"tent",'f1':spacing[0]/self._voxel_size,'f2':spacing[1]/self._voxel_size,'f3':spacing[2]/self._voxel_size} tmpCommandPL = tmpCommand % {'in':pl_file_name,'out':pl_file_name_resample,'kernel':"cheap",'f1':spacing[0]/self._voxel_size,'f2':spacing[1]/self._voxel_size,'f3':spacing[2]/self._voxel_size} print tmpCommandCT print tmpCommandPL subprocess.call(tmpCommandCT,shell=True) subprocess.call(tmpCommandPL,shell=True) ct_file_name = ct_file_name_resample pl_file_name = pl_file_name_resample for ii in self._regions: rtag = ii.lower() tmpDir = os.path.join(self._tmp_dir,rtag) if os.path.exists(tmpDir) == False: os.mkdir(tmpDir) # Define FileNames that will be used pl_file_nameRegion= os.path.join(tmpDir,self._case_id + "_" + rtag + "_partialLungLabelMap.nhdr") ct_file_nameRegion= os.path.join(tmpDir,self._case_id + "_" + rtag + ".nhdr") featureMapFileNameRegion = os.path.join(tmpDir,self._case_id + "_" + rtag + "_featureMap.nhdr") maskFileNameRegion = os.path.join(tmpDir,self._case_id + "_" + rtag + "_mask.nhdr") particlesFileNameRegion = os.path.join(self._output_prefix+ "_" + rtag + "VesselParticles.vtk") if self._justparticles == False: #Create SubVolume Region tmpCommand ="CropLung -r %(region)s -m 0 -v -1000 -i %(ct-in)s --plf %(lm-in)s -o %(ct-out)s --opl %(lm-out)s" tmpCommand = tmpCommand % {'region':ii,'ct-in':ct_file_name,'lm-in':pl_file_name,'ct-out':ct_file_nameRegion,'lm-out':pl_file_nameRegion} tmpCommand = os.path.join(path['CIP_PATH'],tmpCommand) print tmpCommand subprocess.call( tmpCommand, shell=True ) #Extract Lung Region + Distance map to peel lung tmpCommand ="ExtractChestLabelMap -r %(region)s -i %(lm-in)s -o %(lm-out)s" tmpCommand = tmpCommand % {'region':ii,'lm-in':pl_file_nameRegion,'lm-out':pl_file_nameRegion} tmpCommand = os.path.join(path['CIP_PATH'],tmpCommand) print tmpCommand subprocess.call( tmpCommand, shell=True ) tmpCommand ="unu 2op gt %(lm-in)s 0.5 -o %(lm-out)s" tmpCommand = tmpCommand % {'lm-in':pl_file_nameRegion,'lm-out':pl_file_nameRegion} print tmpCommand subprocess.call( tmpCommand, shell=True ) #tmpCommand ="ComputeDistanceMap -l %(lm-in)s -d %(distance-map)s -s 2" #tmpCommand = tmpCommand % {'lm-in':self._pl_file_nameRegion,'distance-map':self._pl_file_nameRegion} #tmpCommand = os.path.join(path['CIP_PATH'],tmpCommand) #print tmpCommand #subprocess.call( tmpCommand, shell=True ) tmpCommand ="pxdistancetransform -in %(lm-in)s -out %(distance-map)s" tmpCommand = tmpCommand % {'lm-in':pl_file_nameRegion,'distance-map':pl_file_nameRegion} tmpCommand = os.path.join(path['ITKTOOLS_PATH'],tmpCommand) print tmpCommand subprocess.call( tmpCommand, shell=True ) tmpCommand ="unu 2op lt %(distance-map)s %(distance)f -t short -o %(lm-out)s" tmpCommand = tmpCommand % {'distance-map':pl_file_nameRegion,'distance':self._distance_from_wall,'lm-out':pl_file_nameRegion} print tmpCommand subprocess.call( tmpCommand, shell=True ) # Compute Frangi if self._init_method == 'Frangi': tmpCommand = "ComputeFeatureStrength -i %(in)s -m Frangi -f RidgeLine --std %(minscale)f,4,%(maxscale)f --ssm 1 --alpha 0.5 --beta 0.5 --C 250 -o %(out)s" tmpCommand = tmpCommand % {'in':ct_file_nameRegion,'out':featureMapFileNameRegion,'minscale':self._min_scale,'maxscale':self._max_scale} tmpCommand = os.path.join(path['CIP_PATH'],tmpCommand) print tmpCommand #subprocess.call( tmpCommand, shell=True ) #Hist equalization, threshold Feature strength and masking tmpCommand = "unu 2op x %(feat)s %(mask)s -t float | unu heq -b 10000 -a 0.5 -s 2 | unu 2op gt - %(vesselness_th)f | unu convert -t short -o %(out)s" tmpCommand = tmpCommand % {'feat':featureMapFileNameRegion,'mask':pl_file_nameRegion,'vesselness_th':self._vesselness_th,'out':maskFileNameRegion} print tmpCommand subprocess.call( tmpCommand , shell=True) elif self._init_method == 'StrainEnergy': tmpCommand = "ComputeFeatureStrength -i %(in)s -m StrainEnergy -f RidgeLine --std %(minscale)f,4,%(maxscale)f --ssm 1 --alpha 0.2 --beta 0.1 --kappa 0.5 --nu 0.1 -o %(out)s" tmpCommand = tmpCommand % {'in':ct_file_nameRegion,'out':featureMapFileNameRegion,'minscale':self._min_scale,'maxscale':self._max_scale} tmpCommand = os.path.join(path['CIP_PATH'],tmpCommand) print tmpCommand subprocess.call( tmpCommand, shell=True ) #Hist equalization, threshold Feature strength and masking tmpCommand = "unu 2op x %(feat)s %(mask)s -t float | unu heq -b 10000 -a 0.5 -s 2 | unu 2op gt - %(vesselness_th)f | unu convert -t short -o %(out)s" tmpCommand = tmpCommand % {'feat':featureMapFileNameRegion,'mask':pl_file_nameRegion,'vesselness_th':self._vesselness_th,'out':maskFileNameRegion} print tmpCommand subprocess.call( tmpCommand , shell=True) elif self._init_method == 'Threshold': tmpCommand = "unu 2op gt %(in)s %(intensity_th)f | unu 2op x - %(mask)s -o %(out)s" tmpCommand = tmpCommand % {'in':ct_file_nameRegion,'mask':pl_file_nameRegion,'intensity_th':self._intensity_th,'out':maskFileNameRegion} print tmpCommand subprocess.call( tmpCommand , shell=True) #Binary Thinning tmpCommand = "GenerateBinaryThinning3D -i %(in)s -o %(out)s" tmpCommand = tmpCommand % {'in':maskFileNameRegion,'out':maskFileNameRegion} tmpCommand = os.path.join(path['CIP_PATH'],tmpCommand) print tmpCommand subprocess.call( tmpCommand, shell=True) # Vessel Particles For the Region if self._multires==False: particlesGenerator = VesselParticles(ct_file_nameRegion,particlesFileNameRegion,tmpDir,maskFileNameRegion,live_thresh=self._lth,seed_thresh=self._sth,min_intensity=-950,max_intensity=100) particlesGenerator._clean_tmp_dir=self._clean_cache particlesGenerator._interations_phase3 = 70 particlesGenerator._irad_phase3 = 0.9 particlesGenerator._srad_phase3 = 4 particlesGenerator._verbose = 0 particlesGenerator.execute() else: particlesGenerator = MultiResVesselParticles(ct_file_nameRegion,particlesFileNameRegion,tmpDir,maskFileNameRegion,live_thresh=-600,seed_thresh=-600) particlesGenerator._clean_tmp_dir=self._clean_cache particlesGenerator.execute()