예제 #1
0
def main(imgDir: Path,
         imgPattern: str,
         ffDir: Path,
         brightPattern: str,
         outDir: Path,
         darkPattern: typing.Optional[str] = None,
         photoPattern: typing.Optional[str] = None) -> None:
    ''' Start a process for each set of brightfield/darkfield/photobleach patterns '''
    # Create the FilePattern objects to handle file access
    ff_files = FilePattern(ffDir, brightPattern)
    fp = FilePattern(imgDir, imgPattern)
    if darkPattern != None and darkPattern != '':
        dark_files = FilePattern(ffDir, darkPattern)
    if photoPattern != None and photoPattern != '':
        photo_files = FilePattern(
            str(Path(ffDir).parents[0].joinpath('metadata').absolute()),
            photoPattern)

    group_by = [v for v in fp.variables if v not in ff_files.variables]
    GROUPED = group_by + ['file']

    ProcessManager.init_processes('main', 'unshade')

    for files in fp(group_by=group_by):

        flat_path = ff_files.get_matching(
            **{k.upper(): v
               for k, v in files[0].items() if k not in GROUPED})[0]['file']
        if flat_path is None:
            logger.warning("Could not find a flatfield image, skipping...")
            continue

        if darkPattern is not None and darkPattern != '':
            dark_path = dark_files.get_matching(**{
                k.upper(): v
                for k, v in files[0].items() if k not in GROUPED
            })[0]['file']

            if dark_path is None:
                logger.warning("Could not find a darkfield image, skipping...")
                continue

        if photoPattern is not None and photoPattern != '':
            photo_path = photo_files.get_matching(**{
                k.upper(): v
                for k, v in files[0].items() if k not in GROUPED
            })[0]['file']

            if photo_path is None:
                logger.warning(
                    "Could not find a photobleach file, skipping...")
                continue

        ProcessManager.submit_process(unshade_batch, files, outDir, flat_path,
                                      dark_path, photo_path)

    ProcessManager.join_processes()
예제 #2
0
def main(input_dir: pathlib.Path,
         output_dir: pathlib.Path,
         file_pattern: typing.Optional[str] = None,
         group_by: typing.Optional[str] = None,
         get_darkfield: typing.Optional[bool] = None,
         get_photobleach: typing.Optional[bool] = None,
         metadata_dir: pathlib.Path = None) -> None:

    if group_by is None:
        group_by = 'xyp'

    if get_darkfield is None:
        get_darkfield = False

    if get_photobleach is None:
        get_photobleach = False

    if file_pattern is None:
        filepattern = '.*'

    fp = FilePattern(input_dir, file_pattern)

    ProcessManager.init_processes("basic")

    for files in fp(group_by=group_by):

        ProcessManager.submit_process(basic.basic, files, output_dir,
                                      metadata_dir, get_darkfield,
                                      get_photobleach)

    ProcessManager.join_processes()
예제 #3
0
def main(
    inpDir: Path,
    filePattern: str,
    outDir: Path,
) -> None:

    ProcessManager.init_processes("main", "zarr")

    fp = FilePattern(inpDir, filePattern)

    for files in fp():
        for file in files:
            ProcessManager.submit_process(image_to_zarr, file["file"], outDir)

    ProcessManager.join_processes()
예제 #4
0
def bench(
    input_dir: Path,
    output_dir: Path,
    file_pattern: str,
    replicate: int,
):
    components_dir = output_dir.joinpath('components')
    components_dir.mkdir(exist_ok=True)

    coefficients_dir = output_dir.joinpath('csvs')
    coefficients_dir.mkdir(exist_ok=True)

    corrected_dir = output_dir.joinpath('images')
    corrected_dir.mkdir(exist_ok=True)

    heatmaps_dir = output_dir.joinpath('plots')
    heatmaps_dir.mkdir(exist_ok=True)

    channel_ordering = [1, 0, 3, 2, 4, 5, 7, 6, 8, 9]
    fp = FilePattern(input_dir, file_pattern)
    for group in fp(['c']):
        write_corrected_images(
            group=group,
            channel_ordering=channel_ordering,
            components_dir=components_dir,
            output_dir=corrected_dir,
        )
        plot_pearson_coefficients(
            group=group,
            pattern=file_pattern,
            channel_ordering=channel_ordering,
            corrected_dir=corrected_dir,
            selector_name='HighMeanIntensity',
            heatmaps_dir=heatmaps_dir,
            replicate=replicate,
        )
    return
