def copyFilesFromFinal(self):
		#check that the program didn't finished and that not forced start point was not specified
		if ((self.final_start_point == checkpoint['END']) or self.final_start_point > self.end_point)  and not self.force_start_point_str:
			#If the program has finished there is nothing to do here.
			print_flush('%s The files from completed results analysis were found in %s. Remove them if you want to recalculated them again.' % (self.base_name, self.results_dir))
			sys.exit(0)
		
		#find what files we need to copy from the final destination if the analysis is going to resume from a later point
		files2copy = []
		
		if self.analysis_start_point <= checkpoint['INT_PROFILE']: 
			#we do not need the mask to calculate the features
			try:
				#check if there is already a finished/readable temporary mask file in current directory otherwise copy the 
				with h5py.File(self.tmp_mask_file, "r") as mask_fid:
					if mask_fid['/mask'].attrs['has_finished'] < 1:
						#go to the exception if the mask has any other flag
						raise
			except:
				with h5py.File(self.masked_image_file, "r") as mask_fid:
					#check if the video to mask conversion did indeed finished correctly
					assert mask_fid['/mask'].attrs['has_finished'] >= 1

				files2copy += [(self.masked_image_file, self.tmp_mask_dir)]

		if self.tmp_start_point < self.final_start_point:
			#copy files from an incomplete analysis files.
			if self.final_start_point > checkpoint['TRAJ_CREATE']: #and final_start_point <= checkpoint['SKE_CREATE']:
				files2copy += [(self.trajectories_file, self.tmp_results_dir)]
			if self.final_start_point > checkpoint['SKE_CREATE']:
				files2copy += [(self.skeletons_file, self.tmp_results_dir)]
			if self.final_start_point > checkpoint['INT_PROFILE']:
				files2copy += [(self.intensities_file, self.tmp_results_dir)]
		
		copyFilesLocal(files2copy)
	def exec_all(self):
		try:
			self.start()
			self.main_code()
			self.clean()
		except:
			raise
			print_flush(base_name + ' Error')
Exemple #3
0
def compressSingleWorker(video_file, mask_dir, param_file, is_single_worm,
                         cmd_original):

    if mask_dir[-1] != os.sep: mask_dir += os.sep

    #get function parameters
    param = tracker_param(param_file)

    base_name = video_file.rpartition('.')[0].rpartition(os.sep)[-1]
    masked_image_file = os.path.join(mask_dir, base_name + '.hdf5')

    print(masked_image_file)
    try:
        #try to get the has_finished flag, if this fails the file is likely to be corrupted so we can start over again
        with h5py.File(masked_image_file, "r") as mask_fid:
            has_finished = mask_fid['/mask'].attrs['has_finished']

            if is_single_worm and not all(
                    dd in mask_fid for dd in ['stage_data', 'xml_info']):
                #if a single_worm file does not have the stage_data or xml_info there is something really bad,
                #let's recalculate everything again
                has_finished = 0
    except:
        has_finished = 0

    if has_finished:
        print_flush(
            'File alread exists: %s. If you want to calculate the mask again delete the existing file.'
            % masked_image_file)
        return
    else:
        initial_time = time.time()

        #check if the video file exists
        assert os.path.exists(video_file)
        #create the mask path if it does not exist
        if not os.path.exists(mask_dir): os.makedirs(mask_dir)

        #This function will throw an exception if the additional files do not exists, before attempting to calculate anything
        if is_single_worm: getAdditionalFiles(video_file)

        #compress video the provenance tracking functions
        compressVideoWProv(video_file, masked_image_file,
                           param.compress_vid_param, cmd_original)

        #get the store the additional data for the single worm case. It needs that the
        #masked_image_file has been created.
        if is_single_worm: storeAdditionalDataSW(video_file, masked_image_file)

    time_str = str(
        datetime.timedelta(seconds=round(time.time() - initial_time)))
    progress_str = 'Processing Done. Total time = %s' % time_str
    print_flush(base_name + ' ' + progress_str)

    return masked_image_file
def copyFilesLocal(files2copy):
	#copy the necessary files (maybe we can create a daemon later)
		for files in files2copy:
			file_name, destination = files
			
			#if not os.path.exists(file_name): continue
			
			assert(os.path.exists(destination))

			if os.path.abspath(os.path.dirname(file_name)) != os.path.abspath(destination):
				print_flush('Copying %s to %s' % (file_name, destination))
				shutil.copy(file_name, destination)
def copyFilesLocal(files2copy):
    #copy the necessary files (maybe we can create a daemon later)
    for files in files2copy:
        file_name, destination = files

        #if not os.path.exists(file_name): continue

        assert (os.path.exists(destination))

        if os.path.abspath(
                os.path.dirname(file_name)) != os.path.abspath(destination):
            print_flush('Copying %s to %s' % (file_name, destination))
            shutil.copy(file_name, destination)
