def main(parser): # read args from console args = parser.parse_args() # read source path (path of binary segmentation images) source_path = manage_path_argument(args.source_folder) # take base path and stack name base_path = os.path.dirname(os.path.dirname(source_path)) stack_name = os.path.basename(source_path) # create path and folder where save section images sections_path = os.path.join(base_path, 'xz_sections', stack_name) filled_sections_path = os.path.join(base_path, 'xz_filled_sections', stack_name) for path in [sections_path, filled_sections_path]: if not os.path.exists(path): os.makedirs(path) # portion of y axes for section estimation y_start = np.uint16(args.y_start[0]) y_stop = np.uint16(args.y_stop[0]) # preference for fill or not the holes _fill_holes = args.fill_holes print('\n\n\n _fill_holes : ', _fill_holes) # Def .txt filepath txt_parameters_path = os.path.join(base_path, 'parameters.txt') if _fill_holes: txt_results_path = os.path.join(base_path, 'Measure_analysis_filled.txt') else: txt_results_path = os.path.join(base_path, 'Measure_analysis.txt') # SCRIPT ---------------------------------------------------------------------- # print to video and write in results.txt init message init_message = [ ' **** Script for Estimation of Section Area and Volume **** \n \n' ' Source from path : {}'.format(base_path), ' Stack : {}'.format(stack_name), '\n\n *** Start processing... \n' ] error_message = '\n *** ERROR *** : stack in this path is None' with open(txt_results_path, 'w') as f: for line in init_message: print(line) f.write(line + '\n') # reads parameters parameters = extract_parameters(txt_parameters_path) # measure units x_step = parameters['res_xy'] # micron y_step = parameters['res_xy'] # micron z_step = parameters['res_z'] # micron pixel_xy_in_micron2 = x_step * y_step # micron^2 pixel_xz_in_micron2 = x_step * z_step # micron^2 voxel_in_micron3 = x_step * y_step * z_step # micron^3 # preferences _save_binary_sections = bool(parameters['save_binary_sections']) # create images stack from source path print(' *** Start to load the Stack...') # old version: # masks, mess = load_stack_into_numpy_ndarray([source_path]) # print(mess) #new version: masks = load_tif_data(source_path) if len(masks.shape) == 2: masks = np.expand_dims(masks, axis=2) # add the zeta axis # count selected sections total_sections = masks.shape[0] # row -> y -> number of sections print('\n Volume shape:', masks.shape) print('Number of total sections: ', total_sections) print('\n') # set y portion if y_stop < y_start: y_start = np.uint16(total_sections / 4) y_stop = np.uint16(total_sections * 3 / 4) print( ' *** ATTENTION : y portion selected by DEFAULT: {} -> {}'.format( y_start, y_stop)) # Every Section(y) is XZ projection of mask. Estimated Area is the sum of the Non_Zero pixel selected_sections = np.uint16(y_stop - y_start) sections_micron2 = np.zeros(selected_sections) print('Number of selected sections: ', y_stop - y_start) # Initializing to zero the Volume counter effective_myocites_volume = 0 # real estimated volume of myocites (sum of area of real cells) t_start = time.time() analyzed_section = 0 # counter, only for control the for loop (remove) with open(txt_results_path, 'a') as f: pre_info = list() pre_info.append('\nPortion of y selected: [{} -> {}]'.format( y_start, y_stop)) pre_info.append('Option for fill the holes: {}'.format(_fill_holes)) pre_info.append('\n') for l in pre_info: print(l) f.write(l + '\n') if masks is not None: # *** 1 *** - Mean Section Estimation print('\n... Estimation of mean section...') for y in range(y_start, y_stop): # extract section section = masks[y, :, :] sec_name = create_img_name_from_index(total_sections - y - 1) # img_name.tif # filled the section holes and set comment for tiff filenames if _fill_holes: section = ndimage.morphology.binary_fill_holes(section) comment = 'filled_section' dest_path = filled_sections_path else: comment = 'section' dest_path = sections_path # count cell pixel pixels_with_cell = np.count_nonzero(section.astype(bool)) if pixels_with_cell > 0: area_in_micron2 = pixels_with_cell * pixel_xz_in_micron2 sections_micron2[y - y_start] = area_in_micron2 measure = ' - {} ----> {} um^2'.format( sec_name, area_in_micron2) if _save_binary_sections: # transform point of view section = np.rot90(m=np.flipud(section), k=1, axes=(0, 1)) # save section in correct path save_tiff(img=section, img_name=sec_name, comment=comment, folder_path=dest_path) else: measure = ' - {} is empty'.format(sec_name) analyzed_section += 1 print(measure) # f.write(measure+'\n') # *** 2 *** - Volume Estimation print('\n\n ...Estimation of Volume...\n') for z in range(masks.shape[2]): # check fill option if _fill_holes: print('... filling {} xy frame'.format(z)) z_frame = ndimage.morphology.binary_fill_holes(masks[:, :, z]) else: z_frame = masks[:, :, z] # add pixels_of_real_cells of current z-slice to the counter effective_myocites_volume += np.count_nonzero(z_frame) # execution time (h, m, s) = seconds_to_min_sec(time.time() - t_start) # volumes in micron^3 effective_volume_in_micron3 = effective_myocites_volume * voxel_in_micron3 # count empty sections sections_with_cell = np.count_nonzero(sections_micron2) empties = selected_sections - sections_with_cell # Mean sections: mean_section = np.sum( sections_micron2) / sections_with_cell # (original images) # create results string result_message = list() result_message.append( '\n *** Process successfully completed, time of execution: {0:2d}h {1:2d}m {2:2d}s \n' .format(int(h), int(m), int(s))) result_message.append(' Total number of frames: {}'.format( masks.shape[2])) result_message.append(' Total sections: {}'.format(total_sections)) result_message.append( ' Selected sections: {}'.format(selected_sections)) result_message.append( ' Effective analyzed sections: {}'.format(analyzed_section)) result_message.append( ' Number of empty section: {}'.format(empties)) result_message.append( ' Number of section with cells: {}'.format(sections_with_cell)) result_message.append('\n') result_message.append( ' Mean sections: {0:.3f} um^2'.format(mean_section)) result_message.append( ' Effective miocytes tissue volume : {0:.6f} mm^3'.format( effective_volume_in_micron3 / 10**9)) result_message.append('\n') result_message.append(' \n OUTPUT SAVED IN: \n') result_message.append(txt_results_path) # write and print results for l in result_message: print(l) f.write(l + '\n') else: print(error_message) f.write(error_message) print(' \n \n \n ')
def main(parser): # --- PRELIMINARY OPERATIONS -------------------------------------------------------- # read args from console args = parser.parse_args() source_path = manage_path_argument(args.source_folder) # take base path and stack name base_path = os.path.dirname(os.path.dirname(source_path)) stack_name = os.path.basename(source_path) # Def .txt filepath txt_parameters_path = os.path.join(base_path, 'parameters.txt') txt_results_path = os.path.join(base_path, 'ALFA_volume_results.txt') txt_metadata_path = os.path.join(base_path, 'metadata.txt') process_names = [ 'clahe', 'mask_bin', 'segmented', 'contourned', 'contours' ] # create destination paths where save images destination_paths = [] for process in process_names: destination_paths.append(os.path.join(base_path, process, stack_name)) # if those folders do not exist, this creates them for path in destination_paths: if not os.path.exists(path): os.makedirs(path) # --- SCRIPT --------------------------------------------------------------- # reads parameters parameters = extract_parameters(txt_parameters_path) # read user preference (if save images or not) _save_clahe = bool(parameters['save_clahe']) _save_binary_mask = bool(parameters['save_binary_mask']) _save_segmented = bool(parameters['save_segmented']) _save_countourned = bool(parameters['save_countourned']) _save_contours = bool(parameters['save_contours']) # print to video and write in results.txt init message init_message = [ ' Source from path : {} \n'.format(base_path), ' Stack : {} \n'.format(stack_name), '\n\n - Start load the Stack, this may take a few minutes... ' ] error_message = '\n *** ERROR *** : stack in this path is None' with open(txt_results_path, 'w') as f: for line in init_message: print(line, end='') f.write(line + '\n') # measure units x_step = parameters['res_xy'] # micron y_step = parameters['res_xy'] # micron z_step = parameters['res_z'] # micron voxel_in_micron3 = x_step * y_step * z_step # micron^3 # extract stack (OLD METHOD) # volume, mess = load_stack_into_numpy_ndarray([source_path]) # img_shape = volume[:, :, 0].shape # extract stack (NEW METHOD)--------------- volume = load_tif_data(source_path) if len(volume.shape) == 2: volume = np.expand_dims(volume, axis=2) # add the zeta axis img_shape = (volume.shape[0], volume.shape[1]) # --------------------------------------------- print(' Images shape : ', img_shape, '\n') # measure of imaging volume area_of_slice = img_shape[0] * img_shape[1] number_of_slices = volume.shape[2] # Estimated Volume total_imaging_volume = area_of_slice * number_of_slices # total volume, from z=0 to z maximum # Initializing to zero the Volume counter effective_myocites_volume = 0 # real estimated volume of myocites (sum of area of real cells) # Boolean vector with length = number_of_slices. # Element i-th is: # True - if i-th slice have info # False - if i-th lice i empty slices_info = np.zeros(number_of_slices).astype( bool) # created with all False values. # save elaboration time for each iteration (for estimate mean time of elaboration) slice_elab_time_list = list() t_start = time.time() print(' EQUALIZATION and SEGMENTATION of every frame:') with open(txt_results_path, 'a') as f: if volume is not None: for z in range(number_of_slices): # extract current slice img = volume[:, :, z] img_name = create_img_name_from_index(z) # img_name.tif # check if img is empty (too black) if image_have_info(img, parameters['t_rate_info']): elab_start = time.time() slices_info[z] = True img = normalize(img) equalized_img = clahe(img, parameters, img_name, destination_paths[0], _save=_save_clahe) bw_mask, pixels_of_real_cells = create_byn_mask( equalized_img, parameters, img_name, destination_paths[1], _save=_save_binary_mask) effective_myocites_volume += pixels_of_real_cells create_and_save_segmented_images(bw_mask, equalized_img, img_name, destination_paths[2], _save=_save_segmented) contours = create_surrounded_images( bw_mask, equalized_img, img_name, destination_paths[3], _save=_save_countourned) if _save_contours: # save image with only contours for fiji visualization: save_contours(img_name, contours, bw_mask.shape, destination_paths[4]) save_contours(img_name, contours, bw_mask.shape, destination_paths[4]) slice_elab_time_list.append(time.time() - elab_start) elapsed_time = (number_of_slices - z - 1) * np.mean(slice_elab_time_list) (h, m, s) = seconds_to_min_sec(elapsed_time) measure = ' - {0} --> {1:.1f} um^3 - ET: {2:2d}h {3:2d}m {4:2d}s'.format( img_name, pixels_of_real_cells * voxel_in_micron3, int(h), int(m), int(s)) else: # black = np.zeros(img.shape) # for path in destination_paths: # save_tiff(img=black, img_name=img_name, comment='empty', folder_path=path) measure = ' - {} is black, rejected'.format(img_name) print(measure) f.write(measure + '\n') # execution time (h, m, s) = seconds_to_min_sec(time.time() - t_start) # Num of saved slices saved = np.count_nonzero(slices_info) # Num of empty slice on top = Index of first slice with info empty_on_top = np.where(slices_info == True)[0][0] # Num of empty slice on bottom = Index of first slice with info, searching from from z=z_max to z=0 empty_on_bottom = np.where(np.flipud(slices_info) == True)[0][0] # volumes in micron^3 total_imaging_volume_in_micron = total_imaging_volume * voxel_in_micron3 effective_volume_in_micron3 = effective_myocites_volume * voxel_in_micron3 # in percentage myocites_perc = 100 * effective_myocites_volume / total_imaging_volume result_message = list() result_message.append( '\n *** Process successfully completed, time of execution: {0:2d}h {1:2d}m {2:2d}s \n' .format(int(h), int(m), int(s))) result_message.append(' Number of saved slices: {}'.format(saved)) result_message.append( ' Number of rejected slices (because empty) on the top of Volume: {}' .format(empty_on_top)) result_message.append( ' Number of rejected slices (because empty) on the bottom of Volume: {}' .format(empty_on_bottom)) result_message.append( ' Total Imaging volume : {0:.6f} mm^3'.format( total_imaging_volume_in_micron / 10**9)) result_message.append( ' Effective miocytes tissue volume : {0:.6f} mm^3, {1:.3f}% of Imaging volume' .format(effective_volume_in_micron3 / 10**9, myocites_perc)) result_message.append('\n') result_message.append(' OUTPUT SAVED IN: \n') for path in destination_paths: result_message.append(path) # write and print results for l in result_message: print(l) f.write(l + '\n') # write metadata with open(txt_metadata_path, 'w') as m: m.write('empty_on_top = {}\n'.format(empty_on_top)) m.write('empty_on_bottom = {}\n'.format(empty_on_bottom)) m.write('saved = {}'.format(saved)) else: print(error_message) f.write(error_message) print(' \n \n \n ')
def main(parser): ''' Docstring (TODO) parameters ''' # ====== 0 ====== Initial operations # TODO estrare dai parametri da terminale la bool 'verbose' verbose = False # read args from console args = parser.parse_args() source_path = manage_path_argument(args.source_folder) base_path = os.path.dirname(os.path.dirname(source_path)) stack_name = os.path.basename(source_path) # Def .txt filepath txt_parameters_path = os.path.join(base_path, 'parameters.txt') txt_results_path = os.path.join(base_path, 'GAMMA_orientation_results.txt') Results_filename = 'orientation_Results.npy' Results_filepath = os.path.join(base_path, Results_filename) # print to video and write in results.txt init message init_message = [ ' ***************** GAMMA - Orientation analysis of 3D stack *****************\n' ' Source from path : {}'.format(source_path), ' Base path : {}'.format(base_path), ' Stack : {}'.format(stack_name), ] with open(txt_results_path, 'w') as f: for line in init_message: print(line) f.write(line + '\n') # reads parameters parameters = extract_parameters(txt_parameters_path) # analysis block dimension in z-axis num_of_slices_P = parameters['num_of_slices_P'] # Parameters of Acquisition System: res_z = parameters['res_z'] res_xy = parameters['res_xy'] resolution_factor = res_z / res_xy block_side = row_P = col_P = int(num_of_slices_P * resolution_factor) shape_P = np.array((row_P, col_P, num_of_slices_P)).astype(np.int32) """ ===================================================================================== __________________________ -1- OPEN STACK _______________________________________________""" loading_mess = list() loading_mess.append( ' ***** Start load the Stack, this may take a few minutes... ') # extract data (OLD METHOD) volume = load_tif_data(source_path) if len(volume.shape) == 2: volume = np.expand_dims(volume, axis=2) # add the zeta axis # extract stack (NEW METHOD)------------------- # infile = InputFile(source_path) # read virtual file (shape, dtype, ecc..) # volume = infile.whole() # load real images in RAM # # move axes from (z, y, x) -> to (r, c, z)=(y, x, z) [S.R. ZetaStitcher -> Strip Analysis] # volume = np.moveaxis(volume, 0, -1) # --------------------------------------------- loading_mess.append(' - Volume shape : {}'.format(volume.shape)) with open(txt_results_path, 'a') as f: for m in loading_mess: print(m) f.write(m + '\n') # calculate dimension shape_V = np.array(volume.shape) """ ===================================================================================== ________________________ -2- CYCLE FOR BLOCKS EXTRACTION and ANALYSIS __________________""" t_start = time.time() # create empty Result matrix R, shape_R = create_R(shape_V, shape_P) # create 3D filter mask = create_3D_filter(block_side, res_xy, parameters['sarc_length']) count = 1 # count iteration total_iter = np.prod(shape_R) print( '\n \n ***** Start iteration of analysis, expectd iterations : {} \n'. format(total_iter)) with open(txt_results_path, 'a') as f: for z in range(shape_R[2]): for r in range(shape_R[0]): for c in range(shape_R[1]): # initialize list of string lines lines = [] start_coord = create_coord_by_iter(r, c, z, shape_P) slice_coord = create_slice_coordinate(start_coord, shape_P) if verbose: lines.append('\n \n') lines.append( '- iter: {} - init_coord : {} - on total: {}'.format( count, start_coord, total_iter)) # save init info in R R[r, c, z]['id_block'] = count R[r, c, z]['init_coord'] = start_coord # extract parallelepiped parall = volume[slice_coord] # check dimension (if iteration is on border of volume, add zero_pad) parall = pad_dimension(parall, shape_P) if np.max(parall) != 0: parall = (normalize(parall)).astype( np.float32) # fft analysis work with float # analysis of parallelepiped extracted there_is_cell, there_is_freq, results = block_analysis( parall, shape_P, parameters, block_side, mask, verbose, lines) # save info in R[r, c, z] if there_is_cell: R[r, c, z]['cell_info'] = True if there_is_freq: R[r, c, z]['freq_info'] = True # save results in R for key in results.keys(): R[r, c, z][key] = results[key] else: if verbose: lines.append(' block rejected') for l in lines: print(l) count += 1 # execution time (h, m, s) = seconds_to_min_sec(time.time() - t_start) print('\n Iterations ended successfully \n') """ ===================================================================================== ________________________ -3- RESULTS ANALYSIS __________________________________""" post_proc_mess = list() # count results, rejected and accepted blocks block_with_cell = np.count_nonzero(R['cell_info']) block_with_peak = np.count_nonzero(R['freq_info']) p_rejec_cell = 100 * (1 - block_with_cell / count) p_rejec_freq_tot = 100 * (1 - block_with_peak / count) p_rejec_freq = 100 * (1 - block_with_peak / block_with_cell) post_proc_mess.append( '\n ***** End of iterations, time of execution: {0:2d}h {1:2d}m {2:2d}s \n' .format(int(h), int(m), int(s))) post_proc_mess.append('\n - Expected iterations : {}'.format(total_iter)) post_proc_mess.append(' - Total iterations : {}'.format(count - 1)) post_proc_mess.append( '\n - block with cell : {}, rejected from total: {} ({}%)'.format( block_with_cell, count - block_with_cell, p_rejec_cell)) post_proc_mess.append( ' - block with freq. info : {}' '\n rejected from total: {} ({}%)' '\n rejected from block with cell: {} ({}%)'.format( block_with_peak, count - block_with_peak, p_rejec_freq_tot, block_with_cell - block_with_peak, p_rejec_freq)) with open(txt_results_path, 'a') as f: for m in post_proc_mess: print(m) f.write(m + '\n') post_proc_mess = list() # threshold results on frequency validation parameter and save matrix mess = '\n \n *** Analysis of Results : remove block with low frequency affidability \n' post_proc_mess.append(mess) print(mess) # - 1 normalization of psd_ratio values R = parameter_normalizer(R, 'psd_ratio') mess = '- 1 - Normalization on \'psd_ratio\': complete' post_proc_mess.append(mess) print(mess) # - 2 thresholding on psd_ratio values R, before, after = threshold_par(R, parameters, 'psd_ratio') mess = '- 2 - First thresholding based on PSD Information: selected {} blocks from {}'.format( after, before) post_proc_mess.append(mess) print(mess) # - 3 outlier remotion based of orientation and psd_ratio values - NOT EXECUTED mess = '-*** NO Outlier Remotion based on PSD Information.' post_proc_mess.append(mess) print(mess) # save Result matrix np.save(Results_filepath, R) # - 4 Estimate and write local disorder inside Result Matrix R, shape_LD, isolated_value = estimate_local_disorder( R, parameters, resolution_factor) mess = '- 4 - Local Disorder estimated inside result Matrix, with grane (r, c, z): ({}, {}, {}) ' \ 'and isolated points setted with local_disorder = {}'\ .format(shape_LD[0], shape_LD[1], shape_LD[2], isolated_value) post_proc_mess.append(mess) print(mess) # se funziona tutto, salvare solo una versione di R Results_filename = 'orientation_Results_after_disorder.npy' Results_filepath = os.path.join(base_path, Results_filename) np.save(Results_filepath, R) with open(txt_results_path, 'a') as f: for m in post_proc_mess: f.write(m + '\n') del post_proc_mess """ ===================================================================================== ________________________ -4- STATISTICS __________________________________""" stat = statistics(R, parameters) result_mess = list() result_mess.append( '\n \n *** Results of statistical analysis on accepted points: \n') result_mess.append(' - {0} : {1:.3f} um^(-1)'.format( 'Mean module', stat['Mean Module'])) result_mess.append(' - {0} : {1:.3f} um'.format('Mean Period', stat['Mean Period'])) result_mess.append(' - {0} : {1:.3f} % '.format('Alignment', 100 * stat['Alignment'])) result_mess.append(' - {0} : {1:.3f} % '.format( 'XZ Dispersion (area_ratio)', 100 * stat['area_ratio'])) result_mess.append(' - {0} : {1:.3f} % '.format( 'XZ Dispersion (sum dev.std)', 100 * stat['sum_std'])) result_mess.append( ' \n \n ***************************** END GAMMA - orientation_analysis.py ********************' '\n \n \n \n ') with open(txt_results_path, 'a') as f: for l in result_mess: print(l) f.write(l + '\n')
def main(parser): # read args from console args = parser.parse_args() # read source path (path of binary segmentation images) source_path = manage_path_argument(args.source_folder) # take base path and stack name base_path = os.path.dirname(os.path.dirname(source_path)) stack_name = os.path.basename(source_path) # create path and folder where save section images sections_path = os.path.join(base_path, 'xz_sections', stack_name) filled_sections_path = os.path.join(base_path, 'xz_filled_sections', stack_name) convex_sections_path = os.path.join(base_path, 'xz_convex_sections', stack_name) for path in [sections_path, filled_sections_path, convex_sections_path]: if not os.path.exists(path): os.makedirs(path) # portion of y axes for section estimation y_start = np.uint16(args.y_start[0]) y_stop = np.uint16(args.y_stop[0]) # Def .txt filepath txt_parameters_path = os.path.join(base_path, 'parameters.txt') txt_results_path = os.path.join(base_path, 'Measure_analysis.txt') # SCRIPT ---------------------------------------------------------------------- # print to video and write in results.txt init message init_message = [' **** Script for Estimation of Real Myocardial fraction volume **** \n \n' ' Source from path : {}'.format(base_path), ' Stack : {}'.format(stack_name), '\n\n *** Start processing... \n' ] error_message = '\n *** ERROR *** : stack in this path is None' with open(txt_results_path, 'w') as f: for line in init_message: print(line) f.write(line+'\n') # reads parameters parameters = extract_parameters(txt_parameters_path) # measure units x_step = parameters['res_xy'] # micron y_step = parameters['res_xy'] # micron z_step = parameters['res_z'] # micron pixel_xz_in_micron2 = x_step * z_step # micron^2 voxel_in_micron3 = x_step * y_step * z_step # micron^3 # preferences _save_binary_sections = bool(parameters['save_binary_sections']) # load data print(' *** Start to load the Stack...') infile = InputFile(source_path) masks = infile.whole() # swap axis from ZYX to YXZ masks = np.moveaxis(masks, 0, -1) # check if it's a 3D or a 2D image (if only one frame, it's 2D and i add an empty axis if len(masks.shape) == 2: masks = np.expand_dims(masks, axis=2) # add the zeta axis # count selected sections total_sections = masks.shape[0] # row -> y -> number of sections print('\n Volume shape:', masks.shape) print('Number of total sections: ', total_sections) print('\n') # set y portion [optional] if y_start == y_start == 0: y_start = 0 y_stop = total_sections - 1 print(' *** ATTENTION : selected all the sections: {} -> {}'.format(y_start, y_stop)) if y_stop < y_start: y_start = np.uint16(total_sections / 4) y_stop = np.uint16(total_sections * 3 / 4) print(' *** ATTENTION : y portion selected by DEFAULT: {} -> {}'.format(y_start, y_stop)) # Every Section(y) is XZ projection of mask. Estimated Area is the sum of the Non_Zero pixel in the section image selected_sections = np.uint16(y_stop - y_start) sections_micron2 = np.zeros(selected_sections) # area in micron of every section print('Number of selected sections: ', y_stop-y_start) # Initializing to zero the Volume counters effective_myocites_volume = 0 # real estimated volume of myocites (sum of area of real cells in sections) filled_myocite_volume = 0 # filled tissue volume (sum of area of the sections with filled holes) global_tissue_volume = 0 # global tissue volume (sum of area of convex envelop of the sections) t_start = time.time() analyzed_section = 0 # counter, only for control the for loop (remove) with open(txt_results_path, 'a') as f: pre_info = list() pre_info.append('\nPortion of y selected: [{} -> {}]'.format(y_start, y_stop)) pre_info.append('Option for save the sections images: {}'.format(_save_binary_sections)) pre_info.append('\n') for l in pre_info: print(l) f.write(l+'\n') if masks is not None: print('\n... Estimation of mean section and Volume fraction of Myocardial Tissue...') for y in range(y_start, y_stop): # extract section section = masks[y, :, :] sec_name = create_img_name_from_index(total_sections - y - 1) # img_name.tif # count pixels of real cardiomyocyte cells of current section pixels_with_cardiomyocyte = np.count_nonzero(section) effective_myocites_volume += pixels_with_cardiomyocyte # save original sections if _save_binary_sections: # transform point of view and save save_tiff(img=np.rot90(m=np.flipud(section), k=1, axes=(0, 1)), img_name=sec_name, comment='section', folder_path=sections_path) # fill the section holes and set comment for tiff filenames (to save images) section = 255 * ndimage.morphology.binary_fill_holes(section).astype(np.uint8) # count cell pixel in the envelopped section pixels_with_filled_cell = np.count_nonzero(section.astype(bool)) filled_myocite_volume += pixels_with_filled_cell if _save_binary_sections: # transform point of view and save save_tiff(img=np.rot90(m=np.flipud(section), k=1, axes=(0, 1)), img_name=sec_name, comment='filled_section', folder_path=filled_sections_path) # create envelop (convex polygon) of section to estimate and set comment for tiff filenames section = 255 * convex_hull_image(np.ascontiguousarray(section)).astype(np.uint8) # envelop if _save_binary_sections: # transform point of view and save save_tiff(img=np.rot90(m=np.flipud(section), k=1, axes=(0, 1)), img_name=sec_name, comment='convex_section', folder_path=convex_sections_path) # count cell pixel in the enveloped section pixels_with_generic_cell = np.count_nonzero(section.astype(bool)) global_tissue_volume += pixels_with_generic_cell # estimate area of this section if pixels_with_cardiomyocyte > 0: real_area_in_micron2 = pixels_with_cardiomyocyte * pixel_xz_in_micron2 filled_area_in_micron2 = pixels_with_filled_cell * pixel_xz_in_micron2 global_area_in_micron2 = pixels_with_generic_cell * pixel_xz_in_micron2 # save in the section area list sections_micron2[y - y_start] = real_area_in_micron2 # create string messages measure = bcolors.OKBLUE + '{}'.format(os.path.basename(base_path)) + bcolors.ENDC + \ ' - {} ->'.format(sec_name) + \ 'real: {0:3.1f} um^2 - filled: {1:3.1f} um^2 - convex: {2:3.1f}'.\ format(real_area_in_micron2, filled_area_in_micron2, global_area_in_micron2) else: measure = ' - {} is empty'.format(sec_name) analyzed_section += 1 print(measure) # f.write(measure+'\n') # execution time (h, m, s) = seconds_to_min_sec(time.time() - t_start) # percentage of cardiomyocyte volumes perc_fill = 100 * effective_myocites_volume / filled_myocite_volume perc_env = 100 * effective_myocites_volume / global_tissue_volume # volumes in micron^3 effective_volume_in_micron3 = effective_myocites_volume * voxel_in_micron3 filled_volume_in_micron3 = filled_myocite_volume * voxel_in_micron3 global_tissue_volume_in_micron3 = global_tissue_volume * voxel_in_micron3 # count empty sections sections_with_cell = np.count_nonzero(sections_micron2) empties = selected_sections - sections_with_cell # Mean sections: mean_section = np.sum(sections_micron2) / sections_with_cell # (original images) # create results string result_message = list() result_message.append('\n *** Process successfully completed, time of execution: {0:2d}h {1:2d}m {2:2d}s \n'.format(int(h), int(m), int(s))) result_message.append(' Total number of frames: {}'.format(masks.shape[2])) result_message.append(' Total sections: {}'.format(total_sections)) result_message.append(' Selected sections: {}'.format(selected_sections)) result_message.append(' Effective analyzed sections: {}'.format(analyzed_section)) result_message.append(' Number of empty section: {}'.format(empties)) result_message.append(' Number of section with cells: {}'.format(sections_with_cell)) result_message.append('\n') result_message.append(' Mean sections: {0:.3f} um^2'.format(mean_section)) result_message.append('\n') result_message.append(' Myocardium volume : {0:.6f} mm^3'.format(effective_volume_in_micron3 / 10 ** 9)) result_message.append(' Filled volume : {0:.6f} mm^3'.format(filled_volume_in_micron3 / 10 ** 9)) result_message.append(' Global volume : {0:.6f} mm^3'.format(global_tissue_volume_in_micron3 / 10 ** 9)) result_message.append(' Percentage of myocardium tissue filled: {}%'.format(perc_fill)) result_message.append(' Percentage of myocardium tissue enveloped: {}%'.format(perc_env)) result_message.append('\n') result_message.append(' \n OUTPUT SAVED IN: \n') result_message.append(txt_results_path) # write and print results for l in result_message: print(l) f.write(l+'\n') else: print(error_message) f.write(error_message) print(' \n \n \n ')