예제 #5
0
        '%(asctime)s - %(name)s - Process [{0},{1},{2}] - %(levelname)s - %(message)s'
        .format(R, T, C),
        datefmt='%d-%b-%y %H:%M:%S')
    logger = logging.getLogger("BaSiC")
    logger.setLevel(logging.INFO)

    # Start the javabridge
    log_config = Path(__file__).parent.joinpath("log4j.properties")
    jutil.start_vm(args=[
        "-Dlog4j.configuration=file:{}".format(str(log_config.absolute()))
    ],
                   class_path=bioformats.JARS)

    # Parse files into list to access by variable
    regex, variables = get_regex(inp_regex)
    test = FilePattern(fpath, inp_regex)
    files = [i['file'] for i in test.get_matching(R=R, T=T, C=C)]

    # Load files and sort
    logger.info('Loading and sorting images...')
    img_stk, X, Y = _get_resized_image_stack(files)
    img_stk_sort = np.sort(img_stk)

    # Initialize options
    new_options = _initialize_options(img_stk_sort, get_darkfield, OPTIONS)

    # Initialize flatfield/darkfield matrices
    logger.info('Beginning flatfield estimation')
    flatfield_old = np.ones((new_options['size'], new_options['size']),
                            dtype=np.float64)
    darkfield_old = np.random.normal(size=(new_options['size'],
예제 #6
0
                        help='Filename pattern used to separate data', required=True)
    parser.add_argument('--inpDir', dest='inpDir', type=str,
                        help='Input image collection to be processed by this plugin', required=True)
    parser.add_argument('--outDir', dest='outDir', type=str,
                        help='Output collection', required=True)
    
    # Parse the arguments
    args = parser.parse_args()
    filePattern = args.filePattern
    if not filePattern.strip():
        filePattern = '.*'
    logger.info('filePattern = {}'.format(filePattern))
    inpDir = args.inpDir
    logger.info('inpDir = {}'.format(inpDir))
    outDir = args.outDir
    logger.info('outDir = {}'.format(outDir))
    
    # Get all file names in inpDir image collection
    fp = FilePattern(inpDir,pattern=filePattern)

    # Loop through files in inpDir image collection and process
    for files in fp():
        if isinstance(files,list):
            # files is a list of file dictionaries
            for f in files:
                input_path = Path(f['file'])
                output_path = Path(outDir).joinpath(input_path.name)
                logger.info('Copying file: {}'.format(input_path.name))
                shutil.copy2(str(input_path.absolute()), str(output_path.absolute()))    
    logger.info('Finished copying all files!')
예제 #7
0
def main(pattern: str,
         inpDir: pathlib.Path,
         layout: typing.List[str],
         outDir: pathlib.Path,
         imageSpacing: typing.Optional[int] = None,
         gridSpacing: typing.Optional[int] = None
         ) -> None:
    
    global SPACING
    global MULTIPLIER
    
    # Set new image spacing and grid spacing arguments if present
    if image_spacing != None:
        SPACING = int(image_spacing)
    if grid_spacing != None:
        MULTIPLIER = int(grid_spacing)

    # Set up the file pattern parser
    logger.info('Parsing the file pattern...')
    fp = FilePattern(inpDir,pattern)

    # Parse the layout
    logger.info('Parsing the layout...')
    regex, variables = get_regex(pattern)
    layout = layout.replace(' ','')
    layout = layout.split(',')

    for l in layout: # Error checking
        for v in l:
            if v not in VARIABLES:
                logger.error("Variables must be one of {}".format(VARIABLES))
                raise ValueError("Variables must be one of {}".format(VARIABLES))
        if len(layout)>2 or len(layout)<1:
            logger.error("Each layout subgrid must have one or two variables assigned to it.")
            raise ValueError("Each layout subgrid must have one or two variables assigned to it.")

    for v in reversed(variables): # Add supergrids if a variable is undefined in layout
        is_defined = False
        for l in layout:
            if v in l:
                is_defined = True
                break
        if not is_defined:
            layout.append(v)

    # Layout dimensions, used to calculate positions later on
    layout_dimensions = {'grid_size':[[] for r in range(len(layout))],  # number of tiles in each dimension in the subgrid
                         'size':[[] for r in range(len(layout))],       # total size of subgrid in pixels
                         'tile_size':[[] for r in range(len(layout))]}  # dimensions of each tile in the grid

    # Get the size of each image
    logger.info('Get the size of every image...')
    grid_width = 0
    grid_height = 0
    for files in fp(group_by=layout[0]):
        # Determine number of rows and columns in the smallest subgrid
        grid_size = _get_xy_index(files,layout[0],layout)
        layout_dimensions['grid_size'][len(layout)-1].append(grid_size)

        # Get the height and width of each image
        for f in files:
            f['width'], f['height'] = BioReader.image_size(f['file'])

            if grid_width < f['width']:
                grid_width = f['width']
            if grid_height < f['height']:
                grid_height = f['height']
        logger.info('Got the size of {} images...'.format(len(files)))

        # Set the pixel and tile dimensions
        layout_dimensions['tile_size'][len(layout)-1].append([grid_width,grid_height])
        layout_dimensions['size'][len(layout)-1].append([grid_width*grid_size[0],grid_height*grid_size[1]])

    # Find the largest subgrid size for the lowest subgrid
    grid_size = [0,0]
    for g in layout_dimensions['grid_size'][len(layout)-1]:
        if g[0] > grid_size[0]:
            grid_size[0] = g[0]
        if g[1] > grid_size[1]:
            grid_size[1] = g[1]
    tile_size = [0,0]
    for t in layout_dimensions['tile_size'][len(layout)-1]:
        if t[0] > tile_size[0]:
            tile_size[0] = t[0]
        if t[1] > tile_size[1]:
            tile_size[1] = t[1]
    layout_dimensions['grid_size'][len(layout)-1] = grid_size
    layout_dimensions['tile_size'][len(layout)-1] = [tile_size[0] + SPACING, tile_size[1] + SPACING]
    layout_dimensions['size'][len(layout)-1] = [layout_dimensions['grid_size'][len(layout)-1][0] * layout_dimensions['tile_size'][len(layout)-1][0],
                                                layout_dimensions['grid_size'][len(layout)-1][1] * layout_dimensions['tile_size'][len(layout)-1][1]]
    logger.info('Grid size for layer ({}): {}'.format(layout[0],grid_size))

    # Build the rest of the subgrid indexes
    for i in range(1,len(layout)):
        # Get the largest size subgrid image in pixels
        index = len(layout) - 1 - i
        layout_dimensions['tile_size'][index] = layout_dimensions['size'][index+1]

        for files in fp(group_by=''.join(layout[:i+1])):
            # determine number of rows and columns in the current subgrid
            grid_size = _get_xy_index(files,layout[i],layout)
            layout_dimensions['grid_size'][index].append(grid_size)

        # Get the current subgrid size
        grid_size = [0,0]
        for g in layout_dimensions['grid_size'][index]:
            if g[0] > grid_size[0]:
                grid_size[0] = g[0]
            if g[1] > grid_size[1]:
                grid_size[1] = g[1]
        layout_dimensions['grid_size'][index] = grid_size
        layout_dimensions['tile_size'][index] = [layout_dimensions['tile_size'][index][0] + (MULTIPLIER**i) * SPACING, layout_dimensions['tile_size'][index][1] + (MULTIPLIER**i) * SPACING]
        layout_dimensions['size'][len(layout)-1] = [layout_dimensions['grid_size'][index][0] * layout_dimensions['tile_size'][index][0],
                                                    layout_dimensions['grid_size'][index][1] * layout_dimensions['tile_size'][index][1]]
        logger.info('Grid size for layer ({}): {}'.format(layout[i],grid_size))

    # Build stitching vector
    logger.info('Building the stitching vector....')
    fpath = str(pathlib.Path(outDir).joinpath("img-global-positions-1.txt").absolute())
    max_dim = len(layout_dimensions['grid_size'])-1
    with open(fpath,'w') as fw:
        correlation = 0
        for file in fp():
            f = file[0]
            file_name = pathlib.Path(f['file']).name

            # Calculate the image position
            gridX = 0
            gridY = 0
            posX = 0
            posY = 0
            for i in reversed(range(max_dim + 1)):
                posX += f[str(i) + '_gridX'] * layout_dimensions['tile_size'][i][0]
                posY += f[str(i) + '_gridY'] * layout_dimensions['tile_size'][i][1]
                if i == max_dim:
                    gridX += f[str(i) + '_gridX']
                    gridY += f[str(i) + '_gridY']
                else:
                    gridX += f[str(i) + '_gridX'] * layout_dimensions['grid_size'][i+1][0]
                    gridY += f[str(i) + '_gridY'] * layout_dimensions['grid_size'][i+1][1]
            
            # Write the position to the stitching vector
            fw.write("file: {}; corr: {}; position: ({}, {}); grid: ({}, {});\n".format(file_name,
                                                                                        correlation,
                                                                                        posX,
                                                                                        posY,
                                                                                        gridX,
                                                                                        gridY))

    logger.info('Done!')
예제 #8
0
def basic(files: typing.List[Path],
          out_dir: Path,
          metadata_dir: typing.Optional[Path] = None,
          darkfield: bool = False,
          photobleach: bool = False):

    # Try to infer a filename
    try:
        pattern = infer_pattern([f['file'].name for f in files])
        fp = FilePattern(files[0]['file'].parent,pattern)
        base_output = fp.output_name()
        
    # Fallback to the first filename
    except:
        base_output = files[0]['file'].name
        
    extension = ''.join(files[0]['file'].suffixes)

    with ProcessManager.process(base_output):

        # Load files and sort
        ProcessManager.log('Loading and sorting images...')
        img_stk,X,Y = _get_resized_image_stack(files)
        img_stk_sort = np.sort(img_stk)
        
        # Initialize options
        new_options = _initialize_options(img_stk_sort,darkfield,OPTIONS)

        # Initialize flatfield/darkfield matrices
        ProcessManager.log('Beginning flatfield estimation')
        flatfield_old = np.ones((new_options['size'],new_options['size']),dtype=np.float64)
        darkfield_old = np.random.normal(size=(new_options['size'],new_options['size'])).astype(np.float64)
        
        # Optimize until the change in values is below tolerance or a maximum number of iterations is reached
        for w in range(new_options['max_reweight_iterations']):
            # Optimize using inexact augmented Legrangian multiplier method using L1 loss
            A, E1, A_offset = _inexact_alm_l1(copy.deepcopy(img_stk_sort),new_options)

            # Calculate the flatfield/darkfield images and update training weights
            flatfield, darkfield, new_options = _get_flatfield_and_reweight(A,E1,A_offset,new_options)

            # Calculate the change in flatfield and darkfield images between iterations
            mad_flat = np.sum(np.abs(flatfield-flatfield_old))/np.sum(np.abs(flatfield_old))
            temp_diff = np.sum(np.abs(darkfield - darkfield_old))
            if temp_diff < 10**-7:
                mad_dark =0
            else:
                mad_dark = temp_diff/np.max(np.sum(np.abs(darkfield_old)),initial=10**-6)
            flatfield_old = flatfield
            darkfield_old = darkfield

            # Stop optimizing if the change in flatfield/darkfield is below threshold
            ProcessManager.log('Iteration {} loss: {}'.format(w+1,mad_flat))
            if np.max(mad_flat,initial=mad_dark) < new_options['reweight_tol']:
                break

        # Calculate photobleaching effects if specified
        if photobleach:
            pb = _get_photobleach(copy.deepcopy(img_stk),flatfield,darkfield)

        # Resize images back to original image size
        ProcessManager.log('Saving outputs...')
        flatfield = cv2.resize(flatfield,(Y,X),interpolation=cv2.INTER_CUBIC).astype(np.float32)
        if new_options['darkfield']:
            darkfield = cv2.resize(darkfield,(Y,X),interpolation=cv2.INTER_CUBIC).astype(np.float32)
        
        # Export the flatfield image as a tiled tiff
        flatfield_out = base_output.replace(extension,'_flatfield' + extension)
        
        with BioReader(files[0]['file'],max_workers=2) as br:
            metadata = br.metadata
        
        with BioWriter(out_dir.joinpath(flatfield_out),metadata=metadata,max_workers=2) as bw:
            bw.dtype = np.float32
            bw.x = X
            bw.y = Y
            bw[:] = np.reshape(flatfield,(Y,X,1,1,1))
        
        # Export the darkfield image as a tiled tiff
        if new_options['darkfield']:
            darkfield_out = base_output.replace(extension,'_darkfield' + extension)
            with BioWriter(out_dir.joinpath(darkfield_out),metadata=metadata,max_workers=2) as bw:
                bw.dtype = np.float32
                bw.x = X
                bw.y = Y
                bw[:] = np.reshape(darkfield,(Y,X,1,1,1))
            
        # Export the photobleaching components as csv
        if photobleach:
            offsets_out = base_output.replace(extension,'_offsets.csv')
            with open(metadata_dir.joinpath(offsets_out),'w') as fw:
                fw.write('file,offset\n')
                for f,o in zip(files,pb[0,:].tolist()):
                    fw.write("{},{}\n".format(f,o))
예제 #9
0
            'Oh no! Something went wrong:',
            *_error_messages,
            'See the README for more details.',
        ))
        logger.error(_message)
        raise ValueError(_message)

    logger.info(f'inpDir = {_input_dir}')
    logger.info(f'filePattern = {_pattern}')
    logger.info(f'groupBy = {_group_by}')
    logger.info(f'selectionCriterion = {_selector_name}')
    logger.info(f'model = {_model_name}')
    logger.info(f'channelOverlap = {_channel_overlap}')
    logger.info(f'kernelSize = {_kernel_size}x{_kernel_size}')
    logger.info(f'channelOrdering = {_channel_ordering}')
    logger.info(f'outDir = {_output_dir}')
    logger.info(f'csvDir = {_csv_dir}')

    _fp = FilePattern(_input_dir, _pattern)
    _kwargs = dict(
        pattern=_pattern,
        selector_name=_selector_name,
        model_name=_model_name,
        channel_overlap=_channel_overlap,
        kernel_size=_kernel_size,
        channel_ordering=_channel_ordering,
        output_dir=_output_dir,
        metadata_dir=_csv_dir,
    )
    main(_fp, _group_by, _kwargs)
