Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: Add support for multi-channel ScanImage data #776

Closed
2 tasks done
weiglszonja opened this issue Mar 12, 2024 · 3 comments
Closed
2 tasks done

[Feature]: Add support for multi-channel ScanImage data #776

weiglszonja opened this issue Mar 12, 2024 · 3 comments

Comments

@weiglszonja
Copy link
Contributor

What would you like to see added to NeuroConv?

This is already supported in roiextractors with ScanImageTiffSinglePlaneImagingExtractor, looks like we just need to add the interface.

I'm happy work on it as it is going to be needed for Dombeck 2p conversion; just wanted to check-in with @pauladkisson @alessandratrapani before jumping on it.
Let me know what you think.

Is your feature request related to a problem?

No response

Do you have any interest in helping implement the feature?

Yes.

Code of Conduct

@pauladkisson
Copy link
Member

Thanks Szonja, that would be great! It looks like it should be as easy as changing the ExtractorName in the ScanImageImagingInterface. lmk if you run into any problems.

@weiglszonja
Copy link
Contributor Author

weiglszonja commented Mar 14, 2024

@pauladkisson I switched to the new extractor in #779, but run into a problem when trying to test with this file:

file_path=str(OPHYS_DATA_PATH / "imaging_datasets" / "ScanImage" / "scanimage_20220801_volume.tif")

The full traceback:

../../../anaconda3/envs/neuroconv311/lib/python3.11/site-packages/roiextractors/extractors/tiffimagingextractors/scanimagetiffimagingextractor.py:264: IndexError
FAILED [ 66%]
src/neuroconv/tools/testing/data_interface_mixins.py:204 (TestScanImageImagingInterfaceRecent.test_interface_alignment)
self = <tests.test_on_data.test_imaging_interfaces.TestScanImageImagingInterfaceRecent testMethod=test_interface_alignment>

    def test_interface_alignment(self):
        interface_kwargs = self.interface_kwargs
        if isinstance(interface_kwargs, dict):
            interface_kwargs = [interface_kwargs]
        for num, kwargs in enumerate(interface_kwargs):
            with self.subTest(str(num)):
                self.case = num
                self.test_kwargs = kwargs
    
                self.check_interface_get_original_timestamps()
                self.check_interface_get_timestamps()
                self.check_interface_set_aligned_timestamps()
                self.check_shift_timestamps_by_start_time()
                self.check_interface_original_timestamps_inmutability()
    
>               self.check_nwbfile_temporal_alignment()

../src/neuroconv/tools/testing/data_interface_mixins.py:220: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../src/neuroconv/tools/testing/data_interface_mixins.py:251: in check_nwbfile_temporal_alignment
    interface.run_conversion(nwbfile_path=nwbfile_path, overwrite=True, metadata=metadata)
../src/neuroconv/basedatainterface.py:113: in run_conversion
    self.add_to_nwbfile(nwbfile_out, metadata=metadata, **conversion_options)
../src/neuroconv/datainterfaces/ophys/baseimagingextractorinterface.py:132: in add_to_nwbfile
    add_imaging(
../src/neuroconv/tools/roiextractors/roiextractors.py:548: in add_imaging
    add_photon_series(
../src/neuroconv/tools/roiextractors/roiextractors.py:420: in add_photon_series
    frames_to_iterator = _imaging_frames_to_hdmf_iterator(
../src/neuroconv/tools/roiextractors/roiextractors.py:534: in _imaging_frames_to_hdmf_iterator
    return ImagingExtractorDataChunkIterator(imaging_extractor=imaging, **iterator_options)
../src/neuroconv/tools/roiextractors/imagingextractordatachunkiterator.py:69: in __init__
    self._dtype = self._get_dtype()
../src/neuroconv/tools/roiextractors/imagingextractordatachunkiterator.py:123: in _get_dtype
    return self.imaging_extractor.get_dtype()
../../../anaconda3/envs/neuroconv311/lib/python3.11/site-packages/roiextractors/extractors/tiffimagingextractors/scanimagetiffimagingextractor.py:293: in get_dtype
    return self.get_frames(0).dtype
../../../anaconda3/envs/neuroconv311/lib/python3.11/site-packages/roiextractors/extractors/tiffimagingextractors/scanimagetiffimagingextractor.py:193: in get_frames
    return self.get_video(start_frame=frame_idxs[0], end_frame=frame_idxs[-1] + 1)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <roiextractors.extractors.tiffimagingextractors.scanimagetiffimagingextractor.ScanImageTiffSinglePlaneImagingExtractor object at 0x2aabec510>
start_frame = 0, end_frame = 1

    def get_video(self, start_frame=None, end_frame=None) -> np.ndarray:
        """Get the video frames.
    
        Parameters
        ----------
        start_frame: int, optional
            Start frame index (inclusive).
        end_frame: int, optional
            End frame index (exclusive).
    
        Returns
        -------
        video: numpy.ndarray
            The video frames.
        """
        if start_frame is None:
            start_frame = 0
        if end_frame is None:
            end_frame = self._num_frames
        end_frame_inclusive = end_frame - 1
        self.check_frame_inputs(end_frame_inclusive)
        self.check_frame_inputs(start_frame)
        raw_start = self.frame_to_raw_index(start_frame)
        raw_end_inclusive = self.frame_to_raw_index(end_frame_inclusive)  # frame_to_raw_index requires inclusive frame
        raw_end = raw_end_inclusive + 1
    
        ScanImageTiffReader = _get_scanimage_reader()
        with ScanImageTiffReader(filename=str(self.file_path)) as io:
            raw_video = io.data(beg=raw_start, end=raw_end)
    
        start_cycle = np.ceil(start_frame / self._frames_per_slice).astype("int")
        end_cycle = end_frame // self._frames_per_slice
        num_cycles = end_cycle - start_cycle
        start_frame_in_cycle = start_frame % self._frames_per_slice
        end_frame_in_cycle = end_frame % self._frames_per_slice
        start_left_in_cycle = (self._frames_per_slice - start_frame_in_cycle) % self._frames_per_slice
        end_left_in_cycle = (self._frames_per_slice - end_frame_in_cycle) % self._frames_per_slice
        index = []
        for j in range(start_left_in_cycle):  # Add remaining frames from first (incomplete) cycle
            index.append(j * self._num_channels)
        for i in range(num_cycles):
            for j in range(self._frames_per_slice):
                index.append(
                    (j - start_frame_in_cycle) * self._num_channels
                    + (i + bool(start_left_in_cycle)) * self._num_raw_per_cycle
                )
        for j in range(end_left_in_cycle):  # Add remaining frames from last (incomplete) cycle)
            index.append((j - start_frame_in_cycle) * self._num_channels + num_cycles * self._num_raw_per_cycle)
>       video = raw_video[index]
E       IndexError: index 1 is out of bounds for axis 0 with size 1

I see in roiextractors you're using a different file:
https://github.com/catalystneuro/roiextractors/blob/7aa2a63c1700075df45f377cc281f573aa1c30f8/tests/test_scanimagetiffimagingextractor.py#L11
for reason explained in catalystneuro/roiextractors#241 (comment)

But I don't see why this file should not work with the new extractor, maybe I'm missing something here?

@weiglszonja
Copy link
Contributor Author

This was done in #809

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants