Exemple #1
0
 def test_sims_extra_masses(self):
     tiff.write(self.filename, self.float_image)
     with warnings.catch_warnings(record=True) as warns:
         image = tiff.read(self.filename, masses=[1, 2, 6])
     expected_image = tiff.read(self.filename).slice_image([1, 2])
     self.assertEqual(expected_image, image)
     messages = [str(w.message) for w in warns]
     self.assertTrue('Requested masses not found in file: [6]' in messages)
Exemple #2
0
 def test_sims_and_sed(self):
     tiff.write(self.filename, self.image, sed=SED)
     image = tiff.read(self.filename)
     self.assertEqual(image, self.image)
     sims, sed, optical, label = tiff.read(self.filename, sed=True,
                                           optical=True, label=True)
     self.assertEqual(sims, self.image)
     np.testing.assert_array_equal(sed, SED)
     self.assertIsNone(optical)
     self.assertIsNone(label)
Exemple #3
0
    def test_sims_extra_targets(self):
        tiff.write(self.filename, self.float_image)
        target = self.float_image.targets[1]

        with warnings.catch_warnings(record=True) as warns:
            image = tiff.read(self.filename, targets=['Target0', target])
        expected_image = tiff.read(self.filename).slice_image([target])
        self.assertEqual(expected_image, image)
        messages = [str(w.message) for w in warns]
        self.assertTrue(
            'Requested targets not found in file: [\'Target0\']' in messages)
Exemple #4
0
 def test_sims_only(self):
     tiff.write(self.filename, self.image)
     image = tiff.read(self.filename)
     self.assertEqual(image, self.image)
     sims, sed, optical, label = tiff.read(self.filename, sed=True,
                                           optical=True, label=True)
     self.assertEqual(sims, self.image)
     self.assertIsNone(sed)
     self.assertIsNone(optical)
     self.assertIsNone(label)
     self.assertEqual(image.data.dtype, np.uint16)
Exemple #5
0
    def test_read_optical_and_label_only(self):
        tiff.write(self.filename, self.image, optical=CAROUSEL)
        optical, label = tiff.read(self.filename, sims=False,
                                   optical=True, label=True)
        np.testing.assert_array_equal(optical, CAROUSEL)
        np.testing.assert_array_equal(label, LABEL)

        optical_only = tiff.read(self.filename, sims=False, optical=True)
        np.testing.assert_array_equal(optical_only, CAROUSEL)

        label_only = tiff.read(self.filename, sims=False, label=True)
        np.testing.assert_array_equal(label_only, LABEL)
Exemple #6
0
def load_imgs_from_mibitiff(mibitiff_paths, channels=None, load_axis="fovs"):
    """Load images from a series of MIBItiff files.

    This function takes a set of MIBItiff files and load the images into an
    xarray. The type used to store the images will be the same as that of the
    MIBIimages stored in the MIBItiff files.

    Args:
        mibitiff_paths: list of MIBItiff files to load.
        channels: optional list of channels to load. Defaults to `None`, in
            which case, all channels in the first MIBItiff are used.
        load_axis: axis that images will get loaded onto. Must be one of
            ["fovs", "stacks"].

    Returns:
        img_xr: xarray with shape [fovs, tifs, x_dim, y_dim]
    """

    # sanity check
    if not np.isin(load_axis, ["fovs", "stacks"]):
        raise ValueError(
            "Invalid value for load_axis, must be one of [fovs, stacks]")

    # if no channels specified, get them from first MIBItiff file
    if channels is None:
        channel_tuples = tiff.read(mibitiff_paths[0]).channels
        channels = [channel_tuple[1] for channel_tuple in channel_tuples]

    # extract point name from file name
    fovs = [
        mibitiff_path.split(os.sep)[-1].split('_')[0]
        for mibitiff_path in mibitiff_paths
    ]

    # extract images from MIBItiff file
    img_data = []
    for mibitiff_path in mibitiff_paths:
        img_data.append(tiff.read(mibitiff_path)[channels])
    img_data = np.stack(img_data, axis=0)

    # create xarray with image data
    img_xr = xr.DataArray(img_data,
                          coords=[
                              fovs,
                              range(img_data[0].data.shape[0]),
                              range(img_data[0].data.shape[1]), channels
                          ],
                          dims=[load_axis, "rows", "cols", "channels"])

    return img_xr