예제 #10
0
    vectorInMetadata = args.vectorInMetadata == 'true'
    logger.info('vectorInMetadata = {}'.format(vectorInMetadata))
    if vectorInMetadata:
        outVectors = Path(outImages).joinpath('metadata_files')
        outVectors.mkdir()
        outVectors = str(outVectors.absolute())
        outImages = Path(outImages).joinpath('images')
        outImages.mkdir()
        outImages = str(outImages.absolute())
    else:
        outVectors = args.outVectors
    logger.info('outImages = {}'.format(outImages))
    logger.info('outVectors = {}'.format(outVectors))

    # Set up the fileparser
    fp = FilePattern(inpDir,'.*.ome.tif')

    # Parse the stitching vector
    logger.info('Parsing stitching vectors...')
    widths, heights = _parse_stitch(vector,fp)

    # Parse the features
    logger.info('Parsing features...')
    feature_list = _parse_features(features,fp,method)

    # Determine the min, max, and unique values for each data set
    logger.info('Setting feature scales...')
    feature_mins = {}
    feature_ranges = {}
    for key,val in feature_list.items():
        valid_vals = [v for v in val if v is not 'NaN']
예제 #11
0
    outDir = args.outDir
    logger.info('outDir = {}'.format(outDir))
    image_spacing = args.imageSpacing
    logger.info('image_spacing = {}'.format(image_spacing))
    grid_spacing = args.gridSpacing
    logger.info('grid_spacing = {}'.format(grid_spacing))
    
    # Set new image spacing and grid spacing arguments if present
    if image_spacing != None:
        SPACING = int(image_spacing)
    if grid_spacing != None:
        MULTIPLIER = int(grid_spacing)

    # Set up the file pattern parser
    logger.info('Parsing the file pattern...')
    fp = FilePattern(inpDir,pattern)
    
    # Parse the layout
    logger.info('Parsing the layout...')
    regex, variables = get_regex(pattern)
    layout = layout.replace(' ','')
    layout = layout.split(',')

    for l in layout: # Error checking
        for v in l:
            if v not in VARIABLES:
                logger.error("Variables must be one of {}".format(VARIABLES))
                ValueError("Variables must be one of {}".format(VARIABLES))
        if len(layout)>2 or len(layout)<1:
            logger.error("Each layout subgrid must have one or two variables assigned to it.")
            ValueError("Each layout subgrid must have one or two variables assigned to it.")