def compressSingleWorker(video_file, mask_dir, param_file, is_single_worm, cmd_original): 
    
    if mask_dir[-1] != os.sep: mask_dir += os.sep

    #get function parameters
    param = tracker_param(param_file)
    
    base_name = video_file.rpartition('.')[0].rpartition(os.sep)[-1]
    masked_image_file = os.path.join(mask_dir, base_name + '.hdf5')
    
    print(masked_image_file)
    try:
        #try to get the has_finished flag, if this fails the file is likely to be corrupted so we can start over again
        with h5py.File(masked_image_file, "r") as mask_fid:
            has_finished = mask_fid['/mask'].attrs['has_finished']

            if is_single_worm and not all(dd in mask_fid for dd in ['stage_data', 'xml_info']):
                #if a single_worm file does not have the stage_data or xml_info there is something really bad, 
                #let's recalculate everything again
                has_finished = 0 
    except:
        has_finished = 0 

    if has_finished:
        print_flush('File alread exists: %s. If you want to calculate the mask again delete the existing file.' % masked_image_file)
        return
    else:
        initial_time = time.time()

        #check if the video file exists
        assert os.path.exists(video_file)
        #create the mask path if it does not exist
        if not os.path.exists(mask_dir): os.makedirs(mask_dir)
        
        #This function will throw an exception if the additional files do not exists, before attempting to calculate anything
        if is_single_worm: getAdditionalFiles(video_file)
        
        #compress video the provenance tracking functions
        compressVideoWProv(video_file, masked_image_file, param.compress_vid_param, cmd_original)

        #get the store the additional data for the single worm case. It needs that the 
        #masked_image_file has been created.
        if is_single_worm: storeAdditionalDataSW(video_file, masked_image_file)
    
    time_str = str(datetime.timedelta(seconds=round(time.time()-initial_time)))
    progress_str = 'Processing Done. Total time = %s' % time_str
    print_flush(base_name + ' ' + progress_str)
    
    return masked_image_file
	def start(self):
		self.start_time = time.time()
		
		if not os.path.exists(self.tmp_mask_dir): os.makedirs(self.tmp_mask_dir)
		
		self.get_file_names()
		self.get_start_point()

		#copy the video file locally if requiered. See getFileNames
		if self.final_has_finished == 0 and self.tmp_video_file != self.video_file:
			print_flush(self.base_name + ' Copying video file to local temporary directory.')
			shutil.copy(self.video_file, self.tmp_video_file)
			if self.is_single_worm:
				try:
					dd = self.video_file.rpartition('.')[0]
					shutil.copy(dd + '.log.csv', self.tmp_mask_dir)
					shutil.copy(dd + '.info.xml', self.tmp_mask_dir)
				except FileNotFoundError:
					try:
						dd = self.video_file.rpartition('.')[0]
						dd, base_name = os.path.split(dd)
						dd = os.path.join(dd, '.data', base_name)
						shutil.copy(dd + '.log.csv', self.tmp_mask_dir)
						shutil.copy(dd + '.info.xml', self.tmp_mask_dir)
					except FileNotFoundError:
						pass

			
		#this might be more logically group in main_code, but this operation can and should be do remotely if required
		if self.final_has_finished  == 1:
			#The file finished to be processed but the additional data was not stored. We can do this remotely. 
			os.chflags(self.masked_image_file, not stat.UF_IMMUTABLE)
			compressSingleWorker(self.video_file, self.mask_dir, self.json_file, self.is_single_worm, self.cmd_original)
			os.chflags(self.masked_image_file, stat.UF_IMMUTABLE)

		if self.final_has_finished  == 2:
			print_flush('File alread exists: %s. If you want to calculate the mask again delete the existing file.' % self.masked_image_file)
	
		#parameters to calculate the mask, this will return a list with necessary commands in case I want to use it as a subprocess
		if self.is_calculate_mask:
			self.main_input_params = [self.tmp_video_file, self.tmp_mask_dir, self.json_file, self.is_single_worm, self.cmd_original]
		else:
			self.main_input_params = []
		
		return self.create_script()
	def clean(self):
		if self.final_has_finished == 0:
			print_flush(self.base_name + ' Moving files to final destination and removing temporary files.')
			if os.path.abspath(self.tmp_video_file) != os.path.abspath(self.video_file):
				#print_flush(self.base_name + ' Removing video file from local temporary directory.')
				assert os.path.abspath(self.tmp_video_file) != os.path.abspath(self.video_file)
				os.remove(self.tmp_video_file)
				assert os.path.exists(self.video_file)

				if self.is_single_worm:
					dd = self.tmp_video_file.rpartition('.')[0]
					os.remove(dd + '.log.csv')
					os.remove(dd + '.info.xml')


			#assert the local file did finished
			with h5py.File(self.tmp_mask_file, "r") as mask_fid:
				assert mask_fid['/mask'].attrs['has_finished'] > 0

			if os.path.abspath(self.tmp_mask_file) != os.path.abspath(self.masked_image_file):
				#it is very important to use os.path.abspath() otherwise there could be some 
				#confunsion in the same file name
				#print_flush(self.base_name + " Copying temporal masked file into the final directory.")
				shutil.copy(self.tmp_mask_file, self.masked_image_file)
			
				#print_flush(self.base_name + " Removing temporary files.")
				assert os.path.exists(self.masked_image_file)
				os.remove(self.tmp_mask_file)

			#Change the permissions so everybody can read/write. 
			#Otherwise only the owner would be able to change the ummutable flag.
			os.chmod(self.masked_image_file, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWUSR|stat.S_IWGRP|stat.S_IWOTH) 
			
			#Protect file from deletion.
			os.chflags(self.masked_image_file, stat.UF_IMMUTABLE)
			#print_flush(self.base_name + " Finished to create masked file")


		time_str = str(datetime.timedelta(seconds=round(time.time()-self.start_time)))
		print_flush('%s Finished. Total time = %s' % (self.base_name, time_str))
    def copyFilesFromFinal(self):
        #check that the program didn't finished and that not forced start point was not specified
        if ((self.final_start_point == checkpoint['END'])
                or self.final_start_point > self.end_point
            ) and not self.force_start_point_str:
            #If the program has finished there is nothing to do here.
            print_flush(
                '%s The files from completed results analysis were found in %s. Remove them if you want to recalculated them again.'
                % (self.base_name, self.results_dir))
            sys.exit(0)

        #find what files we need to copy from the final destination if the analysis is going to resume from a later point
        files2copy = []

        if self.analysis_start_point <= checkpoint['INT_PROFILE']:
            #we do not need the mask to calculate the features
            try:
                #check if there is already a finished/readable temporary mask file in current directory otherwise copy the
                with h5py.File(self.tmp_mask_file, "r") as mask_fid:
                    if mask_fid['/mask'].attrs['has_finished'] < 1:
                        #go to the exception if the mask has any other flag
                        raise
            except:
                with h5py.File(self.masked_image_file, "r") as mask_fid:
                    #check if the video to mask conversion did indeed finished correctly
                    assert mask_fid['/mask'].attrs['has_finished'] >= 1

                files2copy += [(self.masked_image_file, self.tmp_mask_dir)]

        if self.tmp_start_point < self.final_start_point:
            #copy files from an incomplete analysis files.
            if self.final_start_point > checkpoint[
                    'TRAJ_CREATE']:  #and final_start_point <= checkpoint['SKE_CREATE']:
                files2copy += [(self.trajectories_file, self.tmp_results_dir)]
            if self.final_start_point > checkpoint['SKE_CREATE']:
                files2copy += [(self.skeletons_file, self.tmp_results_dir)]
            if self.final_start_point > checkpoint['INT_PROFILE']:
                files2copy += [(self.intensities_file, self.tmp_results_dir)]

        copyFilesLocal(files2copy)