Exemple #7
0
 def test_write_float32_from_float64(self):
     float64_image = mi.MibiImage(DATA.astype(np.float64), CHANNELS,
                                  **METADATA)
     tiff.write(self.filename, float64_image, multichannel=True)
     image = tiff.read(self.filename)
     np.testing.assert_equal(image.data, DATA)
     self.assertEqual(image.data.dtype, np.float32)
Exemple #8
0
    def test_write_float_tiff(self):

        tiff.write(self.filename, self.image,
                   multichannel=True, write_float=True)
        image = tiff.read(self.filename)
        self.assertEqual(image.data.dtype, np.float32)
        np.testing.assert_equal(image.data, self.image.data.astype(np.float32))
Exemple #9
0
 def test_write_uint16_from_uint8(self):
     uint8_image = mi.MibiImage(
         np.random.randint(0, 256, (32, 32, 5), dtype=np.uint8), CHANNELS,
         **METADATA)
     tiff.write(self.filename, uint8_image, multichannel=True)
     image = tiff.read(self.filename)
     np.testing.assert_equal(image.data, uint8_image.data.astype(np.uint16))
     self.assertEqual(image.data.dtype, np.uint16)
Exemple #10
0
 def test_sims_and_sed_and_optical_and_label(self):
     tiff.write(self.filename, self.image, sed=SED, optical=CAROUSEL)
     image, sed, optical, label = tiff.read(self.filename, sed=True,
                                            optical=True, label=True)
     self.assertEqual(image, self.image)
     np.testing.assert_array_equal(sed, SED)
     np.testing.assert_array_equal(optical, CAROUSEL)
     np.testing.assert_array_equal(label, LABEL)
Exemple #11
0
 def test_write_uint16_from_float32_dtype_np_uint16(self):
     tiff.write(self.filename,
                self.float_image,
                multichannel=True,
                dtype=np.uint16)
     image = tiff.read(self.filename)
     self.assertEqual(image.data.dtype, np.uint16)
     np.testing.assert_equal(image.data,
                             self.float_image.data.astype(np.uint16))
Exemple #12
0
 def test_write_float32_from_float32_tiff_dtype_none_non_ascii(self):
     tiff.write(self.filename,
                self.float_image_non_ascii,
                multichannel=True)
     image = tiff.read(self.filename)
     self.assertEqual(image.data.dtype, np.float32)
     np.testing.assert_equal(
         image.data, self.float_image_non_ascii.data.astype(np.float32))
     np.testing.assert_equal(image.channels,
                             self.float_image_non_ascii.channels)
Exemple #13
0
    def test_sort_channels_before_writing(self):

        # Unordered indices: [2, 0, 4, 1, 3]
        unordered_channels = ((3, 'Target3'), (1, 'Target1'), (5, 'Target5'),
                              (2, 'Target2'), (4, 'Target4'))
        unordered_data = np.stack([DATA[:, :, 2], DATA[:, :, 0], DATA[:, :, 4],
                                   DATA[:, :, 1], DATA[:, :, 3]], axis=2)
        unordered_image = mi.MibiImage(unordered_data, unordered_channels,
                                       **METADATA)

        tiff.write(self.filename, unordered_image)
        image = tiff.read(self.filename)
        self.assertEqual(image, self.image)
    def get_mibi_image(self, image_id):
        """Gets image data from MIBItracker and creates a MibiImage instance.

        Args:
            image_id: The integer id of an image.

        Return:
            A MibiImage instance of the requested image.
        """
        image_info = self.get('images/{}/'.format(image_id)).json()
        tiff_path = '/'.join((image_info['run']['path'], image_info['folder'],
                              'summed_image.tiff'))
        tiff_data = self.download_file(tiff_path)
        return tiff.read(tiff_data)
Exemple #15
0
def merge_mibitiffs(input_folder, out=None):
    """Merges a folder of single-channel MIBItiff files into a single MIBItiff.

    Args:
        input_folder: Path to a folder containing MIBItiff files. While these
            files may be single-channel, they are assumed to have accurate and
            consistent MIBI metadata.
        out: Optionally, a path to a location for saving the combined TIFF. If
           not specified, defaults to 'combined.tiff' inside the input folder.
    """
    pattern = re.compile(r'.+\.tiff?$')
    paths = [
        os.path.join(input_folder, f) for f in os.listdir(input_folder)
        if re.match(pattern, f.lower())
    ]
    merged = tiff.read(paths[0])
    for path in paths[1:]:
        image = tiff.read(path)
        merged.append(image)

    if out is None:
        out = os.path.join(input_folder, 'combined.tiff')
    tiff.write(out, merged, multichannel=True)