예제 #12
0
                    v))
        if darkPattern != None and darkPattern != '':
            if (v in dark_variables) != (
                    v in img_variables):  # v must be in both or neither (xor)
                logger.error(
                    'Variable {} is not in both darkPattern and imgPattern.'.
                    format(v))
        if photoPattern != None and photoPattern != '':
            if (v in photo_variables) != (
                    v in img_variables):  # v must be in both or neither (xor)
                logger.error(
                    'Variable {} is not in both photoPattern and imgPattern.'.
                    format(v))
    ''' Start a process for each set of brightfield/darkfield/photobleach patterns '''
    # Create the FilePattern objects to handle file access
    ff_files = FilePattern(ffDir, brightPattern)
    if darkPattern != None and darkPattern != '':
        dark_files = FilePattern(ffDir, darkPattern)
    if photoPattern != None and photoPattern != '':
        photo_files = FilePattern(
            str(Path(ffDir).parents[0].joinpath('metadata').absolute()),
            photoPattern)

    # Initialize variables for process management
    processes = []
    process_timer = []
    pnum = 0
    total_jobs = len([p for p in ff_files.iterate()])

    # Loop through files in ffDir image collection and process
    base_pstring = "python3 apply_flatfield.py --inpDir {} --outDir {} --filepattern {}".format(
예제 #13
0
    darkfield = args.darkfield
    photobleach = args.photobleach
    R = int(args.R)
    T = int(args.T)
    C = int(args.C)
    ''' Initialize the logger '''
    logging.basicConfig(
        format=
        '%(asctime)s - %(name)-8s - Process [{0},{1},{2}] - %(levelname)-8s - %(message)s'
        .format(R, T, C),
        datefmt='%d-%b-%y %H:%M:%S')
    logger = logging.getLogger("do_flat")
    logger.setLevel(logging.INFO)

    # Set up the FilePattern object
    images = FilePattern(inpDir, filepattern)
    ''' Start the javabridge '''
    logger.info("Starting the javabridge...")
    log_config = Path(__file__).parent.joinpath("log4j.properties")
    jutil.start_vm(args=[
        "-Dlog4j.configuration=file:{}".format(str(log_config.absolute()))
    ],
                   class_path=bioformats.JARS)
    ''' Load the flatfielding data '''
    logger.info("Loading the flatfield data...")
    flat_br = BioReader(brightfield)
    flat_image = np.squeeze(flat_br.read_image())
    del flat_br

    # Normalize the brightfield image if it isn't done already
    flat_image = flat_image.astype(np.float32)
예제 #14
0
                        dest='outDir',
                        type=str,
                        help='Output collection',
                        required=True)

    # Parse the arguments
    args = parser.parse_args()
    filePattern = args.filePattern
    logger.info('filePattern = {}'.format(filePattern))
    inpDir = args.inpDir
    logger.info('inpDir = {}'.format(inpDir))
    outDir = args.outDir
    logger.info('outDir = {}'.format(outDir))

    # Get all file names in inpDir image collection
    inpDir_files = FilePattern(inpDir, filePattern)

    # Loop through files in inpDir image collection and process
    for files in inpDir_files.iterate():
        if isinstance(files, list):
            # if a filename pattern is used, then files is a list of file dictionaries
            for f in files:
                input_path = Path(f['file'])
                output_path = Path(outDir).joinpath(input_path.name)
                logger.info('Copying file: {}'.format(input_path.name))
                shutil.copy(str(input_path.absolute()),
                            str(output_path.absolute()))
        else:
            # if no filename pattern was used, only a single file dictionary is returned
            input_path = Path(files['file'])
            output_path = Path(outDir).joinpath(input_path.name)
