Skip to content

Commit

Permalink
v0.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonas Windhager committed Oct 18, 2021
1 parent e271f97 commit ea7747c
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 38 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [v0.6.0] - 2021-10-18

Replaced imctools by readimc

## [v0.5.6] - 2021-10-05

Fixed napari-imc for napari>0.4.10
Expand All @@ -24,6 +28,7 @@ Updated documentation
Last release before introducing this changelog


[v0.6.0]: https://github.com/BodenmillerGroup/napari-imc/compare/v0.5.6...v0.6.0
[v0.5.6]: https://github.com/BodenmillerGroup/napari-imc/compare/v0.5.4...v0.5.6
[v0.5.4]: https://github.com/BodenmillerGroup/napari-imc/compare/v0.5.3...v0.5.4
[v0.5.3]: https://github.com/BodenmillerGroup/napari-imc/compare/v0.5.1...v0.5.3
Expand Down
58 changes: 35 additions & 23 deletions napari_imc/io/mcd.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import numpy as np

from imageio import imread
from imctools.io.mcd.mcdparser import McdParser
from napari_imc.io.base import FileReaderBase, ImageDimensions
from pathlib import Path
from readimc import IMCMcdFile
from typing import List, Optional, Tuple, Union

from napari_imc.models import IMCFileModel, IMCFileAcquisitionModel, IMCFilePanoramaModel
Expand All @@ -12,52 +11,65 @@
class McdFileReader(FileReaderBase):
def __init__(self, path: Union[str, Path]):
super(McdFileReader, self).__init__(path)
self._mcd_parser: Optional[McdParser] = None
self._mcd_file: Optional[IMCMcdFile] = None

def _get_imc_file_panoramas(self, imc_file: IMCFileModel) -> List[IMCFilePanoramaModel]:
return [
IMCFilePanoramaModel(imc_file, panorama.id, panorama.image_type, panorama.description)
for panorama in self._mcd_parser.session.panoramas.values() if panorama.image_type != 'Default'
IMCFilePanoramaModel(imc_file, panorama.id, panorama.metadata.get("Type"), panorama.description)
for slide in self._mcd_file.slides for panorama in slide.panoramas
]

def _get_imc_file_acquisitions(self, imc_file: IMCFileModel) -> List[IMCFileAcquisitionModel]:
return [
IMCFileAcquisitionModel(imc_file, acquisition.id, acquisition.description, acquisition.channel_labels)
for acquisition in self._mcd_parser.session.acquisitions.values() if acquisition.is_valid
for slide in self._mcd_file.slides for acquisition in slide.acquisitions
]

def read_panorama(self, panorama_id: int) -> Tuple[ImageDimensions, np.ndarray]:
panorama = self._mcd_parser.session.panoramas[panorama_id]
xs_physical = [panorama.x1, panorama.x2, panorama.x3, panorama.x4]
ys_physical = [panorama.y1, panorama.y2, panorama.y3, panorama.y4]
panorama = next(
panorama
for slide in self._mcd_file.slides
for panorama in slide.panoramas
if panorama.id == panorama_id
)
xs_physical = [panorama.x1_um, panorama.x2_um, panorama.x3_um, panorama.x4_um]
ys_physical = [panorama.y1_um, panorama.y2_um, panorama.y3_um, panorama.y4_um]
x_physical, y_physical = min(xs_physical), min(ys_physical)
w_physical, h_physical = max(xs_physical) - x_physical, max(ys_physical) - y_physical
data = imread(self._mcd_parser.get_panorama_image(panorama_id))
if x_physical != panorama.x1:
data = self._mcd_file.read_panorama(panorama)
if x_physical != panorama.x1_um:
data = data[:, ::-1, :]
if y_physical != panorama.y1:
if y_physical != panorama.y1_um:
data = data[::-1, :, :]
return (x_physical, y_physical, w_physical, h_physical), data

def read_acquisition(self, acquisition_id: int, channel_label: str) -> Tuple[ImageDimensions, np.ndarray]:
acquisition = self._mcd_parser.session.acquisitions[acquisition_id]
xs_physical = [acquisition.roi_start_x_pos_um, acquisition.roi_end_x_pos_um]
ys_physical = [acquisition.roi_start_y_pos_um, acquisition.roi_end_y_pos_um]
acquisition = next(
acquisition
for slide in self._mcd_file.slides
for acquisition in slide.acquisitions
if acquisition.id == acquisition_id
)
channel_index = acquisition.channel_labels.index(channel_label)
xs_physical = [acquisition.start_x_um, acquisition.end_x_um]
ys_physical = [acquisition.start_y_um, acquisition.end_y_um]
x_physical, y_physical = min(xs_physical), min(ys_physical)
w_physical, h_physical = max(xs_physical) - x_physical, max(ys_physical) - y_physical
data = self._mcd_parser.get_acquisition_data(acquisition.id).get_image_by_label(channel_label)
if x_physical != acquisition.roi_start_x_pos_um:
data = data[:, ::-1]
if y_physical != acquisition.roi_start_y_pos_um:
data = data[::-1, :]
return (x_physical, y_physical, w_physical, h_physical), data
channel_img = self._mcd_file.read_acquisition(acquisition)[channel_index]
if x_physical != acquisition.start_x_um:
channel_img = channel_img[:, ::-1]
if y_physical != acquisition.start_y_um:
channel_img = channel_img[::-1, :]
return (x_physical, y_physical, w_physical, h_physical), channel_img