Exemple #10
0
    def execAllPoints(self):
        initial_time = time.time()

        #if start_point is larger than end_point there is nothing else to do
        if self.start_point > self.end_point:
            print_flush(self.base_name + ' Finished in ' +
                        checkpoint_label[self.end_point])
            return

        print_flush(self.base_name + ' Starting checkpoint: ' +
                    checkpoint_label[self.start_point])

        for ii in range(self.start_point, self.end_point + 1):
            current_point = checkpoint_label[ii]

            if self.is_single_worm and current_point == 'INT_PROFILE':
                execThisPoint(current_point,
                              **self.points_parameters['STAGE_ALIGMENT'],
                              commit_hash=self.commit_hash,
                              cmd_original=self.cmd_original)
                with tables.File(self.skeletons_file, 'r') as fid:
                    try:
                        good_aligment = fid.get_node(
                            '/stage_movement')._v_attrs['has_finished'][:]
                    except (KeyError, IndexError):
                        good_aligment = 0
                    if good_aligment != 1:
                        #break, bad video we do not need to calculate anything else.
                        last_check_point = 'STAGE_ALIGMENT'
                        break

            if not self.use_manual_join and current_point == 'FEAT_MANUAL_CREATE':
                continue

            last_check_point = checkpoint_label[self.end_point]

            if current_point == 'END': break

            #print(current_point, self.points_parameters[current_point]['func'])
            #print(self.points_parameters[current_point]['argkws'])
            execThisPoint(current_point,
                          **self.points_parameters[current_point],
                          commit_hash=self.commit_hash,
                          cmd_original=self.cmd_original)

        time_str = str(
            datetime.timedelta(seconds=round(time.time() - initial_time)))
        print_flush('%s  Finished in %s. Total time %s' %
                    (self.base_name, last_check_point, time_str))
def alignStageMotion(masked_image_file,
                     skeletons_file,
                     tmp_dir=os.path.expanduser('~/Tmp')):

    assert os.path.exists(masked_image_file)
    assert os.path.exists(skeletons_file)

    base_name = os.path.split(masked_image_file)[1].partition('.hdf5')[0]
    #check if it was finished before
    with h5py.File(skeletons_file, 'r+') as fid:
        try:
            has_finished = fid['/stage_movement'].attrs['has_finished'][:]
        except (KeyError, IndexError):
            has_finished = 0
    if has_finished > 0:
        print_flush('%s The stage motion was previously aligned.' % base_name)
        return

    #get the current to add as a matlab path
    current_dir = os.path.dirname(os.path.abspath(__file__))
    start_cmd = ('matlab -nojvm -nosplash -nodisplay -nodesktop <').split()

    script_cmd = "addpath('{0}'); " \
    "try, alignStageMotionSegwormFun('{1}', '{2}'); " \
    "catch ME, disp(getReport(ME)); " \
    "end; exit; "

    script_cmd = script_cmd.format(current_dir, masked_image_file,
                                   skeletons_file)

    #create temporary file to read as matlab script, works better than passing a string in the command line.
    tmp_fid, tmp_script_file = tempfile.mkstemp(suffix='.m',
                                                dir=tmp_dir,
                                                text=True)
    with open(tmp_script_file, 'w') as fid:
        fid.write(script_cmd)

    matlab_cmd = start_cmd + [tmp_script_file]

    #call matlab and align the stage motion
    print_flush('%s Aligning Stage Motion.' % base_name)
    sp.call(matlab_cmd)
    print_flush('%s Alignment finished.' % base_name)

    #delete temporary file.
    os.close(tmp_fid)
    os.remove(tmp_script_file)
    def execAllPoints(self):
        initial_time = time.time()

        #if start_point is larger than end_point there is nothing else to do 
        if self.start_point > self.end_point: 
            print_flush(self.base_name + ' Finished in ' + checkpoint_label[self.end_point])
            return
        
        print_flush(self.base_name + ' Starting checkpoint: ' + checkpoint_label[self.start_point])
            

        for ii in range(self.start_point, self.end_point+1):
            current_point = checkpoint_label[ii]
            
            if self.is_single_worm and current_point == 'INT_PROFILE': 
                execThisPoint(current_point, **self.points_parameters['STAGE_ALIGMENT'], 
                commit_hash=self.commit_hash, cmd_original=self.cmd_original)
                with tables.File(self.skeletons_file, 'r') as fid:
                    try:
                        good_aligment = fid.get_node('/stage_movement')._v_attrs['has_finished'][:]
                    except (KeyError,IndexError):
                        good_aligment = 0;
                    if good_aligment != 1:
                        #break, bad video we do not need to calculate anything else.
                        last_check_point = 'STAGE_ALIGMENT'
                        break

            if not self.use_manual_join and current_point == 'FEAT_MANUAL_CREATE': continue
            

            last_check_point = checkpoint_label[self.end_point]

            if current_point == 'END': break

            #print(current_point, self.points_parameters[current_point]['func'])
            #print(self.points_parameters[current_point]['argkws'])
            execThisPoint(current_point, **self.points_parameters[current_point], 
                commit_hash=self.commit_hash, cmd_original=self.cmd_original)
            
        
        time_str = str(datetime.timedelta(seconds=round(time.time()-initial_time)))
        print_flush('%s  Finished in %s. Total time %s' % (self.base_name, last_check_point, time_str))
