def main():
    coloredlogs.install(level='INFO',
                        fmt='%(levelname)s [%(name)s]: %(message)s')

    args = parse_args()

    logger.info('loading {}'.format( args.input_file))
    infile = InputFile(args.input_file)

    a = infile.whole()
    a = a[::-1]

    logger.info('writing to {}'.format(args.output_file))
    tiff.imsave(args.output_file, a)
Exemple #2
0
def CLAHE(parser):
    print('** =========== **')
    print('** START CLAHE **')
    print('** =========== **')
    args = parser.parse_args()

    # extract data
    infile = InputFile(args.source)
    data = infile.whole()

    # sizes
    (num_of_slices, height, weight) = infile.shape
    ksize = nextpow2(weight / 8) if args.kernel == 0 else args.kernel

    # extract path and filename
    base_path = os.path.dirname(os.path.dirname(args.source))
    filename = os.path.splitext(os.path.basename(args.source))[0]

    # create destination paths where save result
    destination_path = os.path.join(base_path,
                                    'clahed_c{}_k{}'.format(args.clip, ksize))
    if not os.path.exists(destination_path):
        os.makedirs(destination_path)

    # print informations
    print('\n ** PATHS : ')
    print(' - source : {}'.format(args.source))
    print(' - output : {}'.format(destination_path))
    print('\n ** FILENAME: {}'.format(filename))
    print('\n ** CLAHE PARAMETERS : ')
    print(' - clip: {}'.format(args.clip))
    print(' - ksize: {}'.format(ksize))

    print('\n ** OUTPUT FORMAT:')
    if args.image_sequence:
        print(' - output is saved like a 2d tiff images sequence')
    else:
        print(' - output is saved ike a 3D tif files')

    # output array
    if not args.image_sequence:
        clahed = np.zeros_like(data)

    print()
    # Execution
    for z in range(num_of_slices):
        img = normalize(data[z, ...])
        img_eq = normalize(
            exposure.equalize_adapthist(image=img,
                                        kernel_size=ksize,
                                        clip_limit=args.clip))

        if args.image_sequence:
            img_name = create_img_name_from_index(z, post="_clahe")
            save_tiff(img=img_eq,
                      img_name=img_name,
                      prefix='',
                      comment='',
                      folder_path=destination_path)
            print(img_name)
        else:
            clahed[z, ...] = img_eq
            print('z = {}'.format(z))

    # save output
    if not args.image_sequence:
        save_tiff(clahed, os.path.join(destination_path, 'clahed'))
    print(' \n ** Process Finished \n')
Exemple #3
0
def main():
    args = parse_args()

    infile = InputFile(args.input_file)
    ashape = np.flipud(np.array(infile.shape))  # X, Y, Z order

    M_inv, final_shape = inv_matrix(
        shape=ashape,
        theta=args.theta,
        direction=args.direction,
        view=args.view,
        z=args.z,
        xy=args.xy
    )

    logger.info('input_shape: {}, output_shape: {}'
                .format(infile.shape, tuple(final_shape)))

    if os.path.exists(args.output_file):
        logger.warning('Output file {} already exists'.format(args.output_file))
        if not args.force:
            logger.error('(use -f to force)')
            return

    output_dir = os.path.dirname(args.output_file)
    if output_dir:
        os.makedirs(output_dir, exist_ok=True)

    total_byte_size = np.asscalar(np.prod(final_shape) * infile.dtype.itemsize)
    bigtiff = total_byte_size > 2 ** 31 - 1

    logger.info('loading {}'.format(args.input_file))

    a = infile.whole()

    threads = []

    if args.jp2ar_enabled:
        p = Path(args.output_file).with_suffix('.zip')
        logger.info('saving JP2000 ZIP archive to {}'.format(p))
        jp2ar_thread = threading.Thread(target=convert_to_jp2ar, kwargs=dict(
            input_data=a, output_dir=None, compression=args.jp2_compression,
            nthreads=args.nthreads, temp_dir=None, output_file=str(p)))
        jp2ar_thread.start()
        threads.append(jp2ar_thread)

    def worker():
        if args.slices is None:
            t = transform(a.T, M_inv, final_shape)  # X, Y, Z order
            logger.info('saving to {}'.format(args.output_file))
            tiff.imwrite(args.output_file, t.T, bigtiff=bigtiff)
            return

        if os.path.exists(args.output_file):
            os.remove(args.output_file)

        i = 0
        for t in sliced_transform(a, M_inv, final_shape, args.slices):
            i += 1
            logger.info('saving slice {}/{} to {}'.format(
                i, args.slices, args.output_file))

            t = t.T  # Z, Y, X order

            # add dummy color axis to trick imsave
            # (otherwise when size of Z is 3, it thinks it's an RGB image)
            t = t[:, np.newaxis, ...]
            tiff.imwrite(args.output_file, t, append=True, bigtiff=bigtiff)

    transform_thread = threading.Thread(target=worker)
    transform_thread.start()
    threads.append(transform_thread)

    for thread in threads:
        thread.join()
Exemple #4
0
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 ')