1. Build an ImagingExtractor:#
To build your custom ImagingExtractor to interface with a new raw image storage format from your microscope, build a custom class inheriting from a base class that enforces certain methods that need to be defined:
get_channel_names(): returns a list of channel names
get_num_channels(): returns the number of channels used in the recording
get_num_frames(): the number of image frames recorded
get_image_size(): the y,x dim of the image(the resolution)
get_frames(): return specific requested image frames
from roiextractors import ImagingExtractor
class MyFormatImagingExtractor(ImagingExtractor):
def __init__(self, file_path, sampling_frequency: float = None):
ImagingExtractor.__init__(self)
## All file specific initialization code can go here.
self.sampling_frequency = sampling_frequency or # define your own method of extraction
self._data = self._load_data() # groups is a list or a np.array with length num_channels
self._channel_names = [f'channel_{ch}' for ch in range(self.get_num_channels())] # write logic to get channel names
def _load_data(self):
# define a function that retrives an in memory array from your native imaging format
# returns: np.ndarray (shape: frames, image_dims)
def get_channel_names(self):
# Fill code to get a list of channel_ids. If channel ids are not specified, you can use:
# channel_ids = range(num_channels)
return self._channel_names
def get_num_channels(self) -> int:
# define method to find the number of channels
# returns int
def get_num_frames(self):
# Fill code to get the number of frames (samples) in the recordings.
return num_frames
def get_sampling_frequency():
return self.sampling_frequency
def get_frames(self, frame_idxs: ArrayType, channel: int = 0) -> NumpyArray:
# define a method to read a frame from the given frame numbers requested.
return self._data[frame_idxs]
def get_image_size(self)
# returns something like self._data.shape[1:]
@staticmethod
def write_imaging(imaging_obj, save_path, other_params):
'''
This is an example of a function that is not abstract so it is optional if you want to override it.
It allows other ImageExtractors to use your new ImageExtractors to convert their data into your this file format.
'''