def alignStageMotion(masked_image_file, skeletons_file, tmp_dir = os.path.expanduser('~/Tmp')):
    
    assert os.path.exists(masked_image_file)
    assert os.path.exists(skeletons_file)

    base_name = os.path.split(masked_image_file)[1].partition('.hdf5')[0];
    #check if it was finished before
    with h5py.File(skeletons_file, 'r+') as fid:
        try:
            has_finished = fid['/stage_movement'].attrs['has_finished'][:]
        except (KeyError,IndexError):
            has_finished = 0;
    if has_finished > 0:
        print_flush('%s The stage motion was previously aligned.' % base_name)
        return 

    #get the current to add as a matlab path
    current_dir = os.path.dirname(os.path.abspath(__file__))
    start_cmd = ('matlab -nojvm -nosplash -nodisplay -nodesktop <').split()
    
    script_cmd = "addpath('{0}'); " \
    "try, alignStageMotionSegwormFun('{1}', '{2}'); " \
    "catch ME, disp(getReport(ME)); " \
    "end; exit; "
    
    script_cmd = script_cmd.format(current_dir, masked_image_file, skeletons_file)

    #create temporary file to read as matlab script, works better than passing a string in the command line.
    tmp_fid, tmp_script_file = tempfile.mkstemp(suffix='.m', dir=tmp_dir, text=True)
    with open(tmp_script_file, 'w') as fid:
        fid.write(script_cmd)

    matlab_cmd = start_cmd + [tmp_script_file]
    
    #call matlab and align the stage motion
    print_flush('%s Aligning Stage Motion.' % base_name)
    sp.call(matlab_cmd)
    print_flush('%s Alignment finished.' % base_name)

    #delete temporary file.
    os.close(tmp_fid)
    os.remove(tmp_script_file)
        trajectories_file = ff[:-5] + '_trajectories.hdf5'
        skeletons_file = ff[:-5] + '_skeletons.hdf5'
        intensities_file = ff[:-5] + '_intensities.hdf5'

        #check the file finished in the correct step
        #with tables.File(skeletons_file, 'r') as fid:
        #    assert fid.get_node('/skeleton')._v_attrs['has_finished'] >= 4

        with pd.HDFStore(skeletons_file, 'r') as fid:
            trajectories_data = fid['/trajectories_data']

        grouped_trajectories = trajectories_data.groupby('worm_index_joined')
        tot_worms = len(grouped_trajectories)
        #variables to report progress
        base_name = skeletons_file.rpartition('.')[0].rpartition(
            os.sep)[-1].rpartition('_')[0]

        print_flush(base_name +
                    " Checking if the final Head-Tail orientation is correct")
        for index_n, (worm_index,
                      trajectories_worm) in enumerate(grouped_trajectories):

            p_tot, skel_group, int_group = checkFinalOrientation(
                skeletons_file, intensities_file, trajectories_worm,
                head_tail_param)
            print(p_tot)

            if p_tot < 0.5:
                switchBlocks(skel_group, skeletons_file, int_group,
                             intensities_file)
Exemple #15
0
def getIntensityProfile(masked_image_file,
                        skeletons_file,
                        intensities_file,
                        width_resampling=15,
                        length_resampling=131,
                        min_num_skel=100,
                        smooth_win=11,
                        pol_degree=3,
                        width_percentage=0.5,
                        save_int_maps=False):

    assert smooth_win > pol_degree
    assert min_num_skel > 0
    assert 0 < width_percentage < 1

    #we want to use symetrical distance centered in the skeleton
    if length_resampling % 2 == 0: length_resampling += 1
    if width_resampling % 2 == 0: width_resampling += 1

    #get the limits to be averaged from the intensity map
    if save_int_maps:
        width_win_ind = getWidthWinLimits(width_resampling, width_percentage)
    else:
        width_win_ind = (0, width_resampling)

    #filters for the tables structures
    table_filters = tables.Filters(complevel=5,
                                   complib='zlib',
                                   shuffle=True,
                                   fletcher32=True)

    #Get a reduced version of the trajectories_data table with only the valid skeletons.
    #The rows of this new table are going to be saved into skeletons_file
    trajectories_data_valid = setIntMapIndexes(skeletons_file, min_num_skel)

    #let's save this new table into the intensities file
    with tables.File(intensities_file, 'w') as fid:
        fid.create_table('/', 'trajectories_data_valid', \
            obj = trajectories_data_valid.to_records(index=False), filters=table_filters)

    tot_rows = len(trajectories_data_valid)
    if tot_rows == 0:
        with tables.File(intensities_file, "r+") as int_file_id:
            #nothing to do here let's save empty data and go out
            worm_int_avg_tab = int_file_id.create_array(
                "/", "straighten_worm_intensity_median", obj=np.zeros(0))
            worm_int_avg_tab._v_attrs['has_finished'] = 1
        return

    with tables.File(masked_image_file, 'r')  as mask_fid, \
         tables.File(skeletons_file, 'r') as ske_file_id, \
         tables.File(intensities_file, "r+") as int_file_id:

        #pointer to the compressed videos
        mask_dataset = mask_fid.get_node("/mask")

        #pointer to skeletons
        skel_tab = ske_file_id.get_node('/skeleton')
        skel_width_tab = ske_file_id.get_node('/width_midbody')

        filters = tables.Filters(complevel=5, complib='zlib', shuffle=True)

        #we are using Float16 to save space, I am assuing the intensities are between uint8
        worm_int_avg_tab = int_file_id.create_carray("/", "straighten_worm_intensity_median", \
                                   tables.Float16Atom(dflt=np.nan), \
                                   (tot_rows, length_resampling), \
                                    chunkshape = (1, length_resampling),\
                                    filters = table_filters)

        worm_int_avg_tab._v_attrs['has_finished'] = 0
        worm_int_avg_tab.attrs['width_win_ind'] = width_win_ind

        if save_int_maps:
            worm_int_tab = int_file_id.create_carray("/", "straighten_worm_intensity", \
                                   tables.Float16Atom(dflt=np.nan), \
                                   (tot_rows, length_resampling,width_resampling), \
                                    chunkshape = (1, length_resampling,width_resampling),\
                                    filters = table_filters)
        #variables used to report progress
        base_name = skeletons_file.rpartition('.')[0].rpartition(
            os.sep)[-1].rpartition('_')[0]
        progressTime = timeCounterStr('Obtaining intensity maps.')

        for frame, frame_data in trajectories_data_valid.groupby(
                'frame_number'):
            img = mask_dataset[frame, :, :]
            for ii, row_data in frame_data.iterrows():
                skeleton_id = int(row_data['skeleton_id'])
                worm_index = int(row_data['worm_index_joined'])
                int_map_id = int(row_data['int_map_id'])

                #read ROI and skeleton, and put them in the same coordinates map
                worm_img, roi_corner = getWormROI(img, row_data['coord_x'],
                                                  row_data['coord_y'],
                                                  row_data['roi_size'])
                skeleton = skel_tab[skeleton_id, :, :] - roi_corner

                half_width = skel_width_tab[skeleton_id] / 2

                assert not np.isnan(skeleton[0, 0])

                skel_smooth = smoothSkeletons(
                    skeleton,
                    length_resampling=length_resampling,
                    smooth_win=smooth_win,
                    pol_degree=pol_degree)
                straighten_worm, grid_x, grid_y = getStraightenWormInt(
                    worm_img,
                    skel_smooth,
                    half_width=half_width,
                    width_resampling=width_resampling)

                #if you use the mean it is better to do not use float16
                int_avg = np.median(
                    straighten_worm[width_win_ind[0]:width_win_ind[1], :],
                    axis=0)

                worm_int_avg_tab[int_map_id] = int_avg

                #only save the full map if it is specified by the user
                if save_int_maps:
                    worm_int_tab[int_map_id] = straighten_worm.T

            if frame % 500 == 0:
                progress_str = progressTime.getStr(frame)
                print_flush(base_name + ' ' + progress_str)

        worm_int_avg_tab._v_attrs['has_finished'] = 1
