def downsample_stack_file(cls, stack_file, side, output_stack_file=None, mask_file=None): if output_stack_file is None: output_stack_file = set_output_name(stack_file, 'downsampled') if os.path.exists(output_stack_file): raise FileExistsError( f"output file '{yellow(output_stack_file)}' already exists!") if mask_file: if not os.path.exists(mask_file): logger.error(f"mask file {yellow(mask_file)} doesn't exist!") mask = load_stack_from_file(mask_file) else: mask = None stack = load_stack_from_file(stack_file) downsampled_stack = cls.downsample(stack, side, compute_fx=False, stack=True, mask=mask) logger.info( f"downsampled stack from size {stack.shape} to {downsampled_stack.shape}." f" saving to {yellow(output_stack_file)}..") with mrcfile.new(output_stack_file) as mrc_fh: mrc_fh.set_data(downsampled_stack) logger.debug(f"saved to {output_stack_file}")
def abinitio_cmd(stack_file, output): """\b ############################ Abinitio ############################ Abinitio accepts a stack file, calculates Abinitio algorithm on it and saves the results into output file (default adds '_abinitio' to stack name) """ if output is None: output = set_output_name(stack_file, 'abinitio') if os.path.exists(output): logger.error(f"file {yellow(output)} already exsits! remove first " "or use another name with '-o NAME'") return stack = load_stack_from_file(stack_file) logger.info(f'running abinitio on stack file {stack_file}..') output_stack = Abinitio.cryo_abinitio_c1_worker(stack) with mrcfile.new(output) as mrc_fh: mrc_fh.set_data(output_stack.astype('float32')) logger.info(f"saved to {yellow(output)}.")
def normalize_cmd(stack_file, output=None): """ \b ############################ Normalize Stack ############################ Normalize stack of projections. \b Example: $ python aspire.py normalize projections.mrc will produce file projections_normalized.mrc """ if output is None: output = set_output_name(stack_file, 'normalized') if os.path.exists(output): logger.error(f"output file {yellow(output)} already exsits! " f"remove first or use another name with '-o NAME' flag") return logger.info("normalizing projections..") stack = load_stack_from_file(stack_file, c_contiguous=True) normalized_stack = PreProcessor.normalize_background(stack.astype('float64')) with mrcfile.new(output) as fh: fh.set_data(normalized_stack.astype('float32')) logger.info(f"saved to {yellow(output)}.")
def crop_stack_file(cls, stack_file, size, output_stack_file=None, fill_value=None): if output_stack_file is None: output_stack_file = set_output_name(stack_file, 'cropped') if os.path.exists(output_stack_file): raise FileExistsError( f"output file '{yellow(output_stack_file)}' already exists!") stack = load_stack_from_file(stack_file) fill_value = fill_value or PreProcessorConfig.crop_stack_fill_value cropped_stack = cls.crop_stack(stack, size, fill_value=fill_value) action = 'cropped' if size < stack.shape[1] else 'padded' logger.info( f"{action} stack from size {stack.shape} to size {cropped_stack.shape}." f" saving to {yellow(output_stack_file)}..") with mrcfile.new(output_stack_file) as mrc: mrc.set_data(cropped_stack) logger.debug(f"saved to {output_stack_file}")
def viewstack_cmd(stack_file, numslices, startslice, nrows, ncols): """ \b ############################ View Stack ############################ Plot projections using GUI. """ logger.info(f"viewing stack {stack_file}..") stack = load_stack_from_file(stack_file) view_stack(stack, numslices=numslices, startslice=startslice, nrows=nrows, ncols=ncols)
def prewhiten_stack_file(cls, stack_file, output=None): if output is None: output = "prewhitened.mrc" if os.path.exists(output): raise FileExistsError(f"output file '{yellow(output)}' already exists!") stack = load_stack_from_file(stack_file) # TODO adjust to same unified F/C contiguous prewhitten_stack = cls.prewhiten_stack(c_to_fortran(stack)) with mrcfile.new(output) as fh: fh.set_data(np.transpose(prewhitten_stack, (2,1,0)).astype('float32'))
def inspect_cmd(stack_file): """ \b ############################ Inspect Stack ############################ Print info about projections in stack file. """ # load stack but don't convert to C-contiguous indexing stack, stack_type = load_stack_from_file(stack_file, c_contiguous=False, return_format=True) contiguous = red("F-Contiguous") if stack.flags.f_contiguous else "C-Contiguous" logger.info(f"\nStack shape: {yellow(stack.shape)}" f"\nStack format: {yellow(stack_type)}" f"\nContiguous type: {contiguous}")
def global_phaseflip_stack_file(cls, stack_file, output_stack_file=None): if output_stack_file is None: output_stack_file = set_output_name(stack_file, 'g-pf') if os.path.exists(output_stack_file): raise FileExistsError(f"output file '{yellow(output_stack_file)}' already exists!") in_stack = load_stack_from_file(stack_file) out_stack = cls.global_phaseflip_stack(in_stack) # check if stack was flipped if (out_stack[0] == in_stack[0]).all(): logger.info('not saving new mrc file.') else: with mrcfile.new(output_stack_file) as mrc: mrc.set_data(out_stack) logger.info(f"stack is flipped and saved as {yellow(output_stack_file)}")
def phaseflip_star_file(cls, star_file, pixel_size=None): """ todo add verbosity """ # star is a list of star lines describing projections star_records = read_star(star_file)['__root__'] num_projections = len(star_records) projs_init = False # has the stack been initialized already last_processed_stack = None for idx in range(num_projections): # Get the identification string of the next image to process. # This is composed from the index of the image within an image stack, # followed by '@' and followed by the filename of the MRC stack. image_id = star_records[idx].rlnImageName image_parts = image_id.split('@') image_idx = int(image_parts[0]) - 1 stack_name = image_parts[1] # Read the image stack from the disk, if different from the current one. # TODO can we revert this condition to positive? what they're equal? if stack_name != last_processed_stack: mrc_path = os.path.join(os.path.dirname(star_file), stack_name) stack = load_stack_from_file(mrc_path) logger.info( f"flipping stack in {yellow(os.path.basename(mrc_path))}" f" - {stack.shape}") last_processed_stack = stack_name if image_idx > stack.shape[2]: raise DimensionsIncompatible( f'projection {image_idx} in ' f'stack {stack_name} does not exist') proj = stack[image_idx] validate_square_projections(proj) side = proj.shape[1] if not projs_init: # TODO why not initialize before loop (maybe b/c of huge stacks?) # projections was "PFprojs" originally projections = np.zeros((num_projections, side, side), dtype='float32') projs_init = True star_record_data = Box( cryo_parse_Relion_CTF_struct(star_records[idx])) if pixel_size is None: if star_record_data.tmppixA != -1: pixel_size = star_record_data.tmppixA else: raise WrongInput( "Pixel size not provided and does not appear in STAR file" ) h = cryo_CTF_Relion(side, star_record_data) imhat = fftshift(fft2(proj)) pfim = ifft2(ifftshift(imhat * np.sign(h))) if side % 2 == 1: # This test is only vali for odd n # images are single precision imaginery_comp = np.norm(np.imag(pfim[:])) / np.norm(pfim[:]) if imaginery_comp > 5.0e-7: logger.warning( f"Large imaginary components in image {image_idx}" f" in stack {stack_name} = {imaginery_comp}") pfim = np.real(pfim) projections[idx, :, :] = pfim.astype('float32') return projections
def compare_stack_files(file1, file2, verbose=None, max_error=None): """ Wrapper for func compare_stacks. """ stack1 = load_stack_from_file(file1) stack2 = load_stack_from_file(file2) return compare_stacks(stack1, stack2, verbose=verbose, max_error=max_error)