Maps basics#
Internally, masks are stored as 3D numpy.ndarray objects in which each element represents a single voxel.
Externally, masks can be loaded from and written as EM or MRC files.
Work with maps: Basic examples#
In the following section, some examples of how to work with maps are provided. For a complete list of functions, please refer to the cryomap module in the API reference. NOTE: For all the functions displayed, it is assumed that the cryomap module is imported:
[ ]:
import cryocat
from cryocat import cryomap
Read / write maps from / to a file#
The first step to work with a map is to load it and store it as a numpy.ndarray object. This is accomplished with the read() function. The resulting array will have the same shape as the box dimensions of the the map.
[ ]:
my_map = cryomap.read('/path/to/my_map.em')
Conversely, to write a 3D numpy.ndarray object to an EM or MRC file, you need to use the write() function as displayed in the example below. If you pass a file name that already exists, that file will be overwritten by default. To prevent overwriting existing files, you need to specify overwrite=False when calling the function.
[ ]:
# Write 'my_map' ndarray to a new EM file
cryomap.write(my_map, '/path/to/my_map.em')
# Generate an ndarray and write it to an MRC file after having casted the dtypoe to float16
import numpy as np
my_rand_map = np.random.rand(50, 50, 50)
cryomap.write(my_rand_map, '/path/to/my_rand_map.mrc', data_type='float16')
Storing weights and labels associated with maps in HDF5 files#
HDF5 files are containers that are useful to store labels associated to array-like data as maps and volumes. The installation of cryoCAT will automatically install the h5py package as required dependency (please, refer to this link for the official h5py documentation). In cryoCAT, you can use the read_hdf5() and the write_hdf5() functions to read and write labels and weights associated with a map, for instance from a segmentation
prediction job executed on a map or volume. Examples:
[ ]:
# Write an HDF5 file storing a tomogram volume and the associated labels (e.g. from a segmentation prediction)
tomo_hdf5 = cryomap.write_hdf5('/path/to/tomo_map.mrc', labels='/path/to/segmentation_volume.mrc', output_name='/path/to/tomo_map.hdf5')
# Read and inspect the content of an HDF5 file
tomo_hdf5 = cryomap.read_hdf5('/path/to/tomo_map.hdf5', dataset_name="raw", print_datasets=True) #load 'tomo_map.hdf5' and print out the list of datasets stored in it and the dataset "raw"
Convert between different file formats#
It is possible to convert a file from EM format to MRC format and viceversa with the em2mrc() and mrc2em() functions, respectively. Both these functions offer the possibility of inverting the contrast of the original map by passing the option invert=True when calling the function. To prevent overwriting existing files, you need to specify overwrite=False when calling the function. If not specified, the output file will be saved with the same name as the original map with the
changed extension. Note that the path to the orginal file must be passed as input to these functions, not an ndarray. Examples:
[ ]:
cryomap.mrc2em('/path/to/my_map.mrc') # Convert 'my_map.mrc' to 'my_map.em'
cryomap.em2mrc('/path/to/my_map.em', output_name="converted_map.mrc") # Convert 'my_map.em' to 'converted_map.mrc'
Normalize maps#
CryoCAT offers the possibility to normalize a map across its entire ndarray or only the values under a user-specified mask via the normalize() and normalize_under_mask(), respectively. Examples:
[ ]:
# Normalize a map across the entire volume
my_map= cryomap.read('/path/to/my_map.em')
my_map_normalized = cryomap.normalize(my_map)
cryomap.write(my_map_normalized, '/path/to/my_map_normalized.em')
# Nomralize a map within a the sub volume specified by a mask
my_map = cryomap.read('/path/to/my_map.mrc')
my_mask = cryomap.read('/path/to/my_mask.mrc')
my_map_normalized_mask = cryomap.normalize(my_map, my_mask)
cryomap.write(my_map_normalized_mask, '/path/to/my_map_normalized_mask.mrc')
Filters#
In case you want to filter out some frequency information from your map, you need to apply a low-pass and/or a high-pass filter. To apply such filters, you first need to decide the target resolution threshold. The low-/high-pass can be defined with respect to the target resolution or to the box size. The resolution2pixels() and pixels2resolution() functions allow to convert bwetween the two. Examples:
[ ]:
# From resolution to Fourier pixels
target_res = 30 #in Å
box_size = 50 #size of the box in pixels
px_size = 4.2 #in Å
cryomap.resolution2pixels(target_res, box_size, px_size) #print out the respective filetr in Fourier pixels in the console
# From Fourier pixels to resolution
target_fourier_px = 40 #in pixels
box_size = 50 #size of the box in pixels
px_size = 4.2 #in Å
cryomap.pixels2resolution(target_fourier_px, box_size, px_size) #print out the respective resolution in Å in the console
Then, to apply the filter you can use one of the following functions:
Lowpass filter: This can be accomplished with the
lowpass()function. By default a Gaussian fall-off of 3 pixels is applied. Ifoutput_nameis specified, then the output ndarray will be written to the specified file. Example:
[ ]:
target_resolution = 25
px_size = 4.2
box_size = 60
target_fourier_px = cryomap.resolution2pixels(target_resolution, box_size, px_size, print_out=False)
lowpass_filtered_map = cryomap.lowpass('./path/to/input_map.em', fourier_pixels=target_fourier_px, pixel_size=px_size, output_name='/path/to/lowpass_filtered_map.em')
Highpass filter: This can be accomplished with the
highpass()function. By default a Gaussian fall-off of 2 pixels is applied. Example:
[ ]:
input_map = cryomap.read('/path/to/input_map.em')
highpass_filtered_map = cryomap.highpass(input_map, target_resolution=100, pixel_size=4.2, output_name='/path/to/highpass_filtered_map.em')
Combination of low- and high-pass filter: This can be accomplished with the
bandpass()function. The default values of the Gaussian fall-off applied for the lolw- and high-pass filter within this function are the same of their defult values in the respective single filter function illustrated above.
[ ]:
input_map = cryomap.read('/path/to/input_map.em')
filtered_map = cryomap.bandpass(input_map, lp_target_resolution=20, hp_target_resolution=150, pixel_size=4.2, output_name='/path/to/filtered_map.em')
For all the theree functions illustrated above, if the output_name optional argument is specified, the output ndarray will be written to the specified file.
Extract a subvolume#
In case you would like to extract only a part of a volume, you can use one of the following functions:
crop(): This function is mostly suitable for cases in which you want to pass the shape of the new volume (i.e. the box size) and/or only the start coordinates of the original volume for the extraction. The required positional arguments for this functions are the orginal map and the box sizes of the subvolume.
[ ]:
my_subvol = cryomap.crop('/path/to/my_map.em', 25) # extract subvolume of 25x25x25 pixels from 'my_map.em' and on the orginal box center of 'my_map.em'
my_subvol = cryomap.crop('/path/to/my_map.em', (25,30,35), output_file='/path/to/my_subvol.em', crop_coord=(40, 30, 32)) # extract subvolume of 25x30x35 pixels from 'my_map.em' centered on x=40, y=30, z=32 coordinates of 'my_map.em' and save it as 'my_subvol.em'
trim(): This fucntion is mostly suitable when you want to precisely define the start and end coordinates of the region you want to extract, which are the required positional argument together with the orginal map.
[ ]:
my_subvol = cryomap.trim('/path/to/my_map.em', (5,5,5), (25,30,30), output_name = '/path/to/my_subvol.em') # extract the volume deined by a box with start coordinates (5,5,5) and end coordinates (25,30,30) from 'my_map.em' and save it as 'my_subvol.em'
extract_subvolume(): This function is essentially equivalent tocrop(), however it offers the additional option of retaining the orginal box sizes by passingenforce_shape=True. In that case, all the voxels outside the subregion of interest will be filled with the mean value of the original map. Moreover, the input map should be passed as a numpy.ndarray object and the new center is part of the required positional arguments.
[ ]:
my_map = cryomap.read('/path/to/my_map.em')
my_subvol = cryomap.extract_subvolume(my_map, (20,25,30), (40,40,40), enforce_shape=True, output_file='/path/to/my_subvol.em') # extract a subvolume of 20x20x20 pixels centered on 40,40,40 coordinates of 'my_map'
Transformations#
This section illustrates functions in the cryomap module that perform a transformation to the map.
Scaling: The
scale()function allows to scale a map of a user-defined scaling factor. Both down-scaling and up-scaling are supported. This is useful when working with MRC files that carry the pixel size information in the header.
[ ]:
# Scale a map to match a target pixel size to use it as a reference
px_size_ori = 4.2
px_size_new = 2.4
scale_factor = px_size_new / px_size_ori
my_scaled_map = cryomap.scale('/path/to/my_map.em', scale_factor, output_name='/path/to/my_scaled_map.em')
Recenter: The
recenter()function will shift the map to the user-defined center.
[ ]:
recentered_map = cryomap.recenter('/path/to/my_map.em', (10, 10, 10)) # recenter 'my_map.em' to the coordinates (10, 10, 10)
cryomap.write(recentered_map, '/path/to/recentered_map.em') # save the recentered map to a file
Apply a shift to a map: The
shift()applies a user-defined shift to the input map.
Apply a rotation to a map: The
rotate()function apply a user-specified rotation to the input map. Ifoutput_nameis specified, the output map will be saved to file.
Flip the volume: The
flip()function flips a volume along a user-defined axis, which means tat the volume is rotated by -90° along the specified axis. This is equivalent toclip flip[xyz]in IMOD. Ifoutput_nameis specified, the output map will be saved to file.
Other common operations on maps#
Convert a map to a binary map:
binarize(). The default threshold value is 0.5.
[ ]:
my_map = cryomap.read("/path/to/my_map.em")
binarized_map = cryomap.binarize(my_map, threshold=0.03)
Apply symmetry operators to get symmetrized map: The
symmetrize_volume()function applies Cn symmetry operators to generate a symmetrized copy of the the input map. Example:
[ ]:
my_map = cryomap.read("/path/to/my_map.em")
sym_map = cryomap.symmetrize_volume(my_map, "C3") #apply C3 symmetry
cryomap.write(sym_map, "/path/to/sym_map.em")
Invert map contrast: The
invert_contrast()function inverts the contrast of the map by mutiplying the voxel values by -1. The function allows also to save the new ndarray to a file by passing theoutput_nameargument. Example:
[ ]:
inverted_map = cryomap.invert_contrast("/path/to/my_map.em", output_name = '/path/to/inverted_map.em')