Exemple #16
0
        type=int,
        default=-1,
        help='Force the program to start at a specific point in the analysis.')
    parser.add_argument('--end_point',
                        type=int,
                        default=checkpoint['END'],
                        help='End point of the analysis.')
    parser.add_argument(
        '--is_single_worm',
        action='store_true',
        help=
        'This flag indicates if the video corresponds to the single worm case.'
    )
    parser.add_argument(
        '--use_manual_join',
        action='store_true',
        help='Use this flag to calculate features on manually joined data.')
    parser.add_argument(
        '--use_skel_filter',
        action='store_true',
        help='Flag to filter valid skeletons using the movie robust averages.')
    parser.add_argument('--cmd_original',
                        default='',
                        help='Internal. Used in provenance tracking.')

    if len(sys.argv) > 1:
        args = parser.parse_args()
        getTrajectoriesWorkerL(**vars(args))
    else:
        print_flush('Bad', sys.argv)
Exemple #17
0
def correctHeadTailIntensity(skeletons_file, intensities_file, smooth_W = 5,
    gap_size = 0, min_block_size = 10, local_avg_win = 25, min_frac_in = 0.85, head_tail_param = {}):
    
    #get the trajectories table
    with pd.HDFStore(skeletons_file, 'r') as fid:
        trajectories_data = fid['/trajectories_data']
        #at this point the int_map_id with the intensity maps indexes must exist in the table
        assert 'int_map_id' in trajectories_data
    
    grouped_trajectories = trajectories_data.groupby('worm_index_joined')

    tot_worms = len(grouped_trajectories)

    #variables to report progress
    base_name = skeletons_file.rpartition('.')[0].rpartition(os.sep)[-1].rpartition('_')[0]
    progress_timer = timeCounterStr('');
    
    
    bad_worms = [] #worms with not enough difference between the normal and inverted median intensity profile
    switched_blocks = [] #data from the blocks that were switched
    
    #ind2check = [765] 
    for index_n, (worm_index, trajectories_worm) in enumerate(grouped_trajectories):
        #if not worm_index in ind2check: continue 
        
        if index_n % 10 == 0:
            dd = " Correcting Head-Tail using intensity profiles. Worm %i of %i." % (index_n+1, tot_worms)
            dd = base_name + dd + ' Total time:' + progress_timer.getTimeStr()
            print_flush(dd)
        
        #correct head tail using the intensity profiles
        dd = correctHeadTailIntWorm(trajectories_worm, skeletons_file, intensities_file, \
            smooth_W, gap_size, min_block_size, local_avg_win, min_frac_in)
        
        switched_blocks += [(worm_index, t0, tf) for t0, tf in dd] 
        
        
        #check that the final orientation is correct, otherwise switch the whole trajectory
        p_tot, skel_group, int_group = \
        checkFinalOrientation(skeletons_file, intensities_file, trajectories_worm, min_block_size, head_tail_param)
        if p_tot < 0.5:
                switchBlocks(skel_group, skeletons_file, int_group, intensities_file)

    #label the process as finished and store the indexes of the switched worms
    with tables.File(skeletons_file, 'r+') as fid:
        if not '/Intensity_Analysis' in fid:
            fid.create_group('/', 'Intensity_Analysis')
        
        if '/Intensity_Analysis/Bad_Worms' in fid:
            fid.remove_node('/Intensity_Analysismin_block_size/Bad_Worms')
        if '/Intensity_Analysis/Switched_Head_Tail' in fid:
            fid.remove_node('/Intensity_Analysis/Switched_Head_Tail')
        
        if bad_worms:
            fid.create_array('/Intensity_Analysis', 'Bad_Worms', np.array(bad_worms))
        
        if switched_blocks:
            #to rec array
            switched_blocks = np.array(switched_blocks, \
            dtype = [('worm_index',np.int), ('ini_frame',np.int), ('last_frame',np.int)])
            fid.create_table('/Intensity_Analysis', 'Switched_Head_Tail', switched_blocks)
    
        
        fid.get_node('/skeleton')._v_attrs['has_finished'] = 4
        
    print_flush(base_name + ' Head-Tail correction using intensity profiles finished: ' + progress_timer.getTimeStr())
            if current_point == 'END': break

            #print(current_point, self.points_parameters[current_point]['func'])
            #print(self.points_parameters[current_point]['argkws'])
            execThisPoint(current_point, **self.points_parameters[current_point], 
                commit_hash=self.commit_hash, cmd_original=self.cmd_original)
            
        
        time_str = str(datetime.timedelta(seconds=round(time.time()-initial_time)))
        print_flush('%s  Finished in %s. Total time %s' % (self.base_name, last_check_point, time_str))
        


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Track woms in an individual video hdf5 file.")
    parser.add_argument('masked_image_file', help = 'hdf5 video file.')
    parser.add_argument('results_dir', help = 'Directory where results are going to be saved.')
    parser.add_argument('--json_file', default = '', help='File (.json) containing the tracking parameters.')
    parser.add_argument('--start_point', type=int, default = -1, help = 'Force the program to start at a specific point in the analysis.')
    parser.add_argument('--end_point', type=int, default = checkpoint['END'], help='End point of the analysis.')
    parser.add_argument('--is_single_worm', action='store_true', help = 'This flag indicates if the video corresponds to the single worm case.')
    parser.add_argument('--use_manual_join', action='store_true', help = 'Use this flag to calculate features on manually joined data.')
    parser.add_argument('--use_skel_filter', action='store_true', help = 'Flag to filter valid skeletons using the movie robust averages.')
    parser.add_argument('--cmd_original', default = '', help = 'Internal. Used in provenance tracking.')
    
    if len(sys.argv)>1: 
        args = parser.parse_args()
        getTrajectoriesWorkerL(**vars(args)) 
    else:
        print_flush('Bad', sys.argv)
        
	def main_code(self):
		if self.is_calculate_mask:
			#start to calculate the mask from raw video
			print_flush(self.base_name + " Creating temporal masked file.")
			compressSingleWorker(*self.main_input_params)
            
            #save event data as a subgroup per worm
            worm_node = features_fid.create_group(group_feat_events, 'worm_%i' % worm_index )
            worm_node._v_attrs['worm_index'] = worm_index
            worm_node._v_attrs['frame_range'] = (worm.timestamp[0], worm.timestamp[-1])
            for feat in events_data:
                tmp_data = events_data[feat]
                #consider the cases where the output is a single number, empty or None
                if isinstance(tmp_data, (float, int)): tmp_data = np.array([tmp_data])
                if tmp_data is None or tmp_data.size == 0: tmp_data = np.array([np.nan])
                features_fid.create_carray(worm_node, feat, \
                                    obj = tmp_data, filters = filters_tables)

            #save the skeletons in the same group
            features_fid.create_carray(worm_node, 'skeletons', \
                                    obj = skeletons, filters = filters_tables)

            #store the average for each worm feature
            mean_features_df[ind_N] = worm_stats
            #%%
            #report progress
            dd = " Extracting features. Worm %i of %i done." % (ind+1, tot_worms)
            print_flush(base_name + dd + ' Total time:' + progress_timer.getTimeStr())

        #create and save a table containing the averaged worm feature for each worm
        feat_mean = features_fid.create_table('/', 'features_means', obj = mean_features_df, filters=filters_tables)
        
        #flag and report a success finish
        feat_mean._v_attrs['has_finished'] = 1
        print_flush(base_name + ' Feature extraction finished: ' + progress_timer.getTimeStr())