def __enter__(self) -> 'FileReaderBase':
self._mcd_parser = McdParser(self._path)
self._mcd_file = IMCMcdFile(self._path)
self._mcd_file.open()
return self

def __exit__(self, exc_type, exc_val, exc_tb):
self._mcd_parser.close()
self._mcd_file.close()
self._mcd_file = None

@classmethod
def accepts(cls, path: Union[str, Path]) -> bool:
Expand Down
26 changes: 15 additions & 11 deletions napari_imc/io/txt.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import numpy as np
import re

from imctools.io.txt.txtparser import TxtParser
from napari_imc.io.base import FileReaderBase, ImageDimensions
from pathlib import Path
from readimc import IMCTxtFile
from typing import List, Optional, Tuple, Union

from napari_imc.models import IMCFileModel, IMCFileAcquisitionModel, IMCFilePanoramaModel
Expand All @@ -11,34 +12,37 @@
class TxtFileReader(FileReaderBase):
def __init__(self, path: Union[str, Path]):
super(TxtFileReader, self).__init__(path)
self._txt_parser: Optional[TxtParser] = None
self._txt_file: Optional[IMCTxtFile] = None

def _get_imc_file_panoramas(self, imc_file: IMCFileModel) -> List[IMCFilePanoramaModel]:
return []

def _get_imc_file_acquisitions(self, imc_file: IMCFileModel) -> List[IMCFileAcquisitionModel]:
acquisition = self._txt_parser.get_acquisition_data().acquisition
m = re.match(r"(?P<description>.*)_(?P<id>[0-9]+)", self._path.stem)
acquisition_id = int(m.group("id")) if m is not None else 0
acquisition_description = m.group("description") if m is not None else self._path.stem
return [
IMCFileAcquisitionModel(imc_file, acquisition.id, acquisition.description, acquisition.channel_labels)
IMCFileAcquisitionModel(imc_file, acquisition_id, acquisition_description, self._txt_file.channel_labels)
]

def read_panorama(self, panorama_id: int) -> Tuple[ImageDimensions, np.ndarray]:
raise RuntimeError('This operation is not supported')

def read_acquisition(self, acquisition_id: int, channel_label: str) -> Tuple[ImageDimensions, np.ndarray]:
acquisition_data = self._txt_parser.get_acquisition_data()
acquisition = acquisition_data.acquisition
channel_index = self._txt_file.channel_labels.index(channel_label)
channel_img = self._txt_file.read_acquisition()[channel_index]
x_physical, y_physical = 0, 0
w_physical, h_physical = acquisition.max_x, acquisition.max_y
data = acquisition_data.get_image_by_label(channel_label)
return (x_physical, y_physical, w_physical, h_physical), data
h_physical, w_physical = channel_img.shape
return (x_physical, y_physical, w_physical, h_physical), channel_img

def __enter__(self) -> 'FileReaderBase':
self._txt_parser = TxtParser(self._path)
self._txt_file = IMCTxtFile(self._path)
self._txt_file.open()
return self

def __exit__(self, exc_type, exc_val, exc_tb):
pass
self._txt_file.close()
self._txt_file = None

@classmethod
def accepts(cls, path: Union[str, Path]) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion napari_imc/models/imc_file_panorama.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
class IMCFilePanoramaModel(ModelBase, IMCFileTreeItem):
imc_file_tree_is_checkable = True

def __init__(self, imc_file: 'IMCFileModel', id_: int, image_type: str,
def __init__(self, imc_file: 'IMCFileModel', id_: int, image_type: Optional[str],
description: str):
ModelBase.__init__(self)
IMCFileTreeItem.__init__(self)
Expand Down
7 changes: 4 additions & 3 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,19 @@ packages = find:
python_requires = >=3.7
setup_requires = setuptools_scm
install_requires =
imageio
imctools
napari
napari-plugin-engine>=0.1.4
numpy
qtpy
readimc
superqt
use_scm_version =
write_to = napari_czifile2/version.py

[options.extras_require]
IMAXT = zarr
IMAXT =
imageio
zarr

[options.entry_points]
napari.plugin =
Expand Down

0 comments on commit ea7747c

Please sign in to comment.