예제 #15
0
def main():
    """ Initialize argument parser """
    logger.info("Parsing arguments...")
    parser = argparse.ArgumentParser(
        prog='main',
        description='Calculate flatfield information from an image collection.'
    )
    """ Define the arguments """
    parser.add_argument(
        '--inpDir',  # Name of the bucket
        dest='inpDir',
        type=str,
        help='Path to input images.',
        required=True)
    parser.add_argument(
        '--darkfield',  # Path to the data within the bucket
        dest='darkfield',
        type=str,
        help='If true, calculate darkfield contribution.',
        required=False)
    parser.add_argument(
        '--photobleach',  # Path to the data within the bucket
        dest='photobleach',
        type=str,
        help='If true, calculates a photobleaching scalar.',
        required=False)
    parser.add_argument(
        '--inpRegex',  # Output directory
        dest='inp_regex',
        type=str,
        help='Input file name pattern.',
        required=False)
    parser.add_argument(
        '--outDir',  # Output directory
        dest='output_dir',
        type=str,
        help='The output directory for the flatfield images.',
        required=True)
    """ Get the input arguments """
    args = parser.parse_args()
    fpath = args.inpDir
    """Checking if there is images subdirectory"""
    if (Path.is_dir(Path(args.inpDir).joinpath('images'))):
        fpath = Path(args.inpDir).joinpath('images')
    get_darkfield = str(args.darkfield).lower() == 'true'
    output_dir = Path(args.output_dir).joinpath('images')
    output_dir.mkdir(exist_ok=True)
    metadata_dir = Path(args.output_dir).joinpath('metadata_files')
    metadata_dir.mkdir(exist_ok=True)
    inp_regex = args.inp_regex
    get_photobleach = str(args.photobleach).lower() == 'true'

    logger.info('input_dir = {}'.format(fpath))
    logger.info('get_darkfield = {}'.format(get_darkfield))
    logger.info('get_photobleach = {}'.format(get_photobleach))
    logger.info('inp_regex = {}'.format(inp_regex))
    logger.info('output_dir = {}'.format(output_dir))
    # Set up lists for tracking processes
    processes = []
    process_timer = []
    pnum = 0
    # Iterator to group files with  constant r,t and c values
    file = FilePattern(fpath, inp_regex)
    total_no = len(list(file.iterate(group_by='xyz')))
    for i in file.iterate(group_by='xyz'):
        if len(processes) >= multiprocessing.cpu_count() - 1:
            free_process = -1
            while free_process < 0:
                for process in range(len(processes)):
                    if processes[process].poll() is not None:
                        free_process = process
                        break
                # Wait between checks to free up some processing power
                time.sleep(3)
            pnum += 1
            logger.info("Finished process {} of {} in {}s!".format(
                pnum, total_no,
                time.time() - process_timer[free_process]))
            del processes[free_process]
            del process_timer[free_process]

        logger.info("Starting process [r,t,c]: [{},{},{}]".format(
            i[0]['r'], i[0]['t'], i[0]['c']))
        processes.append(
            subprocess.Popen(
                "python3 basic.py --inpDir {} --outDir {} --darkfield {} --photobleach {} --inpRegex {} --R {} --T {} --C {}"
                .format(fpath, args.output_dir, get_darkfield, get_photobleach,
                        inp_regex, i[0]['r'], i[0]['t'], i[0]['c']),
                shell=True))
        process_timer.append(time.time())
    while len(processes) > 1:
        free_process = -1
        while free_process < 0:
            for process in range(len(processes)):
                if processes[process].poll() is not None:
                    free_process = process
                    break
            # Wait between checks to free up some processing power
            time.sleep(3)
        pnum += 1
        logger.info("Finished process {} of {} in {}s!".format(
            pnum, total_no,
            time.time() - process_timer[free_process]))
        del processes[free_process]
        del process_timer[free_process]

    processes[0].wait()

    logger.info("Finished process {} of {} in {}s!".format(
        total_no, total_no,
        time.time() - process_timer[0]))
    logger.info("Finished all processes!")