def getIntensityProfile(masked_image_file, skeletons_file, intensities_file, 
                     width_resampling = 15, length_resampling = 131, min_num_skel = 100,
                     smooth_win = 11, pol_degree = 3, width_percentage = 0.5, save_int_maps = False):
    
    assert smooth_win > pol_degree
    assert min_num_skel > 0
    assert 0 < width_percentage < 1
    
    #we want to use symetrical distance centered in the skeleton
    if length_resampling % 2 == 0: length_resampling += 1
    if width_resampling % 2 == 0: width_resampling += 1
    
    #get the limits to be averaged from the intensity map
    if save_int_maps:
        width_win_ind = getWidthWinLimits(width_resampling, width_percentage)
    else:
        width_win_ind = (0, width_resampling)
    
    #filters for the tables structures
    table_filters = tables.Filters(complevel=5, complib='zlib', 
                                   shuffle=True, fletcher32=True)


    #Get a reduced version of the trajectories_data table with only the valid skeletons. 
    #The rows of this new table are going to be saved into skeletons_file
    trajectories_data_valid = setIntMapIndexes(skeletons_file, min_num_skel)

    #let's save this new table into the intensities file
    with tables.File(intensities_file, 'w') as fid:
        fid.create_table('/', 'trajectories_data_valid', \
            obj = trajectories_data_valid.to_records(index=False), filters=table_filters)
    
    tot_rows = len(trajectories_data_valid);
    if tot_rows == 0:
        with tables.File(intensities_file, "r+") as int_file_id:
            #nothing to do here let's save empty data and go out
            worm_int_avg_tab = int_file_id.create_array("/", "straighten_worm_intensity_median", obj=np.zeros(0))
            worm_int_avg_tab._v_attrs['has_finished'] = 1;
        return

    with tables.File(masked_image_file, 'r')  as mask_fid, \
         tables.File(skeletons_file, 'r') as ske_file_id, \
         tables.File(intensities_file, "r+") as int_file_id:
        
        #pointer to the compressed videos
        mask_dataset = mask_fid.get_node("/mask")
        
        #pointer to skeletons
        skel_tab = ske_file_id.get_node('/skeleton')
        skel_width_tab = ske_file_id.get_node('/width_midbody')
        
        filters = tables.Filters(complevel=5, complib='zlib', shuffle=True)
        
        #we are using Float16 to save space, I am assuing the intensities are between uint8
        worm_int_avg_tab = int_file_id.create_carray("/", "straighten_worm_intensity_median", \
                                   tables.Float16Atom(dflt=np.nan), \
                                   (tot_rows, length_resampling), \
                                    chunkshape = (1, length_resampling),\
                                    filters = table_filters);
        
        worm_int_avg_tab._v_attrs['has_finished'] = 0;
        worm_int_avg_tab.attrs['width_win_ind'] = width_win_ind
        
        if save_int_maps:
            worm_int_tab = int_file_id.create_carray("/", "straighten_worm_intensity", \
                                   tables.Float16Atom(dflt=np.nan), \
                                   (tot_rows, length_resampling,width_resampling), \
                                    chunkshape = (1, length_resampling,width_resampling),\
                                    filters = table_filters);
        #variables used to report progress
        base_name = skeletons_file.rpartition('.')[0].rpartition(os.sep)[-1].rpartition('_')[0]
        progressTime = timeCounterStr('Obtaining intensity maps.');        
        
        for frame, frame_data in trajectories_data_valid.groupby('frame_number'):
            img = mask_dataset[frame,:,:]
            for ii, row_data in frame_data.iterrows():
                skeleton_id = int(row_data['skeleton_id'])
                worm_index = int(row_data['worm_index_joined'])
                int_map_id = int(row_data['int_map_id'])
                
                #read ROI and skeleton, and put them in the same coordinates map
                worm_img, roi_corner = getWormROI(img, row_data['coord_x'], row_data['coord_y'], row_data['roi_size'])
                skeleton = skel_tab[skeleton_id,:,:]-roi_corner

                half_width = skel_width_tab[skeleton_id]/2
                
                assert not np.isnan(skeleton[0,0])
                
                skel_smooth = smoothSkeletons(skeleton, length_resampling = length_resampling, smooth_win = smooth_win, pol_degree = pol_degree)
                straighten_worm, grid_x, grid_y = getStraightenWormInt(worm_img, skel_smooth, half_width=half_width, width_resampling=width_resampling)
                
                #if you use the mean it is better to do not use float16
                int_avg = np.median(straighten_worm[width_win_ind[0]:width_win_ind[1],:], axis = 0)
                
                worm_int_avg_tab[int_map_id] = int_avg
                
                #only save the full map if it is specified by the user
                if save_int_maps: 
                    worm_int_tab[int_map_id]  = straighten_worm.T
        
            if frame % 500 == 0:
                progress_str = progressTime.getStr(frame)
                print_flush(base_name + ' ' + progress_str);
        
        worm_int_avg_tab._v_attrs['has_finished'] = 1;
    #variables to report progress
    base_name = skeletons_file.rpartition('.')[0].rpartition(os.sep)[-1].rpartition('_')[0]
    progress_timer = timeCounterStr('');
    
    
    bad_worms = [] #worms with not enough difference between the normal and inverted median intensity profile
    switched_blocks = [] #data from the blocks that were switched
    
    ind2check = [52] 
    for index_n, (worm_index, trajectories_worm) in enumerate(grouped_trajectories):
        if not worm_index in ind2check: continue 
        
        if index_n % 10 == 0:
            dd = " Correcting Head-Tail using intensity profiles. Worm %i of %i." % (index_n+1, tot_worms)
            dd = base_name + dd + ' Total time:' + progress_timer.getTimeStr()
            print_flush(dd)
        

        good = trajectories_worm['int_map_id']!=-1;
        int_map_id = trajectories_worm.loc[good, 'int_map_id'].values
        int_skeleton_id = trajectories_worm.loc[good, 'skeleton_id'].values
        int_frame_number = trajectories_worm.loc[good, 'frame_number'].values
        #only analyze data that contains at least  min_block_size intensity profiles     
        if int_map_id.size < min_block_size:
            continue
        
        #%%
        #read the worm intensity profiles
        with tables.File(intensities_file, 'r') as fid:
            worm_int_profile = fid.get_node('/straighten_worm_intensity_median')[int_map_id,:]
        #%%