Exemple #16
0
    def test_write_single_channel_tiffs(self):

        basepath = os.path.split(self.filename)[0]

        tiff.write(basepath, self.image, multichannel=False)

        for i, (_, channel) in enumerate(CHANNELS):
            formatted = util.format_for_filename(channel)
            filename = os.path.join(basepath, '{}.tiff'.format(formatted))

            tif = tiff.read(filename)

            np.testing.assert_equal(np.squeeze(tif.data), DATA[:, :, i])
            self.assertTupleEqual(tif.channels, (CHANNELS[i], ))
            self.assertEqual(tif.data.dtype, np.uint16)
Exemple #17
0
def test_load_imgs_from_mibitiff():
    mibitiff_files = [
        os.path.join(
            os.path.dirname(os.path.realpath(__file__)), "..", "..", "data",
            "example_dataset", "input_data", "input_data_TIFF",
            "Point8_RowNumber0_Depth_Profile0-MassCorrected-Filtered.tiff")
    ]
    channels = ["HH3", "Membrane"]
    data_xr = data_utils.load_imgs_from_mibitiff(mibitiff_files, channels)
    assert (data_xr.dims == ("fovs", "rows", "cols", "channels"))
    assert (data_xr.fovs == "Point8")
    assert (data_xr.rows == range(1024)).all()
    assert (data_xr.cols == range(1024)).all()
    assert (data_xr.channels == channels).all()
    np.testing.assert_array_equal(data_xr.values[0], (tiff.read(
        mibitiff_files[0]))[channels].data)
def plot_1_fov(file_name, l_channel, ax=None, file_id=''):
    """Plot a selection of channels for one FoV.

    Parameters
    ----------
    file_name : str
        Path to MIBItiff file of the FoV to use for plotting.
    l_channel : list
        List of channels to plot.
    ax : `~matplotlib.axes.Axes`, optional
        Axes of the figure for the plot.
    file_id : str, optional
        File ID to use in the title for the plots.

    Returns
    -------
    ax : `~matplotlib.axes.Axes`
        Axes of the figure containing the plots.
    """

    print()
    print(f'Plotting file: {file_name}')
    print(f' File ID: {file_id}')

    image = tiff.read(file_name)

    # TODO: allow target name anonymization!!!

    # loop over channels
    for channel, axis in zip(l_channel, ax):
        # plot image
        print(f' Channel: {channel}')
        im = image[channel]
        counts = im.sum()
        plot_image(im,
                   ax=axis,
                   title=str(file_id) + ': ' + str(channel) + ' ' +
                   str("{:.2e}".format(counts)),
                   brighten_image=True)
    if GRAPH_DEBUG > 3:
        plt.show()  # wait until image is closed

    if GRAPH_DEBUG > 2:
        plt.show()  # don't leave at the end

    return ax
Exemple #19
0
def test_load_imgs_from_mibitiff_all_channels():
    mibitiff_files = [
        os.path.join(
            os.path.dirname(os.path.realpath(__file__)), "..", "..", "data",
            "example_dataset", "input_data", "input_data_TIFF",
            "Point8_RowNumber0_Depth_Profile0-MassCorrected-Filtered.tiff")
    ]
    data_xr = data_utils.load_imgs_from_mibitiff(mibitiff_files, channels=None)
    assert (data_xr.dims == ("fovs", "rows", "cols", "channels"))
    assert (data_xr.fovs == "Point8")
    assert (data_xr.rows == range(1024)).all()
    assert (data_xr.cols == range(1024)).all()
    exected_channels = [
        "Background", "BetaCatenin", "BetaTubulin", "CD20", "CD3", "CD4",
        "CD45", "CD8", "CD9", "ECadherin", "ER", "GLUT1", "HER2", "HH3",
        "HLA_Class_1", "Ki67", "LaminAC", "Membrane", "NaK ATPase",
        "PanKeratin", "SMA", "Vimentin"
    ]
    assert (data_xr.channels == exected_channels).all()
    np.testing.assert_array_equal(data_xr.values[0],
                                  (tiff.read(mibitiff_files[0])).data)