예제 #16
0
def parse_collection(directory_path, file_pattern, registration_variable,
                     similarity_variable, template_image):
    """
    This function parses the input directory and returns a dictionary. Each key in the dictionary is a tuple 
    consisting of a template and a moving image. The value corresponding to each key is a list of images that have 
    similar transformation as the moving image. 
    Note: The code produces the expected output when len(registration_variable)==len(similarity_variable)==1.
          The code will NOT spit out an error when the more than one variable is passed as registration or
          similarity variable, but additional testing needs to be done to validate the script for this usecase.
    
    inputs : 
        directory_path: path to the input collection
        file_pattern: file name pattern of the input images
        registration_variable : variable to help determine the set of moving and template images
        similarity variable: variable to help determine the set of images having a similar transformation
                             corresponding to each set of moving and template images
        template_image: name of a template image
    
    outputs : result_dic 
              example of result_dic is shown below
         
    result_dic = {  (template_img1 : moving_img1) : [set1_img1,set1_img2, set1_img3....],
                    (template_img2 : moving_img2) : [set2_img1,set2_img2, set2_img3....],
                                                  .
                                                  .                                     }
      

                           
    """

    # Predefined variables order
    #var_order = 'rtczyx'

    # get all variables in the file pattern
    _, variables = get_regex(file_pattern)

    # get variables except the registration and similarity variable
    moving_variables = [
        var for var in variables
        if var not in registration_variable and var not in similarity_variable
    ]

    # uvals is dictionary with all the possible variables as key
    # corresponding to each key is a list of all values which that variable can take for the input collection
    _, uvals = parse_directory(directory_path, file_pattern)

    parser_object = FilePattern(directory_path, file_pattern)

    image_set = []

    # extract the index values from uvals for each variable in moving_variables
    moving_variables_set = [uvals[var] for var in moving_variables]

    # iterate over the similar transformation variables
    # Code produced expected output when len(registration_variable)==len(similarity_variable)==1
    # refer to function description
    for char in similarity_variable:

        # append the variable to the moving variable set
        moving_variables.append(char)

        # iterate over all possible index values of the similar transf. variable
        for ind in uvals[char]:
            registration_set = []

            # append the fixed value of the index to the moving variables set
            moving_variables_set.append([ind])

            # get all the possible combinations of the index values in the moving variables set
            registration_indices_combinations = list(
                itertools.product(*moving_variables_set))
            all_dicts = []

            # iterate over all combinations and create a dictionary for each combination
            # the dictionary is of the form {'C'=1, 'X'=2...etc} which can be used as an input
            # to the get_matching() function
            for index_comb in registration_indices_combinations:
                inter_dict = {}
                for i in range(len(moving_variables)):
                    inter_dict.update(
                        {moving_variables[i].upper(): index_comb[i]})
                # store all dictionaries
                all_dicts.append(inter_dict)

            # iterate over all dictionaries
            for reg_dict in all_dicts:
                intermediate_set = []
                # use get_matching function to get all filenames with defined variable values in the dictionary
                files = parser_object.get_matching(**reg_dict)

                # files is a list of dictionaries
                for file_dict in files:
                    intermediate_set.append(file_dict['file'])
                registration_set.append(intermediate_set)

            # delete the fixed index value of the similar transf. variable to prepare for the next iteration
            moving_variables_set.pop(-1)
            image_set.append(registration_set)

    # parse image set to form the result dictionary
    result_dic = {}
    old_set = np.array(image_set)
    for j in range(old_set.shape[1]):
        inter = old_set[:, j, :]
        for k in range(inter.shape[1]):
            ky = (inter[0, 0], inter[0, k])
            items = inter[1:, k]
            result_dic.update({ky: items})

    return result_dic