Exemple #23
0
def getWormFeatures(skeletons_file, features_file, good_traj_index, expected_fps = 25, \
    use_skel_filter = True, use_manual_join = False, is_single_worm = False):

    if is_single_worm:
        if not isValidSingleWorm(skeletons_file, good_traj_index):
            #the stage was not aligned correctly. Return empty features file.
            good_traj_index = np.array([])

    fps, is_default_timestamp = getFPS(skeletons_file, expected_fps)
    micronsPerPixel = getMicronsPerPixel(skeletons_file)

    #function to calculate the progress time. Useful to display progress
    base_name = skeletons_file.rpartition('.')[0].rpartition(
        os.sep)[-1].rpartition('_')[0]
    #filter used for each fo the tables
    filters_tables = tables.Filters(complevel=5, complib='zlib', shuffle=True)
    #Time series
    progress_timer = timeCounterStr('')

    #get total number of valid worms and break if it is zero
    tot_worms = len(good_traj_index)
    #initialize by getting the specs data subdivision
    wStats = WormStatsClass()
    #initialize rec array with the averaged features of each worm
    mean_features_df = np.full(tot_worms, np.nan, dtype=wStats.feat_avg_dtype)
    with tables.File(features_file, 'w') as features_fid:
        #initialize groups for the timeseries and event features
        header_timeseries = {
            feat: tables.Float32Col(pos=ii)
            for ii, (feat, _) in enumerate(wStats.feat_timeseries_dtype)
        }
        table_timeseries = features_fid.create_table('/',
                                                     'features_timeseries',
                                                     header_timeseries,
                                                     filters=filters_tables)

        #save some data used in the calculation as attributes
        table_timeseries._v_attrs['micronsPerPixel'] = micronsPerPixel
        table_timeseries._v_attrs[
            'is_default_timestamp'] = is_default_timestamp
        table_timeseries._v_attrs['fps'] = fps

        #start to calculate features for each worm trajectory
        for ind_N, worm_index in enumerate(good_traj_index):
            #initialize worm object, and extract data from skeletons file
            worm = WormFromTable(skeletons_file,
                                 worm_index,
                                 use_skel_filter=use_skel_filter,
                                 use_manual_join=use_manual_join,
                                 micronsPerPixel=micronsPerPixel,
                                 fps=fps,
                                 smooth_window=5)

            if is_single_worm:
                assert worm_index == 1 and ind_N == 0
                worm = correctSingleWorm(worm, skeletons_file)

            #calculate features
            timeseries_data, events_data, worm_stats, skeletons = \
            getFeaturesOpenWorm(worm, wStats)

            #%%
            #save timeseries data
            table_timeseries.append(timeseries_data)
            table_timeseries.flush()

            #save event data as a subgroup per worm
            worm_node = features_fid.create_group('/', 'worm_%i' % worm_index)
            worm_node._v_attrs['worm_index'] = worm_index
            worm_node._v_attrs['frame_range'] = (worm.timestamp[0],
                                                 worm.timestamp[-1])

            worm_feat_events = features_fid.create_group(
                worm_node, 'features_events')
            for feat in events_data:
                tmp_data = events_data[feat]
                #consider the cases where the output is a single number, empty or None
                if isinstance(tmp_data, (float, int)):
                    tmp_data = np.array([tmp_data])
                if tmp_data is None or tmp_data.size == 0:
                    tmp_data = np.array([np.nan])
                features_fid.create_carray(worm_feat_events, feat, \
                                    obj = tmp_data, filters = filters_tables)

            #save the skeletons in the same group
            features_fid.create_carray(worm_node, 'skeletons', \
                                    obj = skeletons, filters = filters_tables)

            #store the average for each worm feature
            mean_features_df[ind_N] = worm_stats
            #%%
            #report progress
            dd = " Extracting features. Worm %i of %i done." % (ind_N + 1,
                                                                tot_worms)
            print_flush(base_name + dd + ' Total time:' +
                        progress_timer.getTimeStr())

        #create and save a table containing the averaged worm feature for each worm
        feat_mean = features_fid.create_table('/',
                                              'features_means',
                                              obj=mean_features_df,
                                              filters=filters_tables)

        #flag and report a success finish
        feat_mean._v_attrs['has_finished'] = 1
        print_flush(base_name + ' Feature extraction finished: ' +
                    progress_timer.getTimeStr())