Exemple #20
0
def plot_1_fov(file_name, l_channel, ax=None, file_id=''):
    """Plot the channels for one FoV."""

    print()
    print(f'Plotting file: {file_name}')
    print(f' File ID: {file_id}')

    # load input
    input_folder = '~/IONpath/data/temp'
    input_folder = os.path.expanduser(
        input_folder)  # expand home dir into string
    file_path = os.path.join(input_folder, file_name)
    image = tiff.read(file_path)

    #import IPython; IPython.embed()
    #print(f'image metadata:\n{image.metadata()}')
    #print(f'image channels:\n{image.channels}')

    # loop over channels
    for channel, axis in zip(l_channel, ax):
        # plot image
        print(f' Channel: {channel}')
        im = image[channel]
        counts = im.sum()
        #import IPython; IPython.embed()
        plot_image(im,
                   ax=axis,
                   title=str(file_id) + ': ' + str(channel) + ' ' +
                   str("{:.2e}".format(counts)))
    if GRAPH_DEBUG > 3:
        plt.show()  # wait until image is closed

    if GRAPH_DEBUG > 2:
        plt.show()  # don't leave at the end

    return ax
Exemple #21
0
 def test_read_sed_only(self):
     tiff.write(self.filename, self.image, sed=SED)
     sed = tiff.read(self.filename, sims=False, sed=True)
     np.testing.assert_array_equal(sed, SED)
Exemple #22
0
    a_masses = np.arange(10, 220)

a_masses.sort()
print(f'a_masses = {a_masses}')

# dark plot style
plt.style.use('dark_background')

# loop over FOVs
for fov in df_fov_list['FOV Name']:
    print(f'\nGoing for FOV {fov}')

    # open input images
    image_path = os.path.join(input_path, f'{fov}.tiff')
    print(f'file: {image_path}')
    image = tiff.read(image_path)
    print(f'channels {sorted(image.channels)}')  # sorted by mass

    if SAVE_OUTPUT:
        output_path_fov = os.path.join(output_path, fov)
        print(f'Creating output folder {output_path_fov}')
        os.makedirs(output_path_fov)

    # loop over channels
    for ch_order, channel in enumerate(sorted(image.channels)):
        mass = channel[0]
        target = channel[1]

        if mass in a_masses:  # selected channels
            print()
            print(f'\nchannel {ch_order}: mass {mass}, target {target}')
def load_imgs_from_mibitiff(data_dir,
                            mibitiff_files=None,
                            channels=None,
                            delimiter=None,
                            dtype='int16'):
    """Load images from a series of MIBItiff files.

    This function takes a set of MIBItiff files and load the images into an
    xarray. The type used to store the images will be the same as that of the
    MIBIimages stored in the MIBItiff files.

    Args:
        data_dir (str): directory containing MIBItiffs
        mibitiff_files (list): list of MIBItiff files to load. If None,
            all MIBItiff files in data_dir are loaded.
        channels (list): optional list of channels to load. Defaults to `None`, in
            which case, all channels in the first MIBItiff are used.
        delimiter (str): optional delimiter-character/string which separate fov names
            from the rest of the file name. Defaults to None
        dtype (str/type): optional specifier of image type.  Overwritten with warning for
            float images

    Returns:
        img_xr (xr.DataArray): xarray with shape [fovs, x_dim, y_dim, channels]
    """

    if not mibitiff_files:
        mibitiff_files = iou.list_files(data_dir, substrs=['.tif'])

    # extract fov names w/ delimiter agnosticism
    fovs = iou.extract_delimited_names(mibitiff_files, delimiter=delimiter)

    mibitiff_files = [
        os.path.join(data_dir, mt_file) for mt_file in mibitiff_files
    ]

    test_img = io.imread(mibitiff_files[0], plugin='tifffile')

    # check to make sure that float dtype was supplied if image data is float
    data_dtype = test_img.dtype
    if np.issubdtype(data_dtype, np.floating):
        if not np.issubdtype(dtype, np.floating):
            warnings.warn(
                f"The supplied non-float dtype {dtype} was overwritten to {data_dtype}, "
                f"because the loaded images are floats")
            dtype = data_dtype

    # if no channels specified, get them from first MIBItiff file
    if channels is None:
        channel_tuples = tiff.read(mibitiff_files[0]).channels
        channels = [channel_tuple[1] for channel_tuple in channel_tuples]

    # extract images from MIBItiff file
    img_data = []
    for mibitiff_file in mibitiff_files:
        img_data.append(tiff.read(mibitiff_file)[channels])
    img_data = np.stack(img_data, axis=0)
    img_data = img_data.astype(dtype)

    # create xarray with image data
    img_xr = xr.DataArray(img_data,
                          coords=[
                              fovs,
                              range(img_data[0].data.shape[0]),
                              range(img_data[0].data.shape[1]), channels
                          ],
                          dims=["fovs", "rows", "cols", "channels"])

    return img_xr