def getWormFeatures(skeletons_file, features_file, good_traj_index, expected_fps = 25, \
    use_skel_filter = True, use_manual_join = False, is_single_worm = False):

    if is_single_worm:
        if not isValidSingleWorm(skeletons_file, good_traj_index):
            #the stage was not aligned correctly. Return empty features file.
            good_traj_index = np.array([])


    fps, is_default_timestamp = getFPS(skeletons_file, expected_fps)
    micronsPerPixel = getMicronsPerPixel(skeletons_file)
    
    
    #function to calculate the progress time. Useful to display progress 
    base_name = skeletons_file.rpartition('.')[0].rpartition(os.sep)[-1].rpartition('_')[0]
    #filter used for each fo the tables
    filters_tables = tables.Filters(complevel = 5, complib='zlib', shuffle=True)
    #Time series
    progress_timer = timeCounterStr('');
    
    #get total number of valid worms and break if it is zero
    tot_worms = len(good_traj_index)
    #initialize by getting the specs data subdivision
    wStats = WormStatsClass()
    #initialize rec array with the averaged features of each worm
    mean_features_df = np.full(tot_worms, np.nan, dtype=wStats.feat_avg_dtype)
    with tables.File(features_file, 'w') as features_fid:
        #initialize groups for the timeseries and event features
        header_timeseries = {feat:tables.Float32Col(pos=ii) for ii, (feat,_) in enumerate(wStats.feat_timeseries_dtype)}
        table_timeseries = features_fid.create_table('/', 'features_timeseries', header_timeseries, filters=filters_tables)
        
        #save some data used in the calculation as attributes
        table_timeseries._v_attrs['micronsPerPixel'] = micronsPerPixel
        table_timeseries._v_attrs['is_default_timestamp'] = is_default_timestamp
        table_timeseries._v_attrs['fps'] = fps

        #start to calculate features for each worm trajectory
        for ind_N, worm_index  in enumerate(good_traj_index):
            #initialize worm object, and extract data from skeletons file
            worm = WormFromTable(skeletons_file, worm_index,
                use_skel_filter = use_skel_filter, use_manual_join = use_manual_join,
                micronsPerPixel = micronsPerPixel,fps=fps, smooth_window = 5)
            
            if is_single_worm:
                assert worm_index == 1 and ind_N == 0
                worm = correctSingleWorm(worm, skeletons_file)
            
            #calculate features
            timeseries_data, events_data, worm_stats, skeletons = \
            getFeaturesOpenWorm(worm, wStats)

            #%%
            #save timeseries data
            table_timeseries.append(timeseries_data)
            table_timeseries.flush()
            

            
            #save event data as a subgroup per worm
            worm_node = features_fid.create_group('/', 'worm_%i' % worm_index )
            worm_node._v_attrs['worm_index'] = worm_index
            worm_node._v_attrs['frame_range'] = (worm.timestamp[0], worm.timestamp[-1])
            
            worm_feat_events = features_fid.create_group(worm_node, 'features_events')
            for feat in events_data:
                tmp_data = events_data[feat]
                #consider the cases where the output is a single number, empty or None
                if isinstance(tmp_data, (float, int)): tmp_data = np.array([tmp_data])
                if tmp_data is None or tmp_data.size == 0: tmp_data = np.array([np.nan])
                features_fid.create_carray(worm_feat_events, feat, \
                                    obj = tmp_data, filters = filters_tables)

            #save the skeletons in the same group
            features_fid.create_carray(worm_node, 'skeletons', \
                                    obj = skeletons, filters = filters_tables)

            #store the average for each worm feature
            mean_features_df[ind_N] = worm_stats
            #%%
            #report progress
            dd = " Extracting features. Worm %i of %i done." % (ind_N + 1, tot_worms)
            print_flush(base_name + dd + ' Total time:' + progress_timer.getTimeStr())

        #create and save a table containing the averaged worm feature for each worm
        feat_mean = features_fid.create_table('/', 'features_means', obj = mean_features_df, filters=filters_tables)
        
        #flag and report a success finish
        feat_mean._v_attrs['has_finished'] = 1
        print_flush(base_name + ' Feature extraction finished: ' + progress_timer.getTimeStr())