def open_tiff(file_name):
    return tiff.read(str(files[0]))
Exemple #25
0
 def test_sims_selected_targets(self):
     tiff.write(self.filename, self.float_image)
     image = tiff.read(self.filename, targets=self.float_image.targets[1:3])
     expected_image = tiff.read(self.filename).slice_image(CHANNELS[1:3])
     self.assertEqual(expected_image, image)
Exemple #26
0
 def test_sims_selected_masses_and_targets(self):
     tiff.write(self.filename, self.float_image)
     with self.assertRaises(ValueError):
         tiff.read(self.filename,
                   masses=self.float_image.masses[1:2],
                   targets=self.float_image.targets[2:3])
Exemple #27
0
 def test_sims_no_selected_found(self):
     tiff.write(self.filename, self.float_image)
     with self.assertRaises(ValueError):
         tiff.read(self.filename, targets=['do', 'not', 'exist'])
Exemple #28
0
 def test_read_with_invalid_return_types(self):
     tiff.write(self.filename, self.image)
     with self.assertRaises(ValueError):
         tiff.read(self.filename, sims=False)
Exemple #29
0
 def test_read_wrong_software_tag(self):
     with warnings.catch_warnings():
         warnings.filterwarnings('ignore', message='.*low contrast image.*')
         io.imsave(self.filename, DATA)
     with self.assertRaises(ValueError):
         tiff.read(self.filename)
def main():
    """Main function.

    Define a list of FoV files and list of channels. A large canvas is created
    with plots of each channel for each FoV. Each row in the canvas represents
    one FoV and each column represents a channel.

    Activate the global variable 'SAVE' in order to save the figure as a png
    file.
    """

    data_path = os.path.expanduser('~/common/path/to/data')
    l_file_name = []
    l_file_label = []

    print()
    print('file 1: MIBI/O MIBItiff file')
    tiff_file = os.path.join(data_path, 'file1/specific/path/to/file.tiff')
    image = tiff.read(tiff_file)
    print(f'metadata {image.metadata}')
    print(f'channels {image.channels}')
    l_file_name.append(tiff_file)
    l_file_label.append('file')

    print()
    print('file 2: MATLAB combined MIBItiff file')
    # note: the matlab pipeline does not produce MIBItiffs, so the converter
    # has to be used first (see mibitracker-client/mibidata/combine_tiffs.py)
    input_folder = os.path.join(data_path,
                                'file2/specific/path/to/folder/with/TIFs')
    run_path = os.path.join(data_path, 'file2/specific/path/to/run_file.xml')
    point = 'Point0'
    panel_path = os.path.join(data_path,
                              'file2/specific/path/to/panel_file.csv')
    slide = '0'
    size = 500  #um
    combine_tiffs.create_mibitiffs(input_folder, run_path, point, panel_path,
                                   slide, size)
    # now the combined tiff file can be used to proceed as before
    tiff_file = os.path.join(input_folder, 'combined.tiff')
    image = tiff.read(tiff_file)
    print(f'metadata {image.metadata}')
    print(f'channels {image.channels}')
    l_file_name.append(tiff_file)
    l_file_label.append('matlab_file')

    l_channel = [89, 113, 115, 128, 146, 197]
    # l_target = ['89', '113', '115', 'Xe128', '146', '197'] # not used for now
    # TODO: function that takes the panel and a list of masses and returns a
    #       list of the corresponding targets!!!
    n_files_to_plot = len(l_file_name)
    n_channels_to_plot = len(l_channel)

    # TODO: allow target name anonymization!!!

    figsize = 6  # inch
    fig, ax = plt.subplots(n_files_to_plot,
                           n_channels_to_plot,
                           figsize=(figsize * n_channels_to_plot,
                                    figsize * n_files_to_plot))

    # loop over files and produce the plots
    count_files = 0
    for tiff_file_name, file_label in zip(l_file_name, l_file_label):
        if count_files < n_files_to_plot:
            #plot_1_fov(tiff_file_name, l_channel, ax[count_files],
            #           file_id=count_files)
            plot_1_fov(tiff_file_name,
                       l_channel,
                       ax[count_files],
                       file_id=file_label)
        count_files += 1

    # save ouptut
    if SAVE:
        output_file_name = 'plot_compare_extraction.png'
        print()
        print(f'Saving image to {output_file_name}')
        plt.savefig(output_file_name)

    if GRAPH_DEBUG > 1:
        plt.show()  # don't leave at the end