diff --git a/README.md b/README.md
index 4c17787..37762a9 100755
--- a/README.md
+++ b/README.md
@@ -3,6 +3,9 @@
[![Build Status](https://travis-ci.org/BodenmillerGroup/imctools.svg?branch=master)](https://travis-ci.org/BodenmillerGroup/imctools)
[![Documentation Status](https://readthedocs.org/projects/imctools/badge/?version=latest)](https://imctools.readthedocs.io/en/latest/?badge=latest)
+> `imctools` v1.x is now deprecated. We strongly encourage you to migrate to `imctools` v2.x as all further efforts will be focused on a development of this version.
+> Please modify your processing pipeline source code accordingly, due to many changes in data output format, CLI changes, dropped Python 2 and Fiji plugins support, etc.
+
An IMC file conversion tool that aims to convert IMC rawfiles (.mcd, .txt) into an intermediary ome.tiff, containing all the relevant metadata. Further it contains tools to generate simpler tiff files that can be directly be used as input files for e.g. CellProfiller, Ilastik, Fiji etc.
Further imctools can directly work as a FIJI plugin, exploiting the Jython language. That allows that IMC data can be directly visualized in FIJI.
@@ -27,13 +30,9 @@ Documentation: https://imctools.readthedocs.io
## Installation
-Preferable way to install `imctools` is via official PyPI registry:
-```
-pip install imctools
-```
-To directly install the package from Github (**NOT RECOMMENDED**):
+Preferable way to install `imctools` is via official PyPI registry. Please define package version explicitly in order to avoid incompatibilities between v1.x and v2.x versions:
```
-pip install git+https://github.com/BodenmillerGroup/imctools.git
+pip install imctools==1.0.7
```
## Usage
diff --git a/docs/source/index.rst b/docs/source/index.rst
index c6f885b..4d09a7a 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -3,8 +3,100 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
-imctools documentation
-====================================
+imctools
+========
+
+ | ``imctools`` v1.x is now deprecated. We strongly encourage you to migrate to ``imctools`` v2.x as all further efforts will be focused on a development of this version. Please modify your processing pipeline source code accordingly, due to many changes in data output format, CLI changes, dropped Python 2 and Fiji plugins support, etc.
+
+An IMC file conversion tool that aims to convert IMC rawfiles (.mcd,
+.txt) into an intermediary ome.tiff, containing all the relevant
+metadata. Further it contains tools to generate simpler tiff files that
+can be directly be used as input files for e.g. CellProfiller, Ilastik,
+Fiji etc.
+
+Further imctools can directly work as a FIJI plugin, exploiting the
+Jython language. That allows that IMC data can be directly visualized in
+FIJI.
+
+For a description of the associated segmentation pipline, please visit:
+https://github.com/BodenmillerGroup/ImcSegmentationPipeline
+
+Documentation: https://imctools.readthedocs.io
+
+Features
+--------
+
+- MCD lazy data access using memorymaps
+- Full MCD metadata access
+- TXT file loading
+- OME-TIFF loading
+- OME-TIFF/TIFF export (including optional compression)
+
+Prerequisites
+-------------
+
+- The package is written for Python3, but should also work with Python2
+- The core functions have a 'base' pure Python/Jython implementation
+ with no dependencies outside the standard libraries.
+- The fast functions do need Python packages, such as numpy, scipy etc.
+ installed.
+
+Installation
+------------
+
+Preferable way to install ``imctools`` is via official PyPI registry.
+Please define package version explicitly in order to avoid
+incompatibilities between v1.x and v2.x versions:
+
+::
+
+ pip install imctools==1.0.7
+
+Usage
+-----
+
+imctools is often used from jupyter as part of the preprocessing
+pipeline, mainly using the 'script' wrapper functions. Check
+'notebooks/example\_preprocessing\_pipline.ipynb' as a template
+
+Further imctools can be directly used as a module:
+
+.. code::
+
+ import imctools.io.mcdparser as mcdparser
+ import imctools.io.txtparser as txtparser
+ import imctools.io.ometiffparser as omeparser
+ import imctools.io.mcdxmlparser as meta
+
+ fn_mcd = '/home/vitoz/Data/varia/201708_instrument_comp/mcd/20170815_imccomp_zoidberg_conc5_acm1.mcd'
+
+ mcd = mcdparser.McdParser(fn_mcd)
+
+ # parsed Metadata Access
+ mcd.acquisition_ids
+ mcd.get_acquisition_channels('1')
+ mcd.get_acquisition_description('1')
+
+ # a metadata object for comprehensive metadata access
+ acmeta = mcd.meta.get_object(meta.ACQUISITION, '1')
+ acmeta.properties
+
+ # The common class to represent a single IMC acquisition is
+ # The IMC acuqisition class.
+ # All parser classes have a 'get_imc_acquisition' method
+ imc_ac = mcd.get_imc_acquisition('1')
+
+ # imc acquisitions can yield the image data
+ image_matrix = imc_ac.get_img_by_metal('Ir191')
+
+ # or can be used to save the images using the image writer class
+ fn_out ='/home/vitoz/temp/test.ome.tiff'
+ img = imc_ac.get_image_writer(filename=fn_out, metals=['Ir191', 'Yb172'])
+ img.save_image(mode='ome', compression=0, dtype=None, bigtiff=False)
+
+ # as the mcd object is using lazy loading memory maps, it needs to be closed
+ # or used with a context manager.
+ mcd.close()
.. toctree::
:maxdepth: 2
diff --git a/imctools/__init__.py b/imctools/__init__.py
index e69de29..5efed93 100644
--- a/imctools/__init__.py
+++ b/imctools/__init__.py
@@ -0,0 +1,5 @@
+import warnings
+
+warnings.warn(
+ "imctools 1.x is deprecated, please migrate to version 2.x", DeprecationWarning
+)
diff --git a/imctools/external/omexml.py b/imctools/external/omexml.py
index cfb42dd..91a520c 100644
--- a/imctools/external/omexml.py
+++ b/imctools/external/omexml.py
@@ -19,24 +19,30 @@
from xml.etree import cElementTree as ElementTree
import sys
+
if sys.version_info.major == 3:
from io import StringIO
- uenc = 'unicode'
+
+ uenc = "unicode"
else:
from cStringIO import StringIO
- uenc = 'utf-8'
+
+ uenc = "utf-8"
import datetime
import logging
from functools import reduce
+
logger = logging.getLogger(__file__)
import re
import uuid
+
def xsd_now():
- '''Return the current time in xsd:dateTime format'''
+ """Return the current time in xsd:dateTime format"""
return datetime.datetime.now().isoformat()
+
DEFAULT_NOW = xsd_now()
#
# The namespaces
@@ -68,9 +74,12 @@ def xsd_now():
-""".format(ns_ome_default=NS_DEFAULT.format(ns_key='ome'),
- ns_sa_default=NS_DEFAULT.format(ns_key='sa'),
- NS_BINARY_FILE=NS_BINARY_FILE, DEFAULT_NOW=DEFAULT_NOW)
+""".format(
+ ns_ome_default=NS_DEFAULT.format(ns_key="ome"),
+ ns_sa_default=NS_DEFAULT.format(ns_key="sa"),
+ NS_BINARY_FILE=NS_BINARY_FILE,
+ DEFAULT_NOW=DEFAULT_NOW,
+)
#
# These are the OME-XML pixel types - not all supported by subimager
@@ -100,16 +109,16 @@ def xsd_now():
# The text for these can be found in
# loci.formats.in.BaseTiffReader.initStandardMetadata
#
-'''IFD # 254'''
+"""IFD # 254"""
OM_NEW_SUBFILE_TYPE = "NewSubfileType"
-'''IFD # 256'''
+"""IFD # 256"""
OM_IMAGE_WIDTH = "ImageWidth"
-'''IFD # 257'''
+"""IFD # 257"""
OM_IMAGE_LENGTH = "ImageLength"
-'''IFD # 258'''
+"""IFD # 258"""
OM_BITS_PER_SAMPLE = "BitsPerSample"
-'''IFD # 262'''
+"""IFD # 262"""
OM_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation"
PI_WHITE_IS_ZERO = "WhiteIsZero"
PI_BLACK_IS_ZERO = "BlackIsZero"
@@ -121,89 +130,89 @@ def xsd_now():
PI_CIE_LAB = "CIELAB"
PI_CFA_ARRAY = "Color Filter Array"
-'''BioFormats infers the image type from the photometric interpretation'''
+"""BioFormats infers the image type from the photometric interpretation"""
OM_METADATA_PHOTOMETRIC_INTERPRETATION = "MetaDataPhotometricInterpretation"
MPI_RGB = "RGB"
MPI_MONOCHROME = "Monochrome"
MPI_CMYK = "CMYK"
-'''IFD # 263'''
-OM_THRESHHOLDING = "Threshholding" # (sic)
-'''IFD # 264 (but can be 265 if the orientation = 8)'''
+"""IFD # 263"""
+OM_THRESHHOLDING = "Threshholding" # (sic)
+"""IFD # 264 (but can be 265 if the orientation = 8)"""
OM_CELL_WIDTH = "CellWidth"
-'''IFD # 265'''
+"""IFD # 265"""
OM_CELL_LENGTH = "CellLength"
-'''IFD # 266'''
+"""IFD # 266"""
OM_FILL_ORDER = "FillOrder"
-'''IFD # 279'''
+"""IFD # 279"""
OM_DOCUMENT_NAME = "Document Name"
-'''IFD # 271'''
+"""IFD # 271"""
OM_MAKE = "Make"
-'''IFD # 272'''
+"""IFD # 272"""
OM_MODEL = "Model"
-'''IFD # 274'''
+"""IFD # 274"""
OM_ORIENTATION = "Orientation"
-'''IFD # 277'''
+"""IFD # 277"""
OM_SAMPLES_PER_PIXEL = "SamplesPerPixel"
-'''IFD # 280'''
+"""IFD # 280"""
OM_MIN_SAMPLE_VALUE = "MinSampleValue"
-'''IFD # 281'''
+"""IFD # 281"""
OM_MAX_SAMPLE_VALUE = "MaxSampleValue"
-'''IFD # 282'''
+"""IFD # 282"""
OM_X_RESOLUTION = "XResolution"
-'''IFD # 283'''
+"""IFD # 283"""
OM_Y_RESOLUTION = "YResolution"
-'''IFD # 284'''
+"""IFD # 284"""
OM_PLANAR_CONFIGURATION = "PlanarConfiguration"
PC_CHUNKY = "Chunky"
PC_PLANAR = "Planar"
-'''IFD # 286'''
+"""IFD # 286"""
OM_X_POSITION = "XPosition"
-'''IFD # 287'''
+"""IFD # 287"""
OM_Y_POSITION = "YPosition"
-'''IFD # 288'''
+"""IFD # 288"""
OM_FREE_OFFSETS = "FreeOffsets"
-'''IFD # 289'''
+"""IFD # 289"""
OM_FREE_BYTECOUNTS = "FreeByteCounts"
-'''IFD # 290'''
+"""IFD # 290"""
OM_GRAY_RESPONSE_UNIT = "GrayResponseUnit"
-'''IFD # 291'''
+"""IFD # 291"""
OM_GRAY_RESPONSE_CURVE = "GrayResponseCurve"
-'''IFD # 292'''
+"""IFD # 292"""
OM_T4_OPTIONS = "T4Options"
-'''IFD # 293'''
+"""IFD # 293"""
OM_T6_OPTIONS = "T6Options"
-'''IFD # 296'''
+"""IFD # 296"""
OM_RESOLUTION_UNIT = "ResolutionUnit"
-'''IFD # 297'''
+"""IFD # 297"""
OM_PAGE_NUMBER = "PageNumber"
-'''IFD # 301'''
+"""IFD # 301"""
OM_TRANSFER_FUNCTION = "TransferFunction"
-'''IFD # 305'''
+"""IFD # 305"""
OM_SOFTWARE = "Software"
-'''IFD # 306'''
+"""IFD # 306"""
OM_DATE_TIME = "DateTime"
-'''IFD # 315'''
+"""IFD # 315"""
OM_ARTIST = "Artist"
-'''IFD # 316'''
+"""IFD # 316"""
OM_HOST_COMPUTER = "HostComputer"
-'''IFD # 317'''
+"""IFD # 317"""
OM_PREDICTOR = "Predictor"
-'''IFD # 318'''
+"""IFD # 318"""
OM_WHITE_POINT = "WhitePoint"
-'''IFD # 322'''
+"""IFD # 322"""
OM_TILE_WIDTH = "TileWidth"
-'''IFD # 323'''
+"""IFD # 323"""
OM_TILE_LENGTH = "TileLength"
-'''IFD # 324'''
+"""IFD # 324"""
OM_TILE_OFFSETS = "TileOffsets"
-'''IFD # 325'''
+"""IFD # 325"""
OM_TILE_BYTE_COUNT = "TileByteCount"
-'''IFD # 332'''
+"""IFD # 332"""
OM_INK_SET = "InkSet"
-'''IFD # 33432'''
+"""IFD # 33432"""
OM_COPYRIGHT = "Copyright"
#
# Well row/column naming conventions
@@ -211,72 +220,82 @@ def xsd_now():
NC_LETTER = "letter"
NC_NUMBER = "number"
+
def page_name_original_metadata(index):
- '''Get the key name for the page name metadata data for the indexed tiff page
+ """Get the key name for the page name metadata data for the indexed tiff page
These are TIFF IFD #'s 285+
index - zero-based index of the page
- '''
+ """
return "PageName #%d" % index
+
def get_text(node):
- '''Get the contents of text nodes in a parent node'''
+ """Get the contents of text nodes in a parent node"""
return node.text
+
def set_text(node, text):
- '''Set the text of a parent'''
+ """Set the text of a parent"""
node.text = text
+
def qn(namespace, tag_name):
- '''Return the qualified name for a given namespace and tag name
+ """Return the qualified name for a given namespace and tag name
This is the ElementTree representation of a qualified name
- '''
+ """
return "{%s}%s" % (namespace, tag_name)
+
def split_qn(qn):
- '''Split a qualified tag name or return None if namespace not present'''
- m = re.match('\{(.*)\}(.*)', qn)
+ """Split a qualified tag name or return None if namespace not present"""
+ m = re.match("\{(.*)\}(.*)", qn)
return m.group(1), m.group(2) if m else None
+
def get_namespaces(node):
- '''Get top-level XML namespaces from a node.'''
- ns_lib = {'ome': None, 'sa': None, 'spw': None}
+ """Get top-level XML namespaces from a node."""
+ ns_lib = {"ome": None, "sa": None, "spw": None}
for child in node.iter():
ns = split_qn(child.tag)[0]
match = re.match(NS_RE, ns)
if match:
- ns_key = match.group('ns_key').lower()
+ ns_key = match.group("ns_key").lower()
ns_lib[ns_key] = ns
return ns_lib
+
def get_float_attr(node, attribute):
- '''Cast an element attribute to a float or return None if not present'''
+ """Cast an element attribute to a float or return None if not present"""
attr = node.get(attribute)
return None if attr is None else float(attr)
+
def get_int_attr(node, attribute):
- '''Cast an element attribute to an int or return None if not present'''
+ """Cast an element attribute to an int or return None if not present"""
attr = node.get(attribute)
return None if attr is None else int(attr)
+
def make_text_node(parent, namespace, tag_name, text):
- '''Either make a new node and add the given text or replace the text
+ """Either make a new node and add the given text or replace the text
parent - the parent node to the node to be created or found
namespace - the namespace of the node's qualified name
tag_name - the tag name of the node's qualified name
text - the text to be inserted
- '''
+ """
qname = qn(namespace, tag_name)
node = parent.find(qname)
if node is None:
node = ElementTree.SubElement(parent, qname)
set_text(node, text)
+
class OMEXML(object):
- '''Reads and writes OME-XML with methods to get and set it.
+ """Reads and writes OME-XML with methods to get and set it.
The OMEXML class has four main purposes: to parse OME-XML, to output
OME-XML, to provide a structured mechanism for inspecting OME-XML and to
@@ -317,7 +336,8 @@ class OMEXML(object):
See the `OME-XML schema documentation `_.
- '''
+ """
+
def __init__(self, xml=None):
if xml is None:
xml = default_xml
@@ -327,7 +347,7 @@ def __init__(self, xml=None):
# determine OME namespaces
self.ns = get_namespaces(self.dom.getroot())
- if self.ns['ome'] is None:
+ if self.ns["ome"] is None:
raise Exception("Error: String not in OME-XML format")
def __str__(self):
@@ -340,9 +360,9 @@ def __str__(self):
ElementTree.register_namespace(ns_key, ns)
ElementTree.register_namespace("om", NS_ORIGINAL_METADATA)
result = StringIO()
- ElementTree.ElementTree(self.root_node).write(result,
- encoding=uenc,
- method="xml")
+ ElementTree.ElementTree(self.root_node).write(
+ result, encoding=uenc, method="xml"
+ )
return result.getvalue()
def to_xml(self, indent="\t", newline="\n", encoding=uenc):
@@ -356,24 +376,27 @@ def root_node(self):
return self.dom.getroot()
def get_image_count(self):
- '''The number of images (= series) specified by the XML'''
- return len(self.root_node.findall(qn(self.ns['ome'], "Image")))
+ """The number of images (= series) specified by the XML"""
+ return len(self.root_node.findall(qn(self.ns["ome"], "Image")))
def set_image_count(self, value):
- '''Add or remove image nodes as needed'''
+ """Add or remove image nodes as needed"""
assert value > 0
root = self.root_node
if self.image_count > value:
- image_nodes = root.find(qn(self.ns['ome'], "Image"))
+ image_nodes = root.find(qn(self.ns["ome"], "Image"))
for image_node in image_nodes[value:]:
root.remove(image_node)
- while(self.image_count < value):
- new_image = self.Image(ElementTree.SubElement(root, qn(self.ns['ome'], "Image")))
+ while self.image_count < value:
+ new_image = self.Image(
+ ElementTree.SubElement(root, qn(self.ns["ome"], "Image"))
+ )
new_image.ID = str(uuid.uuid4())
new_image.Name = "default.png"
new_image.AcquisitionDate = xsd_now()
new_pixels = self.Pixels(
- ElementTree.SubElement(new_image.node, qn(self.ns['ome'], "Pixels")))
+ ElementTree.SubElement(new_image.node, qn(self.ns["ome"], "Pixels"))
+ )
new_pixels.ID = str(uuid.uuid4())
new_pixels.DimensionOrder = DO_XYCTZ
new_pixels.PixelType = PT_UINT8
@@ -383,7 +406,8 @@ def set_image_count(self, value):
new_pixels.SizeY = 512
new_pixels.SizeZ = 1
new_channel = self.Channel(
- ElementTree.SubElement(new_pixels.node, qn(self.ns['ome'], "Channel")))
+ ElementTree.SubElement(new_pixels.node, qn(self.ns["ome"], "Channel"))
+ )
new_channel.ID = "Channel%d:0" % self.image_count
new_channel.Name = new_channel.ID
new_channel.SamplesPerPixel = 1
@@ -396,21 +420,23 @@ def plates(self):
@property
def structured_annotations(self):
- '''Return the structured annotations container
+ """Return the structured annotations container
returns a wrapping of OME/StructuredAnnotations. It creates
the element if it doesn't exist.
- '''
- node = self.root_node.find(qn(self.ns['sa'], "StructuredAnnotations"))
+ """
+ node = self.root_node.find(qn(self.ns["sa"], "StructuredAnnotations"))
if node is None:
node = ElementTree.SubElement(
- self.root_node, qn(self.ns['sa'], "StructuredAnnotations"))
+ self.root_node, qn(self.ns["sa"], "StructuredAnnotations")
+ )
return self.StructuredAnnotations(node)
class Image(object):
- '''Representation of the OME/Image element'''
+ """Representation of the OME/Image element"""
+
def __init__(self, node):
- '''Initialize with the DOM Image node'''
+ """Initialize with the DOM Image node"""
self.node = node
self.ns = get_namespaces(self.node)
@@ -424,12 +450,14 @@ def set_ID(self, value):
def get_Name(self):
return self.node.get("Name")
+
def set_Name(self, value):
self.node.set("Name", value)
+
Name = property(get_Name, set_Name)
def get_AcquisitionDate(self):
- '''The date in ISO-8601 format'''
+ """The date in ISO-8601 format"""
acquired_date = self.node.find(qn(self.ns["ome"], "AcquisitionDate"))
if acquired_date is None:
return None
@@ -439,38 +467,44 @@ def set_AcquisitionDate(self, date):
acquired_date = self.node.find(qn(self.ns["ome"], "AcquisitionDate"))
if acquired_date is None:
acquired_date = ElementTree.SubElement(
- self.node, qn(self.ns["ome"], "AcquisitionDate"))
+ self.node, qn(self.ns["ome"], "AcquisitionDate")
+ )
set_text(acquired_date, date)
- AcquisitionDate = property(get_AcquisitionDate, set_AcquisitionDate)
+ AcquisitionDate = property(get_AcquisitionDate, set_AcquisitionDate)
@property
def Pixels(self):
- '''The OME/Image/Pixels element.
+ """The OME/Image/Pixels element.
- '''
- return OMEXML.Pixels(self.node.find(qn(self.ns['ome'], "Pixels")))
+ """
+ return OMEXML.Pixels(self.node.find(qn(self.ns["ome"], "Pixels")))
def image(self, index=0):
- '''Return an image node by index'''
- return self.Image(self.root_node.findall(qn(self.ns['ome'], "Image"))[index])
+ """Return an image node by index"""
+ return self.Image(self.root_node.findall(qn(self.ns["ome"], "Image"))[index])
class Channel(object):
- '''The OME/Image/Pixels/Channel element'''
+ """The OME/Image/Pixels/Channel element"""
+
def __init__(self, node):
self.node = node
self.ns = get_namespaces(node)
def get_ID(self):
return self.node.get("ID")
+
def set_ID(self, value):
self.node.set("ID", value)
+
ID = property(get_ID, set_ID)
def get_Name(self):
return self.node.get("Name")
+
def set_Name(self, value):
self.node.set("Name", value)
+
Name = property(get_Name, set_Name)
def get_SamplesPerPixel(self):
@@ -478,21 +512,23 @@ def get_SamplesPerPixel(self):
def set_SamplesPerPixel(self, value):
self.node.set("SamplesPerPixel", str(value))
+
SamplesPerPixel = property(get_SamplesPerPixel, set_SamplesPerPixel)
class Plane(object):
- '''The OME/Image/Pixels/Plane element
+ """The OME/Image/Pixels/Plane element
The Plane element represents one 2-dimensional image plane. It
has the Z, C and T indices of the plane and optionally has the
X, Y, Z, exposure time and a relative time delta.
- '''
+ """
+
def __init__(self, node):
self.node = node
self.ns = get_namespaces(self.node)
def get_TheZ(self):
- '''The Z index of the plane'''
+ """The Z index of the plane"""
return get_int_attr(self.node, "TheZ")
def set_TheZ(self, value):
@@ -501,7 +537,7 @@ def set_TheZ(self, value):
TheZ = property(get_TheZ, set_TheZ)
def get_TheC(self):
- '''The channel index of the plane'''
+ """The channel index of the plane"""
return get_int_attr(self.node, "TheC")
def set_TheC(self, value):
@@ -510,7 +546,7 @@ def set_TheC(self, value):
TheC = property(get_TheC, set_TheC)
def get_TheT(self):
- '''The T index of the plane'''
+ """The T index of the plane"""
return get_int_attr(self.node, "TheT")
def set_TheT(self, value):
@@ -519,7 +555,7 @@ def set_TheT(self, value):
TheT = property(get_TheT, set_TheT)
def get_DeltaT(self):
- '''# of seconds since the beginning of the experiment'''
+ """# of seconds since the beginning of the experiment"""
return get_float_attr(self.node, "DeltaT")
def set_DeltaT(self, value):
@@ -529,14 +565,14 @@ def set_DeltaT(self, value):
@property
def ExposureTime(self):
- '''Units are seconds. Duration of acquisition????'''
+ """Units are seconds. Duration of acquisition????"""
exposure_time = self.node.get("ExposureTime")
if exposure_time is not None:
return float(exposure_time)
return None
def get_PositionX(self):
- '''X position of stage'''
+ """X position of stage"""
position_x = self.node.get("PositionX")
if position_x is not None:
return float(position_x)
@@ -548,7 +584,7 @@ def set_PositionX(self, value):
PositionX = property(get_PositionX, set_PositionX)
def get_PositionY(self):
- '''Y position of stage'''
+ """Y position of stage"""
return get_float_attr(self.node, "PositionY")
def set_PositionY(self, value):
@@ -557,7 +593,7 @@ def set_PositionY(self, value):
PositionY = property(get_PositionY, set_PositionY)
def get_PositionZ(self):
- '''Z position of stage'''
+ """Z position of stage"""
return get_float_attr(self.node, "PositionZ")
def set_PositionZ(self, value):
@@ -566,86 +602,101 @@ def set_PositionZ(self, value):
PositionZ = property(get_PositionZ, set_PositionZ)
class Pixels(object):
- '''The OME/Image/Pixels element
+ """The OME/Image/Pixels element
The Pixels element represents the pixels in an OME image and, for
an OME-XML encoded image, will actually contain the base-64 encoded
pixel data. It has the X, Y, Z, C, and T extents of the image
and it specifies the channel interleaving and channel depth.
- '''
+ """
+
def __init__(self, node):
self.node = node
self.ns = get_namespaces(self.node)
def get_ID(self):
return self.node.get("ID")
+
def set_ID(self, value):
self.node.set("ID", value)
+
ID = property(get_ID, set_ID)
def get_DimensionOrder(self):
- '''The ordering of image planes in the file
+ """The ordering of image planes in the file
A 5-letter code indicating the ordering of pixels, from the most
rapidly varying to least. Use the DO_* constants (for instance
DO_XYZCT) to compare and set this.
- '''
+ """
return self.node.get("DimensionOrder")
+
def set_DimensionOrder(self, value):
self.node.set("DimensionOrder", value)
+
DimensionOrder = property(get_DimensionOrder, set_DimensionOrder)
def get_PixelType(self):
- '''The pixel bit type, for instance PT_UINT8
+ """The pixel bit type, for instance PT_UINT8
The pixel type specifies the datatype used to encode pixels
in the image data. You can use the PT_* constants to compare
and set the pixel type.
- '''
+ """
return self.node.get("Type")
+
def set_PixelType(self, value):
self.node.set("Type", value)
+
PixelType = property(get_PixelType, set_PixelType)
def get_SizeX(self):
- '''The dimensions of the image in the X direction in pixels'''
+ """The dimensions of the image in the X direction in pixels"""
return get_int_attr(self.node, "SizeX")
+
def set_SizeX(self, value):
self.node.set("SizeX", str(value))
+
SizeX = property(get_SizeX, set_SizeX)
def get_SizeY(self):
- '''The dimensions of the image in the Y direction in pixels'''
+ """The dimensions of the image in the Y direction in pixels"""
return get_int_attr(self.node, "SizeY")
+
def set_SizeY(self, value):
self.node.set("SizeY", str(value))
+
SizeY = property(get_SizeY, set_SizeY)
def get_SizeZ(self):
- '''The dimensions of the image in the Z direction in pixels'''
+ """The dimensions of the image in the Z direction in pixels"""
return get_int_attr(self.node, "SizeZ")
def set_SizeZ(self, value):
self.node.set("SizeZ", str(value))
+
SizeZ = property(get_SizeZ, set_SizeZ)
def get_SizeT(self):
- '''The dimensions of the image in the T direction in pixels'''
+ """The dimensions of the image in the T direction in pixels"""
return get_int_attr(self.node, "SizeT")
def set_SizeT(self, value):
self.node.set("SizeT", str(value))
+
SizeT = property(get_SizeT, set_SizeT)
def get_SizeC(self):
- '''The dimensions of the image in the C direction in pixels'''
+ """The dimensions of the image in the C direction in pixels"""
return get_int_attr(self.node, "SizeC")
+
def set_SizeC(self, value):
self.node.set("SizeC", str(value))
+
SizeC = property(get_SizeC, set_SizeC)
def get_channel_count(self):
- '''The number of channels in the image
+ """The number of channels in the image
You can change the number of channels in the image by
setting the channel_count:
@@ -653,20 +704,21 @@ def get_channel_count(self):
pixels.channel_count = 3
pixels.Channel(0).Name = "Red"
...
- '''
- return len(self.node.findall(qn(self.ns['ome'], "Channel")))
+ """
+ return len(self.node.findall(qn(self.ns["ome"], "Channel")))
def set_channel_count(self, value):
assert value > 0
channel_count = self.channel_count
if channel_count > value:
- channels = self.node.findall(qn(self.ns['ome'], "Channel"))
+ channels = self.node.findall(qn(self.ns["ome"], "Channel"))
for channel in channels[value:]:
self.node.remove(channel)
else:
for _ in range(channel_count, value):
new_channel = OMEXML.Channel(
- ElementTree.SubElement(self.node, qn(self.ns['ome'], "Channel")))
+ ElementTree.SubElement(self.node, qn(self.ns["ome"], "Channel"))
+ )
new_channel.ID = str(uuid.uuid4())
new_channel.Name = new_channel.ID
new_channel.SamplesPerPixel = 1
@@ -674,12 +726,12 @@ def set_channel_count(self, value):
channel_count = property(get_channel_count, set_channel_count)
def Channel(self, index=0):
- '''Get the indexed channel from the Pixels element'''
- channel = self.node.findall(qn(self.ns['ome'], "Channel"))[index]
+ """Get the indexed channel from the Pixels element"""
+ channel = self.node.findall(qn(self.ns["ome"], "Channel"))[index]
return OMEXML.Channel(channel)
def get_plane_count(self):
- '''The number of planes in the image
+ """The number of planes in the image
An image with only one plane or an interleaved color plane will
often not have any planes.
@@ -690,30 +742,31 @@ def get_plane_count(self):
pixels.plane_count = 3
pixels.Plane(0).TheZ=pixels.Plane(0).TheC=pixels.Plane(0).TheT=0
...
- '''
- return len(self.node.findall(qn(self.ns['ome'], "Plane")))
+ """
+ return len(self.node.findall(qn(self.ns["ome"], "Plane")))
def set_plane_count(self, value):
assert value >= 0
plane_count = self.plane_count
if plane_count > value:
- planes = self.node.findall(qn(self.ns['ome'], "Plane"))
+ planes = self.node.findall(qn(self.ns["ome"], "Plane"))
for plane in planes[value:]:
self.node.remove(plane)
else:
for _ in range(plane_count, value):
new_plane = OMEXML.Plane(
- ElementTree.SubElement(self.node, qn(self.ns['ome'], "Plane")))
+ ElementTree.SubElement(self.node, qn(self.ns["ome"], "Plane"))
+ )
plane_count = property(get_plane_count, set_plane_count)
def Plane(self, index=0):
- '''Get the indexed plane from the Pixels element'''
- plane = self.node.findall(qn(self.ns['ome'], "Plane"))[index]
+ """Get the indexed plane from the Pixels element"""
+ plane = self.node.findall(qn(self.ns["ome"], "Plane"))[index]
return OMEXML.Plane(plane)
class StructuredAnnotations(dict):
- '''The OME/StructuredAnnotations element
+ """The OME/StructuredAnnotations element
Structured annotations let OME-XML represent metadata from other file
formats, for example the tag metadata in TIFF files. The
@@ -730,7 +783,7 @@ class StructuredAnnotations(dict):
callers will be using these to read tag data that's not represented
in OME-XML such as the bits per sample and min and max sample values.
- '''
+ """
def __init__(self, node):
self.node = node
@@ -746,8 +799,9 @@ def __contains__(self, key):
return self.has_key(key)
def keys(self):
- return filter(lambda x: x is not None,
- [child.get("ID") for child in self.node])
+ return filter(
+ lambda x: x is not None, [child.get("ID") for child in self.node]
+ )
def has_key(self, key):
for child in self.node:
@@ -756,30 +810,33 @@ def has_key(self, key):
return False
def add_original_metadata(self, key, value):
- '''Create an original data key/value pair
+ """Create an original data key/value pair
key - the original metadata's key name, for instance OM_PHOTOMETRIC_INTERPRETATION
value - the value, for instance, "RGB"
returns the ID for the structured annotation.
- '''
+ """
xml_annotation = ElementTree.SubElement(
- self.node, qn(self.ns['sa'], "XMLAnnotation"))
+ self.node, qn(self.ns["sa"], "XMLAnnotation")
+ )
node_id = str(uuid.uuid4())
xml_annotation.set("ID", node_id)
- xa_value = ElementTree.SubElement(xml_annotation, qn(self.ns['sa'], "Value"))
+ xa_value = ElementTree.SubElement(
+ xml_annotation, qn(self.ns["sa"], "Value")
+ )
ov = ElementTree.SubElement(
- xa_value, qn(NS_ORIGINAL_METADATA, "OriginalMetadata"))
+ xa_value, qn(NS_ORIGINAL_METADATA, "OriginalMetadata")
+ )
ov_key = ElementTree.SubElement(ov, qn(NS_ORIGINAL_METADATA, "Key"))
set_text(ov_key, key)
- ov_value = ElementTree.SubElement(
- ov, qn(NS_ORIGINAL_METADATA, "Value"))
+ ov_value = ElementTree.SubElement(ov, qn(NS_ORIGINAL_METADATA, "Value"))
set_text(ov_value, value)
return node_id
def iter_original_metadata(self):
- '''An iterator over the original metadata in structured annotations
+ """An iterator over the original metadata in structured annotations
returns (, ())
@@ -789,7 +846,7 @@ def iter_original_metadata(self):
is the original metadata key, typically one of the
OM_* names of a TIFF tag
is the value for the metadata
- '''
+ """
#
# Here's the XML we're traversing:
#
@@ -804,13 +861,18 @@ def iter_original_metadata(self):
#
#
#
- for annotation_node in self.node.findall(qn(self.ns['sa'], "XMLAnnotation")):
+ for annotation_node in self.node.findall(
+ qn(self.ns["sa"], "XMLAnnotation")
+ ):
#
annotation_id = annotation_node.get("ID")
- for xa_value_node in annotation_node.findall(qn(self.ns['sa'], "Value")):
+ for xa_value_node in annotation_node.findall(
+ qn(self.ns["sa"], "Value")
+ ):
#
for om_node in xa_value_node.findall(
- qn(NS_ORIGINAL_METADATA, "OriginalMetadata")):
+ qn(NS_ORIGINAL_METADATA, "OriginalMetadata")
+ ):
#
key_node = om_node.find(qn(NS_ORIGINAL_METADATA, "Key"))
value_node = om_node.find(qn(NS_ORIGINAL_METADATA, "Value"))
@@ -820,35 +882,38 @@ def iter_original_metadata(self):
if key_text is not None and value_text is not None:
yield annotation_id, (key_text, value_text)
else:
- logger.warn("Original metadata was missing key or value:" + om_node.toxml())
+ logger.warn(
+ "Original metadata was missing key or value:"
+ + om_node.toxml()
+ )
return
def has_original_metadata(self, key):
- '''True if there is an original metadata item with the given key'''
- return any([k == key
- for annotation_id, (k, v)
- in self.iter_original_metadata()])
+ """True if there is an original metadata item with the given key"""
+ return any(
+ [k == key for annotation_id, (k, v) in self.iter_original_metadata()]
+ )
def get_original_metadata_value(self, key, default=None):
- '''Return the value for a particular original metadata key
+ """Return the value for a particular original metadata key
key - key to search for
default - default value to return if not found
- '''
+ """
for annotation_id, (k, v) in self.iter_original_metadata():
if k == key:
return v
return default
def get_original_metadata_refs(self, ids):
- '''For a given ID, get the matching original metadata references
+ """For a given ID, get the matching original metadata references
ids - collection of IDs to match
returns a dictionary of key to value
- '''
+ """
d = {}
- for annotation_id, (k,v) in self.iter_original_metadata():
+ for annotation_id, (k, v) in self.iter_original_metadata():
if annotation_id in ids:
d[k] = v
return d
@@ -858,13 +923,14 @@ def OriginalMetadata(self):
return OMEXML.OriginalMetadata(self)
class OriginalMetadata(dict):
- '''View original metadata as a dictionary
+ """View original metadata as a dictionary
Original metadata holds "vendor-specific" metadata including TIFF
tag values.
- '''
+ """
+
def __init__(self, sa):
- '''Initialized with the structured_annotations class instance'''
+ """Initialized with the structured_annotations class instance"""
self.sa = sa
def __getitem__(self, key):
@@ -884,9 +950,9 @@ def __len__(self):
return len(list(self.sa_iter_original_metadata()))
def keys(self):
- return [key
- for annotation_id, (key, value)
- in self.sa.iter_original_metadata()]
+ return [
+ key for annotation_id, (key, value) in self.sa.iter_original_metadata()
+ ]
def has_key(self, key):
for annotation_id, (k, value) in self.sa.iter_original_metadata():
@@ -899,38 +965,41 @@ def iteritems(self):
yield key, value
class PlatesDucktype(object):
- '''It looks like a list of plates'''
+ """It looks like a list of plates"""
+
def __init__(self, root):
self.root = root
self.ns = get_namespaces(self.root)
def __getitem__(self, key):
- plates = self.root.findall(qn(self.ns['spw'], "Plate"))
+ plates = self.root.findall(qn(self.ns["spw"], "Plate"))
if isinstance(key, slice):
return [OMEXML.Plate(plate) for plate in plates[key]]
return OMEXML.Plate(plates[key])
def __len__(self):
- return len(self.root.findall(qn(self.ns['spw'], "Plate")))
+ return len(self.root.findall(qn(self.ns["spw"], "Plate")))
def __iter__(self):
- for plate in self.root.iterfind(qn(self.ns['spw'], "Plate")):
+ for plate in self.root.iterfind(qn(self.ns["spw"], "Plate")):
yield OMEXML.Plate(plate)
- def newPlate(self, name, plate_id = str(uuid.uuid4())):
+ def newPlate(self, name, plate_id=str(uuid.uuid4())):
new_plate_node = ElementTree.SubElement(
- self.root, qn(self.ns['spw'], "Plate"))
+ self.root, qn(self.ns["spw"], "Plate")
+ )
new_plate = OMEXML.Plate(new_plate_node)
new_plate.ID = plate_id
new_plate.Name = name
return new_plate
class Plate(object):
- '''The SPW:Plate element
+ """The SPW:Plate element
This represents the plate element of the SPW schema:
http://www.openmicroscopy.org/Schemas/SPW/2007-06/
- '''
+ """
+
def __init__(self, node):
self.node = node
self.ns = get_namespaces(self.node)
@@ -974,8 +1043,10 @@ def get_ColumnNamingConvention(self):
def set_ColumnNamingConvention(self, value):
assert value in (NC_LETTER, NC_NUMBER)
self.node.set("ColumnNamingConvention", value)
- ColumnNamingConvention = property(get_ColumnNamingConvention,
- set_ColumnNamingConvention)
+
+ ColumnNamingConvention = property(
+ get_ColumnNamingConvention, set_ColumnNamingConvention
+ )
def get_RowNamingConvention(self):
# Consider a default if not defined of NC_LETTER
@@ -984,14 +1055,15 @@ def get_RowNamingConvention(self):
def set_RowNamingConvention(self, value):
assert value in (NC_LETTER, NC_NUMBER)
self.node.set("RowNamingConvention", value)
- RowNamingConvention = property(get_RowNamingConvention,
- set_RowNamingConvention)
+
+ RowNamingConvention = property(get_RowNamingConvention, set_RowNamingConvention)
def get_WellOriginX(self):
return get_float_attr(self.node, "WellOriginX")
def set_WellOriginX(self, value):
self.node.set("WellOriginX", str(value))
+
WellOriginX = property(get_WellOriginX, set_WellOriginX)
def get_WellOriginY(self):
@@ -999,6 +1071,7 @@ def get_WellOriginY(self):
def set_WellOriginY(self, value):
self.node.set("WellOriginY", str(value))
+
WellOriginY = property(get_WellOriginY, set_WellOriginY)
def get_Rows(self):
@@ -1018,32 +1091,39 @@ def set_Columns(self, value):
Columns = property(get_Columns, set_Columns)
def get_Description(self):
- description = self.node.find(qn(self.ns['spw'], "Description"))
+ description = self.node.find(qn(self.ns["spw"], "Description"))
if description is None:
return None
return get_text(description)
def set_Description(self, text):
make_text_node(self.node, NS_SPW, "Description", test)
+
Description = property(get_Description, set_Description)
def get_Well(self):
- '''The well dictionary / list'''
+ """The well dictionary / list"""
return OMEXML.WellsDucktype(self)
+
Well = property(get_Well)
def get_well_name(self, well):
- '''Get a well's name, using the row and column convention'''
- result = "".join([
- "%02d" % (i+1) if convention == NC_NUMBER
- else "ABCDEFGHIJKLMNOP"[i]
- for i, convention
- in ((well.Row, self.RowNamingConvention or NC_LETTER),
- (well.Column, self.ColumnNamingConvention or NC_NUMBER))])
+ """Get a well's name, using the row and column convention"""
+ result = "".join(
+ [
+ "%02d" % (i + 1)
+ if convention == NC_NUMBER
+ else "ABCDEFGHIJKLMNOP"[i]
+ for i, convention in (
+ (well.Row, self.RowNamingConvention or NC_LETTER),
+ (well.Column, self.ColumnNamingConvention or NC_NUMBER),
+ )
+ ]
+ )
return result
class WellsDucktype(dict):
- '''The WellsDucktype lets you retrieve and create wells
+ """The WellsDucktype lets you retrieve and create wells
The WellsDucktype looks like a dictionary but lets you reference
the wells in a plate using indexing. Types of indexes:
@@ -1056,17 +1136,18 @@ class WellsDucktype(dict):
by ID - e.g. plate.Well["Well:0:0:0"]
If the ducktype is unable to parse a well name, it assumes you're
using an ID.
- '''
+ """
+
def __init__(self, plate):
self.plate_node = plate.node
self.plate = plate
self.ns = get_namespaces(self.plate_node)
def __len__(self):
- return len(self.plate_node.findall(qn(self.ns['spw'], "Well")))
+ return len(self.plate_node.findall(qn(self.ns["spw"], "Well")))
def __getitem__(self, key):
- all_wells = self.plate_node.findall(qn(self.ns['spw'], "Well"))
+ all_wells = self.plate_node.findall(qn(self.ns["spw"], "Well"))
if isinstance(key, slice):
return [OMEXML.Well(w) for w in all_wells[key]]
if hasattr(key, "__len__") and len(key) == 2:
@@ -1087,26 +1168,27 @@ def __getitem__(self, key):
return None
def __iter__(self):
- '''Return the standard name for all wells on the plate
+ """Return the standard name for all wells on the plate
for instance, 'B03' for a well with Row=1, Column=2 for a plate
with the standard row and column naming convention
- '''
- all_wells = self.plate_node.findall(qn(self.ns['spw'], "Well"))
+ """
+ all_wells = self.plate_node.findall(qn(self.ns["spw"], "Well"))
well = OMEXML.Well(None)
for w in all_wells:
well.node = w
yield self.plate.get_well_name(well)
- def new(self, row, column, well_id = str(uuid.uuid4())):
- '''Create a new well at the given row and column
+ def new(self, row, column, well_id=str(uuid.uuid4())):
+ """Create a new well at the given row and column
row - index of well's row
column - index of well's column
well_id - the ID attribute for the well
- '''
+ """
well_node = ElementTree.SubElement(
- self.plate_node, qn(self.ns['spw'], "Well"))
+ self.plate_node, qn(self.ns["spw"], "Well")
+ )
well = OMEXML.Well(well_node)
well.Row = row
well.Column = column
@@ -1119,24 +1201,31 @@ def __init__(self, node):
def get_Column(self):
return get_int_attr(self.node, "Column")
+
def set_Column(self, value):
self.node.set("Column", str(value))
+
Column = property(get_Column, set_Column)
def get_Row(self):
return get_int_attr(self.node, "Row")
+
def set_Row(self, value):
self.node.set("Row", str(value))
+
Row = property(get_Row, set_Row)
def get_ID(self):
return self.node.get("ID")
+
def set_ID(self, value):
self.node.set("ID", value)
+
ID = property(get_ID, set_ID)
def get_Sample(self):
return OMEXML.WellSampleDucktype(self.node)
+
Sample = property(get_Sample)
def get_ExternalDescription(self):
@@ -1162,59 +1251,65 @@ def set_Color(self, value):
self.node.set("Color", str(value))
class WellSampleDucktype(list):
- '''The WellSample elements in a well
+ """The WellSample elements in a well
This is made to look like an indexable list so that you can do
things like:
wellsamples[0:2]
- '''
+ """
+
def __init__(self, well_node):
self.well_node = well_node
self.ns = get_namespaces(self.well_node)
def __len__(self):
- return len(self.well_node.findall(qn(self.ns['spw'], "WellSample")))
+ return len(self.well_node.findall(qn(self.ns["spw"], "WellSample")))
def __getitem__(self, key):
- all_samples = self.well_node.findall(qn(self.ns['spw'], "WellSample"))
+ all_samples = self.well_node.findall(qn(self.ns["spw"], "WellSample"))
if isinstance(key, slice):
- return [OMEXML.WellSample(s)
- for s in all_samples[key]]
+ return [OMEXML.WellSample(s) for s in all_samples[key]]
return OMEXML.WellSample(all_samples[int(key)])
def __iter__(self):
- '''Iterate through the well samples.'''
- all_samples = self.well_node.findall(qn(self.ns['spw'], "WellSample"))
+ """Iterate through the well samples."""
+ all_samples = self.well_node.findall(qn(self.ns["spw"], "WellSample"))
for s in all_samples:
yield OMEXML.WellSample(s)
- def new(self, wellsample_id = str(uuid.uuid4()), index = None):
- '''Create a new well sample
- '''
+ def new(self, wellsample_id=str(uuid.uuid4()), index=None):
+ """Create a new well sample
+ """
if index is None:
index = reduce(max, [s.Index for s in self], -1) + 1
new_node = ElementTree.SubElement(
- self.well_node, qn(self.ns['spw'], "WellSample"))
+ self.well_node, qn(self.ns["spw"], "WellSample")
+ )
s = OMEXML.WellSample(new_node)
s.ID = wellsample_id
s.Index = index
class WellSample(object):
- '''The WellSample is a location within a well'''
+ """The WellSample is a location within a well"""
+
def __init__(self, node):
self.node = node
self.ns = get_namespaces(self.node)
def get_ID(self):
return self.node.get("ID")
+
def set_ID(self, value):
self.node.set("ID", value)
+
ID = property(get_ID, set_ID)
def get_PositionX(self):
return get_float_attr(self.node, "PositionX")
+
def set_PositionX(self, value):
self.node.set("PositionX", str(value))
+
PositionX = property(get_PositionX, set_PositionX)
def get_PositionY(self):
@@ -1222,6 +1317,7 @@ def get_PositionY(self):
def set_PositionY(self, value):
self.node.set("PositionY", str(value))
+
PositionY = property(get_PositionY, set_PositionY)
def get_Timepoint(self):
@@ -1231,6 +1327,7 @@ def set_Timepoint(self, value):
if isinstance(value, datetime.datetime):
value = value.isoformat()
self.node.set("Timepoint", value)
+
Timepoint = property(get_Timepoint, set_Timepoint)
def get_Index(self):
@@ -1242,16 +1339,17 @@ def set_Index(self, value):
Index = property(get_Index, set_Index)
def get_ImageRef(self):
- '''Get the ID of the image of this site'''
- ref = self.node.find(qn(self.ns['spw'], "ImageRef"))
+ """Get the ID of the image of this site"""
+ ref = self.node.find(qn(self.ns["spw"], "ImageRef"))
if ref is None:
return None
return ref.get("ID")
def set_ImageRef(self, value):
- '''Add a reference to the image of this site'''
- ref = self.node.find(qn(self.ns['spw'], "ImageRef"))
+ """Add a reference to the image of this site"""
+ ref = self.node.find(qn(self.ns["spw"], "ImageRef"))
if ref is None:
- ref = ElementTree.SubElement(self.node, qn(self.ns['spw'], "ImageRef"))
+ ref = ElementTree.SubElement(self.node, qn(self.ns["spw"], "ImageRef"))
ref.set("ID", value)
+
ImageRef = property(get_ImageRef, set_ImageRef)
diff --git a/imctools/external/temporarydirectory.py b/imctools/external/temporarydirectory.py
index b97b2e7..4f18e73 100644
--- a/imctools/external/temporarydirectory.py
+++ b/imctools/external/temporarydirectory.py
@@ -5,6 +5,7 @@
from tempfile import mkdtemp
+
class TemporaryDirectory(object):
"""Create and return a temporary directory. This has the same
behavior as mkdtemp but can be used as a context manager. For
@@ -19,7 +20,7 @@ class TemporaryDirectory(object):
def __init__(self, suffix="", prefix="tmp", dir=None):
self._closed = False
- self.name = None # Handle mkdtemp raising an exception
+ self.name = None # Handle mkdtemp raising an exception
self.name = mkdtemp(suffix, prefix, dir)
def __repr__(self):
@@ -38,13 +39,14 @@ def cleanup(self, _warn=False):
# up due to missing globals
if "None" not in str(ex):
raise
- print("ERROR: {!r} while cleaning up {!r}".format(ex, self,),
- file=_sys.stderr)
+ print(
+ "ERROR: {!r} while cleaning up {!r}".format(ex, self,),
+ file=_sys.stderr,
+ )
return
self._closed = True
if _warn:
- self._warn("Implicitly cleaning up {!r}".format(self),
- ResourceWarning)
+ self._warn("Implicitly cleaning up {!r}".format(self), ResourceWarning)
def __exit__(self, exc, value, tb):
self.cleanup()
@@ -85,4 +87,3 @@ def _rmtree(self, path):
self._rmdir(path)
except OSError:
pass
-
diff --git a/imctools/imagej/library.py b/imctools/imagej/library.py
index 76f9413..76d7aa5 100644
--- a/imctools/imagej/library.py
+++ b/imctools/imagej/library.py
@@ -12,10 +12,10 @@
import struct
-from loci.formats import ImageReader , MetadataTools, IFormatWriter, FormatTools
+from loci.formats import ImageReader, MetadataTools, IFormatWriter, FormatTools
import ome.xml.model.enums.DimensionOrder as DimensionOrder
import ome.xml.model.primitives.PositiveInteger as PositiveInteger
-import ome.xml.model.primitives.NonNegativeInteger as NonNegativeInteger
+import ome.xml.model.primitives.NonNegativeInteger as NonNegativeInteger
import ome.xml.model.enums.PixelType as PixelType
from loci.formats import ImageWriter, ImageReader
from loci.plugins import BF
@@ -34,7 +34,7 @@ def convert_imc_to_image(imc_acquisition):
:return: an image5d image
"""
ac_id = imc_acquisition.image_ID
- print('Contstruct image from data: %s' %ac_id)
+ print("Contstruct image from data: %s" % ac_id)
img_channels = imc_acquisition.n_channels
channel_names = imc_acquisition.channel_metals
@@ -43,25 +43,26 @@ def convert_imc_to_image(imc_acquisition):
img_data = imc_acquisition.get_img_stack_cyx()
if channel_labels is not None:
- channel_ids = [lab + '_' + name for name, lab in
- zip(channel_names, channel_labels)]
+ channel_ids = [
+ lab + "_" + name for name, lab in zip(channel_names, channel_labels)
+ ]
else:
channel_ids = channel_names
- print('Add planes to stack:')
+ print("Add planes to stack:")
imgstack = stack_to_imagestack(img_data, channel_ids=channel_ids)
- file_name = imc_acquisition.original_filename.replace('.mcd','')
- file_name = file_name.replace('.txt', '')
+ file_name = imc_acquisition.original_filename.replace(".mcd", "")
+ file_name = file_name.replace(".txt", "")
description = imc_acquisition.image_description
if description is not None:
- file_name = '_'.join((file_name,'a'+ac_id, 'd'+description))
+ file_name = "_".join((file_name, "a" + ac_id, "d" + description))
else:
- file_name = '_'.join((file_name, 'a' + ac_id))
+ file_name = "_".join((file_name, "a" + ac_id))
- i5d_img = get_image5d(file_name, imgstack, channel_ids)
+ i5d_img = get_image5d(file_name, imgstack, channel_ids)
i5d_img.setDefaultColors()
- print('finished image: %s' %ac_id)
+ print("finished image: %s" % ac_id)
return i5d_img
@@ -101,15 +102,16 @@ def get_image5d(imgName, img_stack, channel_names):
nchannels = len(channel_names)
for i, lab in enumerate(channel_names):
- img_stack.setSliceLabel(lab, i+1)
- i5dimg = i5d.Image5D(imgName, img_stack, nchannels,1,1)
+ img_stack.setSliceLabel(lab, i + 1)
+ i5dimg = i5d.Image5D(imgName, img_stack, nchannels, 1, 1)
- for i,cid in enumerate(channel_names):
- i5dimg.getChannelCalibration(i+1).setLabel(str(cid))
+ for i, cid in enumerate(channel_names):
+ i5dimg.getChannelCalibration(i + 1).setLabel(str(cid))
i5dimg.setDefaultColors()
return i5dimg
+
def load_ome_img(file_name):
"""
@@ -128,6 +130,7 @@ def load_ome_img(file_name):
return (imag, omeMeta)
+
def generate_ome_fromimc(imc_acquisition):
"""
@@ -136,21 +139,39 @@ def generate_ome_fromimc(imc_acquisition):
"""
y, x, c = imc_acquisition.shape
- print(x,y,c)
+ print(x, y, c)
metadata = MetadataTools.createOMEXMLMetadata()
- filename= '/home/vitoz/temp/test.ome.tiff'
- MetadataTools.populateMetadata(metadata, 0, filename, True, "XYZTC",
- FormatTools.getPixelTypeString(6), x, y, 1, c, 1, 1)
- if imc_acquisition.origin == 'mcd':
+ filename = "/home/vitoz/temp/test.ome.tiff"
+ MetadataTools.populateMetadata(
+ metadata,
+ 0,
+ filename,
+ True,
+ "XYZTC",
+ FormatTools.getPixelTypeString(6),
+ x,
+ y,
+ 1,
+ c,
+ 1,
+ 1,
+ )
+ if imc_acquisition.origin == "mcd":
ac_id = imc_acquisition.image_ID
meta_xml = et.XML(imc_acquisition.original_metadata)
- ns = '{'+meta_xml.tag.split('}')[0].strip('{')+'}'
-
- channel_xml = [channel_xml for channel_xml in meta_xml.findall(ns + 'AcquisitionChannel')
- if channel_xml.find(ns + 'AcquisitionID').text == ac_id]
-
- ac_xml = [tx for tx in meta_xml.findall(ns + 'Acquisition')
- if tx.find(ns + 'ID').text == ac_id][0]
+ ns = "{" + meta_xml.tag.split("}")[0].strip("{") + "}"
+
+ channel_xml = [
+ channel_xml
+ for channel_xml in meta_xml.findall(ns + "AcquisitionChannel")
+ if channel_xml.find(ns + "AcquisitionID").text == ac_id
+ ]
+
+ ac_xml = [
+ tx
+ for tx in meta_xml.findall(ns + "Acquisition")
+ if tx.find(ns + "ID").text == ac_id
+ ][0]
# AcquisitionDate = ac_xml.find(ns+'StartTimeStamp').text
# Description = ac_xml.find(ns+'Description').text
# AblationPower = ac_xml.find(ns + 'AblationPower').text
@@ -167,8 +188,8 @@ def generate_ome_fromimc(imc_acquisition):
# ValueBytes = ac_xml.find(ns + 'ValueBytes').text
#
# chan_order = [int(cxml.find(ns+'OrderNumber').text) for cxml in channel_xml]
- metadata.setImageID(ac_id,0 )
- metadata.setImageName(ac_id,0)
+ metadata.setImageID(ac_id, 0)
+ metadata.setImageName(ac_id, 0)
metadata.setPixelsDimensionOrder(DimensionOrder.XYCZT, 0)
metadata.setPixelsSizeX(PositiveInteger(x), 0)
metadata.setPixelsSizeY(PositiveInteger(y), 0)
@@ -191,10 +212,10 @@ def generate_ome_fromimc(imc_acquisition):
for i in range(c):
metadata.setChannelSamplesPerPixel(PositiveInteger(1), 0, i)
for cxml in channel_xml:
- cnr = int(cxml.find(ns+'OrderNumber').text)-3
- if cnr >=0:
- name = cxml.find(ns + 'ChannelName').text
- label = cxml.find(ns + 'ChannelLabel')
+ cnr = int(cxml.find(ns + "OrderNumber").text) - 3
+ if cnr >= 0:
+ name = cxml.find(ns + "ChannelName").text
+ label = cxml.find(ns + "ChannelLabel")
if label.text is None:
label = name
else:
@@ -202,9 +223,9 @@ def generate_ome_fromimc(imc_acquisition):
label = label.text
print(label)
print(name)
- cid = '_'.join([label, name])
- cid = cid.strip('(').strip(')')
- name = name.replace('(','').strip(')')
+ cid = "_".join([label, name])
+ cid = cid.strip("(").strip(")")
+ name = name.replace("(", "").strip(")")
metadata.setChannelFluor(name, 0, cnr)
metadata.setChannelName(cid, 0, cnr)
metadata.setChannelID(cid, 0, cnr)
@@ -213,7 +234,6 @@ def generate_ome_fromimc(imc_acquisition):
# metadata.setPlaneTheZ(NonNegativeInteger(0), 0, i)
# metadata.setPlaneTheT(NonNegativeInteger(0), 0, i)
-
return metadata
else:
@@ -241,7 +261,9 @@ def generate_ome_fromimc(imc_acquisition):
print(c)
for i in range(c):
metadata.setChannelSamplesPerPixel(PositiveInteger(1), 0, i)
- for cnr, metal, label in zip(range(c), imc_acquisition.channel_metals, imc_acquisition.channel_labels):
+ for cnr, metal, label in zip(
+ range(c), imc_acquisition.channel_metals, imc_acquisition.channel_labels
+ ):
metadata.setChannelFluor(metal, 0, cnr)
metadata.setChannelName(label, 0, cnr)
metadata.setChannelID(label, 0, cnr)
@@ -259,12 +281,8 @@ def save_ome_tiff(filename, image, metadata):
print(image.getStackSize())
for i in range(nchan):
writer.setSeries(0)
- process = stack.getProcessor(i+1)
+ process = stack.getProcessor(i + 1)
pixels = process.getPixels()
pixels = DataTools.floatsToBytes(pixels, True)
writer.saveBytes(i, pixels)
writer.close()
-
-
-
-
diff --git a/imctools/io/__init__.py b/imctools/io/__init__.py
index 5b8ef56..183637f 100644
--- a/imctools/io/__init__.py
+++ b/imctools/io/__init__.py
@@ -1,7 +1,7 @@
import warnings
-CHANGE_DTYPE_LB_WARNING = 'Data minimum trunkated as outside dtype range'
-CHANGE_DTYPE_UB_WARNING = 'Data max trunkated as outside dtype range'
+CHANGE_DTYPE_LB_WARNING = "Data minimum trunkated as outside dtype range"
+CHANGE_DTYPE_UB_WARNING = "Data max trunkated as outside dtype range"
# Checks if numpy is available in the
# Python implementation
@@ -13,6 +13,7 @@
_is_base = True
if _is_base == False:
+
def change_dtype(array, dtype):
"""
Changes the dtype of an array
@@ -24,7 +25,7 @@ def change_dtype(array, dtype):
:param dtypw: a numpy dtype
:returns: a copy of the array with the correct dtype.
"""
- if dtype.kind in ['i', 'u']:
+ if dtype.kind in ["i", "u"]:
dinf = np.iinfo(dtype)
array = np.around(array)
mina = array.min()
diff --git a/imctools/io/abstractparser.py b/imctools/io/abstractparser.py
index bd60047..012c750 100644
--- a/imctools/io/abstractparser.py
+++ b/imctools/io/abstractparser.py
@@ -6,7 +6,9 @@ class AbstractParser(AbstractParserBase):
def __init__(self):
AbstractParserBase.__init__(self)
- def _reshape_long_2_cyx(self, longdat, is_sorted=True, shape=None, channel_idxs=None):
+ def _reshape_long_2_cyx(
+ self, longdat, is_sorted=True, shape=None, channel_idxs=None
+ ):
"""
:param longdat:
@@ -27,13 +29,12 @@ def _reshape_long_2_cyx(self, longdat, is_sorted=True, shape=None, channel_idxs=
nchan = len(channel_idxs)
tdat = longdat[:, channel_idxs]
if is_sorted:
- img = np.reshape(tdat[:(np.prod(shape)),:], [shape[1], shape[0], nchan], order='C')
- img = img.swapaxes(0,2)
+ img = np.reshape(
+ tdat[: (np.prod(shape)), :], [shape[1], shape[0], nchan], order="C"
+ )
+ img = img.swapaxes(0, 2)
img = img.swapaxes(1, 2)
return img
else:
return NotImplemented
-
-
-
diff --git a/imctools/io/abstractparserbase.py b/imctools/io/abstractparserbase.py
index 7aacc2b..0ea070d 100644
--- a/imctools/io/abstractparserbase.py
+++ b/imctools/io/abstractparserbase.py
@@ -3,6 +3,7 @@
"""
from __future__ import with_statement, division
import array
+import warnings
try:
xrange
@@ -13,18 +14,25 @@
class AcquisitionError(Exception):
"""An error with the acquisition"""
+
class AbstractParserBase(object):
"""
"""
+
def __init__(self):
+ warnings.warn(
+ "imctools 1.x is deprecated, please migrate to version 2.x", DeprecationWarning
+ )
pass
def get_imc_acquisition(self):
pass
@classmethod
- def _reshape_long_2_cyx(self, longdat, is_sorted=True, shape=None, channel_idxs=None):
+ def _reshape_long_2_cyx(
+ self, longdat, is_sorted=True, shape=None, channel_idxs=None
+ ):
"""
Helper method to convert to cxy from the long format.
Mainly used by during import step
@@ -44,7 +52,7 @@ def _reshape_long_2_cyx(self, longdat, is_sorted=True, shape=None, channel_idxs=
shape[1] = int(row[1])
shape[0] += 1
shape[1] += 1
- if shape[0]*shape[1] > len(longdat):
+ if shape[0] * shape[1] > len(longdat):
shape[1] -= 1
if channel_idxs is None:
@@ -54,21 +62,29 @@ def _reshape_long_2_cyx(self, longdat, is_sorted=True, shape=None, channel_idxs=
nchans = len(channel_idxs)
npixels = shape[0] * shape[1]
tot_len = npixels * nchans
- imar = array.array('f')
+ imar = array.array("f")
for i in xrange(tot_len):
row = i % npixels
col = channel_idxs[int(i / npixels)]
imar.append(longdat[row][col])
- img = [[imar[(k * shape[0] * shape[1] + j * shape[0]):(k * shape[0] * shape[1] + j * shape[0] + shape[0])]
- for j in range(shape[1])]
- for k in range(nchans)]
+ img = [
+ [
+ imar[
+ (k * shape[0] * shape[1] + j * shape[0]) : (
+ k * shape[0] * shape[1] + j * shape[0] + shape[0]
+ )
+ ]
+ for j in range(shape[1])
+ ]
+ for k in range(nchans)
+ ]
else:
- img = self._initialize_empty_listarray([shape[1],
- shape[0],
- len(channel_idxs)])
+ img = self._initialize_empty_listarray(
+ [shape[1], shape[0], len(channel_idxs)]
+ )
# will be c, y, x
for row in longdat:
x = int(row[0])
@@ -80,11 +96,20 @@ def _reshape_long_2_cyx(self, longdat, is_sorted=True, shape=None, channel_idxs=
@staticmethod
def _initialize_empty_listarray(shape):
- imar = array.array('f')
- for i in xrange(shape[0] * shape[1] * shape[2]): imar.append(-1.)
-
- img = [[imar[(k * shape[0] * shape[1] + j * shape[0]):(k * shape[0] * shape[1] + j * shape[0] + shape[0])]
- for j in range(shape[1])]
- for k in range(shape[2])]
+ imar = array.array("f")
+ for i in xrange(shape[0] * shape[1] * shape[2]):
+ imar.append(-1.0)
+
+ img = [
+ [
+ imar[
+ (k * shape[0] * shape[1] + j * shape[0]) : (
+ k * shape[0] * shape[1] + j * shape[0] + shape[0]
+ )
+ ]
+ for j in range(shape[1])
+ ]
+ for k in range(shape[2])
+ ]
return img
diff --git a/imctools/io/imcacquisition.py b/imctools/io/imcacquisition.py
index 51c1d07..8ae8f8a 100644
--- a/imctools/io/imcacquisition.py
+++ b/imctools/io/imcacquisition.py
@@ -14,14 +14,34 @@ class ImcAcquisition(ImcAcquisitionBase):
"""
- def __init__(self, image_ID, original_file, data, channel_metal, channel_labels,
- original_metadata=None, image_description=None, origin=None, offset=0):
+ def __init__(
+ self,
+ image_ID,
+ original_file,
+ data,
+ channel_metal,
+ channel_labels,
+ original_metadata=None,
+ image_description=None,
+ origin=None,
+ offset=0,
+ ):
"""
:param filename:
"""
- ImcAcquisitionBase.__init__(self, image_ID, original_file, data, channel_metal, channel_labels,
- original_metadata, image_description, origin, offset=offset)
+ ImcAcquisitionBase.__init__(
+ self,
+ image_ID,
+ original_file,
+ data,
+ channel_metal,
+ channel_labels,
+ original_metadata,
+ image_description,
+ origin,
+ offset=offset,
+ )
def save_image(self, filename, metals=None, mass=None):
tw = self.get_image_writer(filename, metals=metals, mass=mass)
@@ -46,33 +66,42 @@ def get_image_writer(self, filename, metals=None, mass=None):
out_names = [self.channel_labels[i] for i in order]
out_fluor = [self.channel_metals[i] for i in order]
dat = np.array(self.get_img_stack_cyx(order), dtype=np.float32).swapaxes(2, 0)
- tw = TiffWriter(filename, dat, channel_name=out_names, original_description=self.original_metadata, fluor=out_fluor)
+ tw = TiffWriter(
+ filename,
+ dat,
+ channel_name=out_names,
+ original_description=self.original_metadata,
+ fluor=out_fluor,
+ )
return tw
def save_analysis_tiff(self, filename, metals=None):
pass
-if __name__ == '__main__':
+
+if __name__ == "__main__":
import matplotlib.pyplot as plt
from imctools.io.mcdparser import McdParser
from imctools.io.ometiffparser import OmetiffParser
- fn = '/home/vitoz/temp/20170508_p52-54_s19_ac1_a12.ome.tiff'
- #with OmetiffParser(fn) as testmcd:
+
+ fn = "/home/vitoz/temp/20170508_p52-54_s19_ac1_a12.ome.tiff"
+ # with OmetiffParser(fn) as testmcd:
testmcd = OmetiffParser(fn)
- #print(testmcd.filename)
- #print(testmcd.n_acquisitions)
- #print(testmcd.get_acquisition_xml('0'))
- #print(testmcd.get_acquisition_channels_xml('0'))
- #print(testmcd.get_acquisition_channels('0'))
+ # print(testmcd.filename)
+ # print(testmcd.n_acquisitions)
+ # print(testmcd.get_acquisition_xml('0'))
+ # print(testmcd.get_acquisition_channels_xml('0'))
+ # print(testmcd.get_acquisition_channels('0'))
imc_img = testmcd.get_imc_acquisition()
print(imc_img.n_channels)
- print(imc_img.get_mass_indices(['191', '193']))
+ print(imc_img.get_mass_indices(["191", "193"]))
# img = imc_img.get_img_by_metal('X')
# plt.figure()OmetiffParser(fn)
# plt.imshow(np.array(img).squeeze())
# plt.show()
-
print(imc_img.channel_metals)
- iw = imc_img.get_image_writer('/home/vitoz/temp/test_iridium.ome.tiff', mass=['191', '193'])
- iw.save_image(mode='ome')
+ iw = imc_img.get_image_writer(
+ "/home/vitoz/temp/test_iridium.ome.tiff", mass=["191", "193"]
+ )
+ iw.save_image(mode="ome")
diff --git a/imctools/io/imcacquisitionbase.py b/imctools/io/imcacquisitionbase.py
index 241354f..8826f9a 100644
--- a/imctools/io/imcacquisitionbase.py
+++ b/imctools/io/imcacquisitionbase.py
@@ -1,4 +1,5 @@
from __future__ import with_statement, division
+
try:
xrange
except NameError:
@@ -13,13 +14,25 @@
import array
import string
+
class ImcAcquisitionBase(object):
"""
An Image Acquisition Object representing a single acquisition
"""
- def __init__(self, image_ID, original_file, data, channel_metal, channel_labels,
- original_metadata=None, image_description=None, origin=None, offset=0):
+
+ def __init__(
+ self,
+ image_ID,
+ original_file,
+ data,
+ channel_metal,
+ channel_labels,
+ original_metadata=None,
+ image_description=None,
+ origin=None,
+ offset=0,
+ ):
"""
:param image_ID: The acquisition ID
@@ -50,14 +63,13 @@ def __init__(self, image_ID, original_file, data, channel_metal, channel_labels,
self.image_description = image_description
self.origin = origin
-
@property
def original_filename(self):
return os.path.split(self.original_file)[1]
@property
def n_channels(self):
- return len(self._data)-self._offset
+ return len(self._data) - self._offset
@property
def shape(self):
@@ -65,16 +77,19 @@ def shape(self):
@property
def channel_metals(self):
- return self._channel_metals[self._offset:]
+ return self._channel_metals[self._offset :]
@property
def channel_mass(self):
- return [''.join([m for m in metal if m.isdigit()]) for metal in self._channel_metals[self._offset:]]
+ return [
+ "".join([m for m in metal if m.isdigit()])
+ for metal in self._channel_metals[self._offset :]
+ ]
@property
def channel_labels(self):
if self._channel_labels is not None:
- return self._channel_labels[self._offset:]
+ return self._channel_labels[self._offset :]
else:
return None
@@ -120,11 +135,10 @@ def get_img_stack_cyx(self, channel_idxs=None, offset=None):
data = self._data
- img = [data[i+offset] for i in channel_idxs]
+ img = [data[i + offset] for i in channel_idxs]
return img
-
def get_img_by_channel_nr(self, chan):
"""
@@ -155,41 +169,45 @@ def validate_channels(self, channel):
for i in range(self._offset):
if i < 3:
- channel = ['X', 'Y', 'Z'][i] + channel
+ channel = ["X", "Y", "Z"][i] + channel
else:
channel = [str(i)] + channel
elif len(channel) == self.n_channels + self._offset:
pass
else:
- raise ValueError('Incompatible channel names/labels!')
+ raise ValueError("Incompatible channel names/labels!")
# remove special characters
- channel = [c.replace('(','').replace(')','').strip() if c is not None else '' for c in channel]
+ channel = [
+ c.replace("(", "").replace(")", "").strip() if c is not None else ""
+ for c in channel
+ ]
return channel
-
@staticmethod
def _get_position(name, namelist):
- pos = [i for i, chan in enumerate(namelist) if chan ==name]
+ pos = [i for i, chan in enumerate(namelist) if chan == name]
return pos[0]
-if __name__ == '__main__':
+
+if __name__ == "__main__":
from mcdparserbase import McdParserBase
import time
- fn = '/mnt/imls-bod/data_vito/grade1.mcd'
+
+ fn = "/mnt/imls-bod/data_vito/grade1.mcd"
with McdParserBase(fn) as testmcd:
print(testmcd.filename)
print(testmcd.n_acquisitions)
# print(testmcd.get_acquisition_xml('0'))
- print(testmcd.get_acquisition_channels_xml('0'))
- print(testmcd.get_acquisition_channels('0'))
- print(len(testmcd.get_acquisition_rawdata('0')))
+ print(testmcd.get_acquisition_channels_xml("0"))
+ print(testmcd.get_acquisition_channels("0"))
+ print(len(testmcd.get_acquisition_rawdata("0")))
start = time.time()
- imc_ac = testmcd.get_imc_acquisition('0')
+ imc_ac = testmcd.get_imc_acquisition("0")
end = time.time()
print(end - start)
print(imc_ac.shape)
- #imc_img.save_image('/mnt/imls-bod/data_vito/test1.tiff')
+ # imc_img.save_image('/mnt/imls-bod/data_vito/test1.tiff')
# acquisition_dict = get_mcd_data(fn, xml_public)
diff --git a/imctools/io/imcfolderwriter.py b/imctools/io/imcfolderwriter.py
index 6a5b1a0..b9669c0 100644
--- a/imctools/io/imcfolderwriter.py
+++ b/imctools/io/imcfolderwriter.py
@@ -5,8 +5,10 @@
logger = logging.getLogger(__name__)
+
class ImcFolderWriter(object):
""" A class to write an imc folder """
+
def __init__(self, out_folder, mcddata=None, imcacquisitions=None, mcdmeta=None):
"""
Initializes an ImcFolderWriter that can be used to write out an imcfolder
@@ -30,7 +32,7 @@ def __init__(self, out_folder, mcddata=None, imcacquisitions=None, mcdmeta=None)
self.add_mcddata(mcddata, add_acquisitions=add_ac)
if self.meta is None:
- raise ValueError('At least mcdata or mcdmeta need to be specified!')
+ raise ValueError("At least mcdata or mcdmeta need to be specified!")
@property
def foldername(self):
@@ -55,7 +57,7 @@ def write_imc_folder(self, zipfolder=True, remove_folder=None):
base_folder = self.out_folder
foldername = self.foldername
out_folder = os.path.join(self.out_folder, self.foldername)
- if not(os.path.exists(out_folder)):
+ if not (os.path.exists(out_folder)):
os.makedirs(out_folder)
for ac in self.acquisitions:
@@ -79,14 +81,17 @@ def write_imc_folder(self, zipfolder=True, remove_folder=None):
self.mcd.save_acquisition_bfimage_before(aid, out_folder)
if zipfolder:
- with zipfile.ZipFile(os.path.join(base_folder, foldername +'_imc.zip'),
- 'w', compression=zipfile.ZIP_DEFLATED,
- allowZip64=True) as imczip:
+ with zipfile.ZipFile(
+ os.path.join(base_folder, foldername + "_imc.zip"),
+ "w",
+ compression=zipfile.ZIP_DEFLATED,
+ allowZip64=True,
+ ) as imczip:
for root, d, files in os.walk(out_folder):
for fn in files:
- imczip.write(os.path.join(root,fn),fn)
+ imczip.write(os.path.join(root, fn), fn)
if remove_folder:
- os.remove(os.path.join(root,fn))
+ os.remove(os.path.join(root, fn))
if remove_folder:
os.removedirs(out_folder)
@@ -95,29 +100,29 @@ def _write_acquisition(self, ac, out_folder):
if 0 in ac.shape:
logger.error(f"Cannot write acquisition with the shape: {ac.shape}")
return
- file_end = '_ac.ome.tiff'
+ file_end = "_ac.ome.tiff"
if ac.image_description is None:
ac_id = ac.image_ID
fn = self.meta.get_object(mcdmeta.ACQUISITION, ac_id).metaname
else:
fn = ac.image_description
- img_writer = ac.get_image_writer(os.path.join(out_folder,
- fn+file_end))
- img_writer.save_image(mode='ome')
-
+ img_writer = ac.get_image_writer(os.path.join(out_folder, fn + file_end))
+ img_writer.save_image(mode="ome")
def _find_ac_metaname_from_txt_fn(self, ac):
raise NotImplementedError
-if __name__ == '__main__':
+
+if __name__ == "__main__":
import imctools.io.mcdparser as mcdp
- #fn_mcd = '/home/vitoz/temp/txtvsmcd/20170805_p60-63_slide6_ac1_vz.mcd'
- #fn_mcd = '/mnt/imls-bod/VitoZ/Spheres/20161130_p25_slide2_ac1/20161130_p25_slide2_ac1.mcd'
- #fn_mcd='/mnt/imls-bod/VitoZ/Spheres/20161005_IS2362_4_site1_ac1/20161005_IS2362_4_site1_ac1.mcd'
+
+ # fn_mcd = '/home/vitoz/temp/txtvsmcd/20170805_p60-63_slide6_ac1_vz.mcd'
+ # fn_mcd = '/mnt/imls-bod/VitoZ/Spheres/20161130_p25_slide2_ac1/20161130_p25_slide2_ac1.mcd'
+ # fn_mcd='/mnt/imls-bod/VitoZ/Spheres/20161005_IS2362_4_site1_ac1/20161005_IS2362_4_site1_ac1.mcd'
# an example of not functional mcd but working txt
# fn_mcd = /mnt/imls-bod/DanielS/ACD/IMC\ 2.06/Her2_grade3
- fn_mcd ='/mnt/imls-bod/VitoZ/Spheres/20161018_OCT1_slide4_ac1/20161018_OCT1_slide4_ac1.mcd'
+ fn_mcd = "/mnt/imls-bod/VitoZ/Spheres/20161018_OCT1_slide4_ac1/20161018_OCT1_slide4_ac1.mcd"
mcd = mcdp.McdParser(fn_mcd)
- mcd.save_meta_xml('/home/vitoz/temp/')
- ifw = ImcFolderWriter('/home/vitoz/temp/', mcddata=mcd)
+ mcd.save_meta_xml("/home/vitoz/temp/")
+ ifw = ImcFolderWriter("/home/vitoz/temp/", mcddata=mcd)
ifw.write_imc_folder()
diff --git a/imctools/io/mcdparser.py b/imctools/io/mcdparser.py
index 3eb2c9a..e8a7b5b 100644
--- a/imctools/io/mcdparser.py
+++ b/imctools/io/mcdparser.py
@@ -1,3 +1,5 @@
+import warnings
+
import numpy as np
import mmap
import xml.etree.ElementTree as et
@@ -21,6 +23,7 @@ class McdParser(AbstractParser, McdParserBase):
:param object:
:return:
"""
+
def __init__(self, filename, filehandle=None, metafilename=None):
"""
Initializes the MCDparser object
@@ -35,7 +38,7 @@ def get_acquisition_rawdata(self, ac_id):
"""
Gets the unreshaped image data from the acquisition.
:param ac_id: the acquisition id
- :returns: the acquisition rawdata
+ :returns: the acquisition rawdata
"""
ac = self.meta.get_acquisitions()[ac_id]
data_offset_start = ac.data_offset_start
@@ -45,14 +48,18 @@ def get_acquisition_rawdata(self, ac_id):
n_channel = ac.n_channels
if n_rows == 0:
- raise AcquisitionError('Acquisition ' + ac_id + ' emtpy!')
-
- data = np.memmap(self._fh, dtype='>> McdParserBase._add_nullbytes('abc')
'a\\x00b\\x00c\\x00'
"""
- pad_str = ''
+ pad_str = ""
for s in buffer_str:
- pad_str += s + '\x00'
+ pad_str += s + "\x00"
return pad_str
@staticmethod
@@ -381,10 +388,10 @@ def _reverse_find_in_buffer(f, s, buffer_size=4096):
buf = None
overlap = len(s) - 1
- bsize = buffer_size +overlap+1
- cur_pos = f.tell() - bsize+1
- offset = (-2*bsize+overlap)
- first_start=True
+ bsize = buffer_size + overlap + 1
+ cur_pos = f.tell() - bsize + 1
+ offset = -2 * bsize + overlap
+ first_start = True
while cur_pos >= 0:
f.seek(cur_pos)
buf = f.read(bsize)
@@ -393,8 +400,8 @@ def _reverse_find_in_buffer(f, s, buffer_size=4096):
if pos >= 0:
return f.tell() - (len(buf) - pos)
- cur_pos = f.tell() +offset
+ cur_pos = f.tell() + offset
if (cur_pos < 0) and first_start:
- first_start=False
- cur_pos=0
+ first_start = False
+ cur_pos = 0
return -1
diff --git a/imctools/io/mcdparsercpp.py b/imctools/io/mcdparsercpp.py
index 0c14479..0c382b7 100644
--- a/imctools/io/mcdparsercpp.py
+++ b/imctools/io/mcdparsercpp.py
@@ -8,6 +8,7 @@
from imctools.io.imcacquisition import ImcAcquisition
from imctools.io.abstractparser import AbstractParser
+
class McdParserCpp(McdParser):
"""
An mcdparser that uses the bindings to the
@@ -30,17 +31,19 @@ def retrieve_mcd_xml(self):
meta = self._cppmcd.readMetadata()
self._cppmeta = meta
self._xml = et.fromstring(meta.schemaXML)
- self._ns = '{'+self._xml.tag.split('}')[0].strip('{')+'}'
+ self._ns = "{" + self._xml.tag.split("}")[0].strip("{") + "}"
@property
def filename(self):
return self._filename
def get_acquisition_buffer(self):
- raise NotImplementedError('Returning buffer not implemented for this parser')
+ raise NotImplementedError("Returning buffer not implemented for this parser")
def get_acquisition_rawdata(self, ac_id):
- ac = [ac for ac in self._cppmeta.acquisitions if ac.properties['ID'] == ac_id][0]
+ ac = [ac for ac in self._cppmeta.acquisitions if ac.properties["ID"] == ac_id][
+ 0
+ ]
acdat = self._cppmcd.readAcquisitionData(ac)
dat = np.vstack([c.data for c in acdat.channelData]).T
return dat
diff --git a/imctools/io/mcdxmlparser.py b/imctools/io/mcdxmlparser.py
index a9076ed..d20d8b7 100644
--- a/imctools/io/mcdxmlparser.py
+++ b/imctools/io/mcdxmlparser.py
@@ -9,76 +9,76 @@
"""
# Definition of all the vocabulary used
-ABLATIONDISTANCEBETWEENSHOTSX = 'AblationDistanceBetweenShotsX'
-ABLATIONDISTANCEBETWEENSHOTSY = 'AblationDistanceBetweenShotsY'
-ABLATIONFREQUENCY = 'AblationFrequency'
-ABLATIONPOWER = 'AblationPower'
-ACQUISITION = 'Acquisition'
-ACQUISITIONCHANNEL = 'AcquisitionChannel'
-ACQUISITIONID = 'AcquisitionID'
-ACQUISITIONROI = 'AcquisitionROI'
-ACQUISITIONROIID = 'AcquisitionROIID'
-AFTERABLATIONIMAGEENDOFFSET = 'AfterAblationImageEndOffset'
-AFTERABLATIONIMAGESTARTOFFSET = 'AfterAblationImageStartOffset'
-BEFOREABLATIONIMAGEENDOFFSET = 'BeforeAblationImageEndOffset'
-BEFOREABLATIONIMAGESTARTOFFSET = 'BeforeAblationImageStartOffset'
-CHANNELLABEL = 'ChannelLabel'
-CHANNELNAME = 'ChannelName'
-DATAENDOFFSET = 'DataEndOffset'
-DATASTARTOFFSET = 'DataStartOffset'
-DESCRIPTION = 'Description'
-DUALCOUNTSTART = 'DualCountStart'
-ENDTIMESTAMP = 'EndTimeStamp'
-FILENAME = 'Filename'
-HEIGHTUM = 'HeightUm'
-ID = 'ID'
-IMAGEENDOFFSET = 'ImageEndOffset'
-IMAGEFILE = 'ImageFile'
-IMAGEFORMAT = 'ImageFormat'
-IMAGESTARTOFFSET = 'ImageStartOffset'
-MCDSCHEMA = 'MCDSchema'
-MAXX = 'MaxX'
-MAXY = 'MaxY'
-MOVEMENTTYPE = 'MovementType'
-ORDERNUMBER = 'OrderNumber'
-PANORAMA = 'Panorama'
-PANORAMAID = 'PanoramaID'
-PANORAMAPIXELXPOS = 'PanoramaPixelXPos'
-PANORAMAPIXELYPOS = 'PanoramaPixelYPos'
-PIXELHEIGHT = 'PixelHeight'
-PIXELSCALECOEF = 'PixelScaleCoef'
-PIXELWIDTH = 'PixelWidth'
-PLUMEEND = 'PlumeEnd'
-PLUMESTART = 'PlumeStart'
-ROIENDXPOSUM = 'ROIEndXPosUm'
-ROIENDYPOSUM = 'ROIEndYPosUm'
-ROIPOINT = 'ROIPoint'
-ROISTARTXPOSUM = 'ROIStartXPosUm'
-ROISTARTYPOSUM = 'ROIStartYPosUm'
-ROITYPE = 'ROIType'
-SEGMENTDATAFORMAT = 'SegmentDataFormat'
-SIGNALTYPE = 'SignalType'
-SLIDE = 'Slide'
-SLIDEID = 'SlideID'
-SLIDETYPE = 'SlideType'
-SLIDEX1POSUM = 'SlideX1PosUm'
-SLIDEX2POSUM = 'SlideX2PosUm'
-SLIDEX3POSUM = 'SlideX3PosUm'
-SLIDEX4POSUM = 'SlideX4PosUm'
-SLIDEXPOSUM = 'SlideXPosUm'
-SLIDEY1POSUM = 'SlideY1PosUm'
-SLIDEY2POSUM = 'SlideY2PosUm'
-SLIDEY3POSUM = 'SlideY3PosUm'
-SLIDEY4POSUM = 'SlideY4PosUm'
-SLIDEYPOSUM = 'SlideYPosUm'
-STARTTIMESTAMP = 'StartTimeStamp'
-TEMPLATE = 'Template'
-UID = 'UID'
-VALUEBYTES = 'ValueBytes'
-WIDTHUM = 'WidthUm'
-
-PARSER = 'parser'
-META_CSV = '_meta.csv'
+ABLATIONDISTANCEBETWEENSHOTSX = "AblationDistanceBetweenShotsX"
+ABLATIONDISTANCEBETWEENSHOTSY = "AblationDistanceBetweenShotsY"
+ABLATIONFREQUENCY = "AblationFrequency"
+ABLATIONPOWER = "AblationPower"
+ACQUISITION = "Acquisition"
+ACQUISITIONCHANNEL = "AcquisitionChannel"
+ACQUISITIONID = "AcquisitionID"
+ACQUISITIONROI = "AcquisitionROI"
+ACQUISITIONROIID = "AcquisitionROIID"
+AFTERABLATIONIMAGEENDOFFSET = "AfterAblationImageEndOffset"
+AFTERABLATIONIMAGESTARTOFFSET = "AfterAblationImageStartOffset"
+BEFOREABLATIONIMAGEENDOFFSET = "BeforeAblationImageEndOffset"
+BEFOREABLATIONIMAGESTARTOFFSET = "BeforeAblationImageStartOffset"
+CHANNELLABEL = "ChannelLabel"
+CHANNELNAME = "ChannelName"
+DATAENDOFFSET = "DataEndOffset"
+DATASTARTOFFSET = "DataStartOffset"
+DESCRIPTION = "Description"
+DUALCOUNTSTART = "DualCountStart"
+ENDTIMESTAMP = "EndTimeStamp"
+FILENAME = "Filename"
+HEIGHTUM = "HeightUm"
+ID = "ID"
+IMAGEENDOFFSET = "ImageEndOffset"
+IMAGEFILE = "ImageFile"
+IMAGEFORMAT = "ImageFormat"
+IMAGESTARTOFFSET = "ImageStartOffset"
+MCDSCHEMA = "MCDSchema"
+MAXX = "MaxX"
+MAXY = "MaxY"
+MOVEMENTTYPE = "MovementType"
+ORDERNUMBER = "OrderNumber"
+PANORAMA = "Panorama"
+PANORAMAID = "PanoramaID"
+PANORAMAPIXELXPOS = "PanoramaPixelXPos"
+PANORAMAPIXELYPOS = "PanoramaPixelYPos"
+PIXELHEIGHT = "PixelHeight"
+PIXELSCALECOEF = "PixelScaleCoef"
+PIXELWIDTH = "PixelWidth"
+PLUMEEND = "PlumeEnd"
+PLUMESTART = "PlumeStart"
+ROIENDXPOSUM = "ROIEndXPosUm"
+ROIENDYPOSUM = "ROIEndYPosUm"
+ROIPOINT = "ROIPoint"
+ROISTARTXPOSUM = "ROIStartXPosUm"
+ROISTARTYPOSUM = "ROIStartYPosUm"
+ROITYPE = "ROIType"
+SEGMENTDATAFORMAT = "SegmentDataFormat"
+SIGNALTYPE = "SignalType"
+SLIDE = "Slide"
+SLIDEID = "SlideID"
+SLIDETYPE = "SlideType"
+SLIDEX1POSUM = "SlideX1PosUm"
+SLIDEX2POSUM = "SlideX2PosUm"
+SLIDEX3POSUM = "SlideX3PosUm"
+SLIDEX4POSUM = "SlideX4PosUm"
+SLIDEXPOSUM = "SlideXPosUm"
+SLIDEY1POSUM = "SlideY1PosUm"
+SLIDEY2POSUM = "SlideY2PosUm"
+SLIDEY3POSUM = "SlideY3PosUm"
+SLIDEY4POSUM = "SlideY4PosUm"
+SLIDEYPOSUM = "SlideYPosUm"
+STARTTIMESTAMP = "StartTimeStamp"
+TEMPLATE = "Template"
+UID = "UID"
+VALUEBYTES = "ValueBytes"
+WIDTHUM = "WidthUm"
+
+PARSER = "parser"
+META_CSV = "_meta.csv"
"""
Definition of all the meta objects
Each entity will have a class corresponding to it, with helpermethods
@@ -89,10 +89,13 @@
Further each object is registered in the global root node, making them easy accessible.
"""
+
+
class Meta(object):
"""
Represents an abstract metadata object.
"""
+
def __init__(self, mtype, meta, parents, symbol=None):
"""
Initializes the metadata object, generates the
@@ -124,7 +127,7 @@ def __init__(self, mtype, meta, parents, symbol=None):
@property
def is_root(self):
- return len(self.parents) == 0
+ return len(self.parents) == 0
def _update_parents(self, p):
self._update_dict(p.childs)
@@ -150,24 +153,28 @@ def get_root(self):
@property
def metaname(self):
pname = self.parents[0].metaname
- return '_'.join([pname, self.symbol+self.id])
+ return "_".join([pname, self.symbol + self.id])
+
# Definition of the subclasses
class Slide(Meta):
def __init__(self, meta, parents):
- Meta.__init__(self, SLIDE, meta, parents, 's')
+ Meta.__init__(self, SLIDE, meta, parents, "s")
+
class Panorama(Meta):
def __init__(self, meta, parents):
- Meta.__init__(self, PANORAMA, meta, parents, 'p')
+ Meta.__init__(self, PANORAMA, meta, parents, "p")
+
class AcquisitionRoi(Meta):
def __init__(self, meta, parents):
- Meta.__init__(self, ACQUISITIONROI, meta, parents, 'r')
+ Meta.__init__(self, ACQUISITIONROI, meta, parents, "r")
+
class Acquisition(Meta):
def __init__(self, meta, parents):
- Meta.__init__(self, ACQUISITION, meta, parents, 'a')
+ Meta.__init__(self, ACQUISITION, meta, parents, "a")
def get_channels(self):
return self.childs[ACQUISITIONCHANNEL]
@@ -192,11 +199,13 @@ def data_offset_end(self):
@property
def data_size(self):
- return self.data_offset_end - self.data_offset_start +1
+ return self.data_offset_end - self.data_offset_start + 1
@property
def data_nrows(self):
- nrow = int(self.data_size/(self.n_channels * int(self.properties[VALUEBYTES])))
+ nrow = int(
+ self.data_size / (self.n_channels * int(self.properties[VALUEBYTES]))
+ )
return nrow
@property
@@ -206,24 +215,27 @@ def n_channels(self):
class RoiPoint(Meta):
def __init__(self, meta, parents):
- Meta.__init__(self, ROIPOINT, meta, parents, 'rp')
+ Meta.__init__(self, ROIPOINT, meta, parents, "rp")
+
class Channel(Meta):
def __init__(self, meta, parents):
- Meta.__init__(self, ACQUISITIONCHANNEL, meta, parents, 'c')
+ Meta.__init__(self, ACQUISITIONCHANNEL, meta, parents, "c")
# A dictionary to map metadata keys to metadata types
# The order reflects the dependency structure of them and the
# order these objects should be initialized
-OBJ_DICT = OrderedDict([
- (SLIDE, Slide),
- (PANORAMA, Panorama),
- (ACQUISITIONROI, AcquisitionRoi),
- (ACQUISITION, Acquisition),
- (ROIPOINT, RoiPoint),
- (ACQUISITIONCHANNEL, Channel)
-])
+OBJ_DICT = OrderedDict(
+ [
+ (SLIDE, Slide),
+ (PANORAMA, Panorama),
+ (ACQUISITIONROI, AcquisitionRoi),
+ (ACQUISITION, Acquisition),
+ (ROIPOINT, RoiPoint),
+ (ACQUISITIONCHANNEL, Channel),
+ ]
+)
# A dictionary to map id keys to metadata keys
# Used for initializaiton of the objects
@@ -231,13 +243,15 @@ def __init__(self, meta, parents):
SLIDEID: SLIDE,
PANORAMAID: PANORAMA,
ACQUISITIONROIID: ACQUISITIONROI,
- ACQUISITIONID: ACQUISITION
+ ACQUISITIONID: ACQUISITION,
}
+
class McdXmlParser(Meta):
"""
Represents the full mcd xml
"""
+
def __init__(self, xml, filename=None):
self._rawxml = xml
meta = libb.etree_to_dict(xml)
@@ -252,12 +266,11 @@ def __init__(self, xml, filename=None):
@property
def metaname(self):
mcd_fn = self.filename
- mcd_fn = mcd_fn.replace('\\', '/')
- mcd_fn = os.path.split(mcd_fn)[1].rstrip('_schema.xml')
+ mcd_fn = mcd_fn.replace("\\", "/")
+ mcd_fn = os.path.split(mcd_fn)[1].rstrip("_schema.xml")
mcd_fn = os.path.splitext(mcd_fn)[0]
return mcd_fn
-
def _init_objects(self):
obj_keys = [k for k in OBJ_DICT.keys() if k in self.properties.keys()]
for k in obj_keys:
@@ -270,7 +283,6 @@ def _init_objects(self):
parents = [self]
ObjClass(o, parents)
-
def get_objects_by_id(self, idname, objid):
"""
Gets objects by idname and id
@@ -304,9 +316,10 @@ def _get_meta_objects(self, mtype):
def save_meta_xml(self, out_folder):
xml = self._rawxml
- fn = self.metaname + '_schema.xml'
+ fn = self.metaname + "_schema.xml"
et.ElementTree.ElementTree(xml).write(
- os.path.join(out_folder,fn), encoding='utf-8')
+ os.path.join(out_folder, fn), encoding="utf-8"
+ )
def save_meta_csv(self, out_folder):
"""
@@ -315,8 +328,8 @@ def save_meta_csv(self, out_folder):
"""
for n, o in self.objects.items():
odict = [i.properties for k, i in o.items()]
- fn = '_'.join([self.metaname, n]) + META_CSV
- with open(os.path.join(out_folder, fn), 'w') as csvfile:
+ fn = "_".join([self.metaname, n]) + META_CSV
+ with open(os.path.join(out_folder, fn), "w") as csvfile:
cols = odict[0].keys()
writer = csv.DictWriter(csvfile, sorted(cols))
writer.writeheader()
@@ -341,7 +354,6 @@ def get_acquisition_meta(self, acid):
"""
return self.get_object(ACQUISITION, acid).properties
-
def get_acquisition_rois(self):
"""
gets a list of all acuisitionROIs
@@ -359,4 +371,3 @@ def get_roipoints(self):
get a list of all roipoints
"""
raise NotImplementedError
-
diff --git a/imctools/io/omeparserbase.py b/imctools/io/omeparserbase.py
index 60cdb5b..5ef5ddf 100644
--- a/imctools/io/omeparserbase.py
+++ b/imctools/io/omeparserbase.py
@@ -2,6 +2,7 @@
from imctools.io.abstractparserbase import AbstractParserBase
import xml.etree.ElementTree as et
+
class OmeParserBase(AbstractParserBase):
def __init__(self, data, ome, original_file=None, origin=None):
"""
@@ -10,9 +11,9 @@ def __init__(self, data, ome, original_file=None, origin=None):
"""
super(OmeParserBase, self).__init__()
if origin is None:
- origin = 'ome'
+ origin = "ome"
self.ome = et.fromstring(ome)
- self.ns = '{' + self.ome.tag.split('}')[0].strip('{') + '}'
+ self.ns = "{" + self.ome.tag.split("}")[0].strip("{") + "}"
self.data = data
self.get_meta_dict()
self.original_file = original_file
@@ -20,29 +21,41 @@ def __init__(self, data, ome, original_file=None, origin=None):
def get_imc_acquisition(self):
meta = self.meta_dict
- return ImcAcquisitionBase(meta['image_ID'],
- self.original_file,
- self.data,
- meta['channel_metals'],
- meta['channel_labels'],
- original_metadata=self.ome,
- image_description=None,
- origin=self.origin, offset=0)
+ return ImcAcquisitionBase(
+ meta["image_ID"],
+ self.original_file,
+ self.data,
+ meta["channel_metals"],
+ meta["channel_labels"],
+ original_metadata=self.ome,
+ image_description=None,
+ origin=self.origin,
+ offset=0,
+ )
def get_meta_dict(self):
meta_dict = dict()
xml = self.ome
ns = self.ns
- img = xml.find(ns+'Image')
- pixels = img.find(ns+'Pixels')
- channels = pixels.findall(ns+'Channel')
+ img = xml.find(ns + "Image")
+ pixels = img.find(ns + "Pixels")
+ channels = pixels.findall(ns + "Channel")
nchan = len(channels)
- chan_dict={int(chan.attrib['ID'].split(':')[2]) :
- (chan.attrib['Name'], chan.attrib['Fluor']) for chan in channels}
+ chan_dict = {
+ int(chan.attrib["ID"].split(":")[2]): (
+ chan.attrib["Name"],
+ chan.attrib["Fluor"],
+ )
+ for chan in channels
+ }
- meta_dict.update({'image_ID': img.attrib['Name'],
- 'channel_metals': [chan_dict[i][1] for i in range(nchan)],
- 'channel_labels': [chan_dict[i][0] for i in range(nchan)]})
+ meta_dict.update(
+ {
+ "image_ID": img.attrib["Name"],
+ "channel_metals": [chan_dict[i][1] for i in range(nchan)],
+ "channel_labels": [chan_dict[i][0] for i in range(nchan)],
+ }
+ )
self.meta_dict = meta_dict
diff --git a/imctools/io/ometiffparser.py b/imctools/io/ometiffparser.py
index 76d8348..9b35ef3 100644
--- a/imctools/io/ometiffparser.py
+++ b/imctools/io/ometiffparser.py
@@ -5,6 +5,7 @@
import xml.etree.ElementTree as et
from imctools.io.abstractparser import AbstractParser
+
class OmetiffParser(AbstractParser, OmeParserBase):
"""
Parses an ome tiff
@@ -16,13 +17,13 @@ def __init__(self, original_file):
:param filename:
"""
- #self._data = None
- #self._ome = None
+ # self._data = None
+ # self._ome = None
AbstractParser.__init__(self)
self.read_image(original_file)
self.filename = original_file
self.n_acquisitions = 1
- OmeParserBase.__init__(self, self.data, self.ome, origin='ome.tiff')
+ OmeParserBase.__init__(self, self.data, self.ome, origin="ome.tiff")
def get_imc_acquisition(self):
"""
@@ -31,28 +32,29 @@ def get_imc_acquisition(self):
:return:
"""
meta = self.meta_dict
- return ImcAcquisition(meta['image_ID'], self.original_file,
- self.data,
- meta['channel_metals'],
- meta['channel_labels'],
- original_metadata=self.ome ,
- image_description=None,
- origin=self.origin,
- offset=0)
+ return ImcAcquisition(
+ meta["image_ID"],
+ self.original_file,
+ self.data,
+ meta["channel_metals"],
+ meta["channel_labels"],
+ original_metadata=self.ome,
+ image_description=None,
+ origin=self.origin,
+ offset=0,
+ )
def read_image(self, filename):
with tifffile.TiffFile(filename) as tif:
try:
- self.data = tif.asarray(out='memmap')
+ self.data = tif.asarray(out="memmap")
except:
# this is in an older tifffile version is used
self.data = tif.asarray()
try:
- self.ome = tif.pages[0].tags['ImageDescription'].value
+ self.ome = tif.pages[0].tags["ImageDescription"].value
except:
- self.ome = tif.pages[0].tags['image_description'].value
-
-
+ self.ome = tif.pages[0].tags["image_description"].value
# @staticmethod
# def reshape_flat(data):
@@ -71,11 +73,13 @@ def read_image(self, filename):
# data))
# return data
-if __name__ == '__main__':
- fn = '/home/vitoz/temp/HIER_healthy_4_3_HIER5_4.ome.tiff'
+
+if __name__ == "__main__":
+ fn = "/home/vitoz/temp/HIER_healthy_4_3_HIER5_4.ome.tiff"
parser = OmetiffParser(fn)
imc_ac = parser.get_imc_acquisition()
import matplotlib.pyplot as plt
+
plt.figure()
dat = np.array(imc_ac.get_img_stack_cyx([0])).squeeze()
plt.imshow(np.array(imc_ac.get_img_stack_cyx([0])).squeeze())
diff --git a/imctools/io/tiffwriter.py b/imctools/io/tiffwriter.py
index 3996d62..c292c9d 100644
--- a/imctools/io/tiffwriter.py
+++ b/imctools/io/tiffwriter.py
@@ -11,36 +11,52 @@
if sys.version_info.major == 3:
from io import StringIO
- uenc = 'unicode'
+
+ uenc = "unicode"
else:
from cStringIO import StringIO
- uenc = 'utf-8'
+
+ uenc = "utf-8"
class TiffWriter(object):
"""
"""
- pixeltype_dict = ({np.int64().dtype: ome.PT_FLOAT,
- np.int32().dtype: ome.PT_INT32,
- np.int16().dtype: ome.PT_INT16,
- np.uint16().dtype: ome.PT_UINT16,
- np.uint32().dtype: ome.PT_UINT32,
- np.uint8().dtype: ome.PT_UINT8,
- np.float32().dtype: ome.PT_FLOAT,
- np.float64().dtype: ome.PT_DOUBLE
- })
+
+ pixeltype_dict = {
+ np.int64().dtype: ome.PT_FLOAT,
+ np.int32().dtype: ome.PT_INT32,
+ np.int16().dtype: ome.PT_INT16,
+ np.uint16().dtype: ome.PT_UINT16,
+ np.uint32().dtype: ome.PT_UINT32,
+ np.uint8().dtype: ome.PT_UINT8,
+ np.float32().dtype: ome.PT_FLOAT,
+ np.float64().dtype: ome.PT_DOUBLE,
+ }
pixeltype_np = {
- ome.PT_FLOAT: np.dtype('float32'),
- ome.PT_DOUBLE: np.dtype('float64'),
- ome.PT_UINT8: np.dtype('uint8'),
- ome.PT_UINT16: np.dtype('uint16'),
- ome.PT_UINT32: np.dtype('uint32'),
- ome.PT_INT8: np.dtype('int8'),
- ome.PT_INT16: np.dtype('int16'),
- ome.PT_INT32: np.dtype('int32')
- }
- def __init__(self, file_name, img_stack, pixeltype =None, channel_name=None, original_description=None, fluor=None):
+ ome.PT_FLOAT: np.dtype("float32"),
+ ome.PT_DOUBLE: np.dtype("float64"),
+ ome.PT_UINT8: np.dtype("uint8"),
+ ome.PT_UINT16: np.dtype("uint16"),
+ ome.PT_UINT32: np.dtype("uint32"),
+ ome.PT_INT8: np.dtype("int8"),
+ ome.PT_INT16: np.dtype("int16"),
+ ome.PT_INT32: np.dtype("int32"),
+ }
+
+ def __init__(
+ self,
+ file_name,
+ img_stack,
+ pixeltype=None,
+ channel_name=None,
+ original_description=None,
+ fluor=None,
+ ):
+ warnings.warn(
+ "imctools 1.x is deprecated, please migrate to version 2.x", DeprecationWarning
+ )
self.file_name = file_name
self.img_stack = img_stack
self.channel_name = channel_name
@@ -54,11 +70,11 @@ def __init__(self, file_name, img_stack, pixeltype =None, channel_name=None, ori
self.pixeltype = pixeltype
if original_description is None:
- original_description = ''
+ original_description = ""
self.original_description = original_description
- def save_image(self, mode='imagej', compression=0, dtype=None, bigtiff=None):
+ def save_image(self, mode="imagej", compression=0, dtype=None, bigtiff=None):
"""
Saves the image as a tiff
:param mode: Specifies the tiff writing mode. Either 'imagej' or 'ome'
@@ -75,7 +91,7 @@ def save_image(self, mode='imagej', compression=0, dtype=None, bigtiff=None):
Default: for 'imagej' mode: False
for 'ome' mode: True
"""
- #TODO: add original metadata somehow
+ # TODO: add original metadata somehow
fn_out = self.file_name
img = self.img_stack.swapaxes(2, 0)
if dtype is not None:
@@ -84,17 +100,24 @@ def save_image(self, mode='imagej', compression=0, dtype=None, bigtiff=None):
dt = self.pixeltype_np[self.pixeltype]
img = change_dtype(img, dt)
# img = img.reshape([1,1]+list(img.shape)).swapaxes(2, 0)
- if mode == 'imagej':
+ if mode == "imagej":
if bigtiff is None:
- bigtiff=False
- tifffile.imsave(fn_out, img, compress=compression, imagej=True,
- bigtiff=bigtiff)
- elif mode == 'ome':
+ bigtiff = False
+ tifffile.imsave(
+ fn_out, img, compress=compression, imagej=True, bigtiff=bigtiff
+ )
+ elif mode == "ome":
if bigtiff is None:
- bigtiff=True
+ bigtiff = True
xml = self.get_xml(dtype=dtype)
- tifffile.imsave(fn_out, img, compress=compression, imagej=False,
- description=xml, bigtiff=bigtiff)
+ tifffile.imsave(
+ fn_out,
+ img,
+ compress=compression,
+ imagej=False,
+ description=xml,
+ bigtiff=bigtiff,
+ )
# def save_xml(self):
# xml = self.get_xml()
@@ -135,22 +158,20 @@ def get_xml(self, dtype=None):
channel_info = self.channel_name[i]
p.Channel(i).set_SamplesPerPixel(1)
p.Channel(i).set_Name(channel_info)
- p.Channel(i).set_ID('Channel:0:' + str(i))
- p.Channel(i).node.set('Fluor', self.fluor[i])
+ p.Channel(i).set_ID("Channel:0:" + str(i))
+ p.Channel(i).node.set("Fluor", self.fluor[i])
# adds original metadata as annotation
if self.original_description is not None:
- if isinstance(self.original_description,
- type(ElementTree.Element(1))):
+ if isinstance(self.original_description, type(ElementTree.Element(1))):
result = StringIO()
- ElementTree.ElementTree(self.original_description).write(result,
- encoding=uenc, method="xml")
+ ElementTree.ElementTree(self.original_description).write(
+ result, encoding=uenc, method="xml"
+ )
desc = result.getvalue()
else:
desc = str(self.original_description)
- omexml.structured_annotations.add_original_metadata(
- 'MCD-XML',
- desc)
+ omexml.structured_annotations.add_original_metadata("MCD-XML", desc)
xml = omexml.to_xml()
return xml
diff --git a/imctools/io/txtparser.py b/imctools/io/txtparser.py
index 6342ff9..c12bf50 100644
--- a/imctools/io/txtparser.py
+++ b/imctools/io/txtparser.py
@@ -7,6 +7,7 @@
import array
import numpy as np
+
class TxtParser(AbstractParser, TxtParserBase):
"""
Loads and strores an IMC .txt file
@@ -24,14 +25,17 @@ def get_imc_acquisition(self):
"""
img = self._reshape_long_2_cyx(self.data, is_sorted=True)
ac_id = self.ac_id
- return ImcAcquisition(ac_id, self.filename,
- img,
- self.channel_metals,
- self.channel_labels,
- original_metadata=None,
- image_description=None,
- origin=self.origin,
- offset=3)
+ return ImcAcquisition(
+ ac_id,
+ self.filename,
+ img,
+ self.channel_metals,
+ self.channel_labels,
+ original_metadata=None,
+ image_description=None,
+ origin=self.origin,
+ offset=3,
+ )
@staticmethod
def clean_channel_metals(names):
@@ -44,40 +48,40 @@ def clean_channel_metals(names):
names = [n.strip("\n") for n in names]
names = [n.strip() for n in names]
# string of sort asbsdf(mn123di)
- if names[0].rfind(')') == (len(names[0])-1):
- #get m123di
+ if names[0].rfind(")") == (len(names[0]) - 1):
+ # get m123di
- names = [n[(n.rfind('(')+1):(n.rfind(')'))] for n in names]
+ names = [n[(n.rfind("(") + 1) : (n.rfind(")"))] for n in names]
# string of sort aasbas_mn123
- elif '_' in names[0]:
- names = [n.split('_')[-1] for n in names]
+ elif "_" in names[0]:
+ names = [n.split("_")[-1] for n in names]
# else do nothing
else:
return names
# else there is the bug where (123123di)
- names = [n.rstrip('di') for n in names]
- names = [n.rstrip('Di') for n in names]
+ names = [n.rstrip("di") for n in names]
+ names = [n.rstrip("Di") for n in names]
if names[0][0].isdigit():
- names = [n[(int(len(n)/2)):] for n in names]
+ names = [n[(int(len(n) / 2)) :] for n in names]
return names
-
-if __name__ == '__main__':
+if __name__ == "__main__":
import matplotlib.pyplot as plt
import timeit
- fn = '/home/vitoz/temp/HIER_healthy_4_3_HIER5_4.txt'
- #fn = '/mnt/imls-bod/data_vito/Spheres/20160330_BigInspheroIMC2/20150330_IS2335_5um_3_site1_ac2_200hz_2200x2200/20150330_IS2335_5um_3_site1_ac2_200hz_2200x2200.txt'
- #fn = '/home/vitoz/temp/20150330_IS2335_5um_3_site1_ac2_200hz_2200x2200.txt'
+
+ fn = "/home/vitoz/temp/HIER_healthy_4_3_HIER5_4.txt"
+ # fn = '/mnt/imls-bod/data_vito/Spheres/20160330_BigInspheroIMC2/20150330_IS2335_5um_3_site1_ac2_200hz_2200x2200/20150330_IS2335_5um_3_site1_ac2_200hz_2200x2200.txt'
+ # fn = '/home/vitoz/temp/20150330_IS2335_5um_3_site1_ac2_200hz_2200x2200.txt'
tic = timeit.default_timer()
imc_txt = TxtParser(fn)
- tic = timeit.default_timer();
+ tic = timeit.default_timer()
imc_ac = imc_txt.get_imc_acquisition()
- #iw = imc_ac.get_image_writer('/home/vitoz/temp/test_iridium.ome.tiff', mass=['191', '193'])
- #iw.save_image(mode='ome')
- #iw = imc_ac.get_image_writer('/home/vitoz/temp/HIER_healthy_4_3_HIER5_4.ome.tiff')
- #iw.save_image(mode='ome')
+ # iw = imc_ac.get_image_writer('/home/vitoz/temp/test_iridium.ome.tiff', mass=['191', '193'])
+ # iw.save_image(mode='ome')
+ # iw = imc_ac.get_image_writer('/home/vitoz/temp/HIER_healthy_4_3_HIER5_4.ome.tiff')
+ # iw.save_image(mode='ome')
diff --git a/imctools/io/txtparserbase.py b/imctools/io/txtparserbase.py
index 2ccd057..459418d 100644
--- a/imctools/io/txtparserbase.py
+++ b/imctools/io/txtparserbase.py
@@ -4,7 +4,9 @@
from imctools.io.imcacquisitionbase import ImcAcquisitionBase
from imctools.io.abstractparserbase import AbstractParserBase
import array
-TXT_FILENDING='.txt'
+
+TXT_FILENDING = ".txt"
+
class TxtParserBase(AbstractParserBase):
"""
@@ -15,12 +17,12 @@ def __init__(self, filename, filehandle=None):
AbstractParserBase.__init__(self)
self.filename = filename
if filehandle is None:
- with open(filename, 'r') as txtfile:
+ with open(filename, "r") as txtfile:
self.parse_csv3(txtfile)
else:
filehandle.seek(0)
self.parse_csv3(filehandle)
- self.origin ='txt'
+ self.origin = "txt"
self.channel_labels = self.channel_metals[:]
self.channel_metals[3:] = self.clean_channel_metals(self.channel_metals[3:])
@@ -31,7 +33,7 @@ def ac_id(self):
@staticmethod
def _txtfn_to_ac(fn):
- return fn.rstrip(TXT_FILENDING).split('_')[-1]
+ return fn.rstrip(TXT_FILENDING).split("_")[-1]
def get_imc_acquisition(self):
"""
@@ -42,14 +44,17 @@ def get_imc_acquisition(self):
img = self._reshape_long_2_cyx(dat, is_sorted=True)
ac_id = self.ac_id
- return ImcAcquisitionBase(ac_id, self.filename,
- img,
- self.channel_metals,
- self.channel_labels,
- original_metadata=None,
- image_description=None,
- origin=self.origin,
- offset=3)
+ return ImcAcquisitionBase(
+ ac_id,
+ self.filename,
+ img,
+ self.channel_metals,
+ self.channel_labels,
+ original_metadata=None,
+ image_description=None,
+ origin=self.origin,
+ offset=3,
+ )
@staticmethod
def clean_channel_metals(names):
@@ -63,52 +68,50 @@ def clean_channel_metals(names):
names = [n.strip("\n") for n in names]
names = [n.strip() for n in names]
# string of sort asbsdf(mn123di)
- if names[0].rfind(')') == (len(names[0])-1):
- #get m123di
+ if names[0].rfind(")") == (len(names[0]) - 1):
+ # get m123di
- names = [n[(n.rfind('(')+1):(n.rfind(')'))] for n in names]
+ names = [n[(n.rfind("(") + 1) : (n.rfind(")"))] for n in names]
print(names)
# string of sort aasbas_mn123
- elif '_' in names[0]:
- names = [n.split('_')[-1] for n in names]
+ elif "_" in names[0]:
+ names = [n.split("_")[-1] for n in names]
# else do nothing
else:
return names
# else there is the bug where (123123di)
- names = [n.rstrip('di') for n in names]
- names = [n.rstrip('Di') for n in names]
+ names = [n.rstrip("di") for n in names]
+ names = [n.rstrip("Di") for n in names]
if names[0][0].isdigit():
- names = [n[(int(len(n)/2)):] for n in names]
+ names = [n[(int(len(n) / 2)) :] for n in names]
return names
def parse_csv(self, txtfile, first_col=3):
- txtreader = csv.reader(txtfile, delimiter='\t')
+ txtreader = csv.reader(txtfile, delimiter="\t")
header = txtreader.next()
channel_names = header[first_col:]
nchan = len(channel_names)
- txtreader = csv.reader(txtfile, delimiter='\t',
- quoting=csv.QUOTE_NONNUMERIC)
+ txtreader = csv.reader(txtfile, delimiter="\t", quoting=csv.QUOTE_NONNUMERIC)
txtreader.next()
data = list()
for row in txtreader:
- rowar = array.array('f')
+ rowar = array.array("f")
rowar.fromlist(row[first_col:])
data.append(rowar)
self.data = data
self.channel_metals = channel_names
def parse_csv2(self, txtfile, first_col=3):
- header = txtfile.readline().split('\t')
+ header = txtfile.readline().split("\t")
channel_names = header[first_col:]
- data = [[float(v) for v in row.split('\t')[first_col:]] for row in txtfile]
+ data = [[float(v) for v in row.split("\t")[first_col:]] for row in txtfile]
self.data = data
self.channel_metals = channel_names
-
def parse_csv3(self, txtfile, first_col=3):
"""
The fastest csv parser so far
@@ -116,30 +119,31 @@ def parse_csv3(self, txtfile, first_col=3):
:param first_col: First column to consider
:return:
"""
- header = txtfile.readline().split('\t')
+ header = txtfile.readline().split("\t")
channel_names = header[first_col:]
nchan = len(channel_names)
- rowar = array.array('f')
+ rowar = array.array("f")
for row in txtfile:
- for v in row.split('\t')[first_col:]:
+ for v in row.split("\t")[first_col:]:
rowar.append(float(v))
- nrow = int(len(rowar)/nchan)
- data = [rowar[(i*nchan):(i*nchan+nchan)] for i in range(nrow)]
+ nrow = int(len(rowar) / nchan)
+ data = [rowar[(i * nchan) : (i * nchan + nchan)] for i in range(nrow)]
self.data = data
self.channel_metals = channel_names
-if __name__ == '__main__':
+if __name__ == "__main__":
import timeit
- #fn = '/home/vitoz/temp/grade1_1_0_A0_0.txt'
- fn = '/media/vitoz/datahdd/data/site1_0_A0_0 - Copy.txt'
- #fn = '/home/vitoz/temp/20150330_IS2335_5um_3_site1_ac2_200hz_2200x2200.txt'
+
+ # fn = '/home/vitoz/temp/grade1_1_0_A0_0.txt'
+ fn = "/media/vitoz/datahdd/data/site1_0_A0_0 - Copy.txt"
+ # fn = '/home/vitoz/temp/20150330_IS2335_5um_3_site1_ac2_200hz_2200x2200.txt'
tic = timeit.default_timer()
imc_txt = TxtParserBase(fn)
- print(timeit.default_timer()-tic)
+ print(timeit.default_timer() - tic)
tic = timeit.default_timer()
imc_txt = imc_txt.parse_csv3(fn)
- print(timeit.default_timer()-tic)
+ print(timeit.default_timer() - tic)
imc_ac = imc_txt.get_imc_acquisition()
rowimg = imc_ac._data[1]
print(rowimg[0][:3])
@@ -147,7 +151,7 @@ def parse_csv3(self, txtfile, first_col=3):
print(rowimg[2][:3])
import numpy as np
import matplotlib.pyplot as plt
- print(np.asarray(rowimg))
+ print(np.asarray(rowimg))
- #print(imc_ac.get_img_by_channel_nr(1))
+ # print(imc_ac.get_img_by_channel_nr(1))
diff --git a/imctools/library.py b/imctools/library.py
index 78e404c..6b5fa95 100644
--- a/imctools/library.py
+++ b/imctools/library.py
@@ -28,7 +28,8 @@
import warnings
-def remove_outlier_pixels(img, threshold=50, mode='median', radius=3):
+
+def remove_outlier_pixels(img, threshold=50, mode="median", radius=3):
"""
>>> a = np.zeros((10, 10))
@@ -38,60 +39,72 @@ def remove_outlier_pixels(img, threshold=50, mode='median', radius=3):
radius=3))
True
"""
- warnings.warn('''remove_outlier_pixels is deprecated and
+ warnings.warn(
+ """remove_outlier_pixels is deprecated and
will not be supported in future versions.
Please use the `Smooth Multichannel` module from
Bodenmillergroup/ImcPluginsCP
- in CellProfiler!''',
- DeprecationWarning)
+ in CellProfiler!""",
+ DeprecationWarning,
+ )
if (radius % 2) == 0:
- radius += 1
+ radius += 1
mask = np.ones((radius, radius))
- mask[int((radius-1)/2),int((radius-1)/2)] = 0
+ mask[int((radius - 1) / 2), int((radius - 1) / 2)] = 0
- if mode == 'max':
+ if mode == "max":
img_agg = ndi.generic_filter(img, np.max, footprint=mask)
- elif mode == 'median':
+ elif mode == "median":
img_agg = ndi.generic_filter(img, np.median, footprint=mask)
else:
- raise('Mode must be: max or median')
+ raise ("Mode must be: max or median")
img_out = img.copy()
- imgfil = (img-img_agg) > threshold
+ imgfil = (img - img_agg) > threshold
img_out[imgfil] = img_agg[imgfil]
return img_out
-def scale_images(img, cap_percentile=99, rescale = False):
- warnings.warn('''scale_images is deprecated and
+
+def scale_images(img, cap_percentile=99, rescale=False):
+ warnings.warn(
+ """scale_images is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
- perc = np.percentile(img, cap_percentile)
- img[img > perc] = perc
- if rescale:
- img = sk.exposure.rescale_intensity(img)
- return img
+ """,
+ DeprecationWarning,
+ )
+ perc = np.percentile(img, cap_percentile)
+ img[img > perc] = perc
+ if rescale:
+ img = sk.exposure.rescale_intensity(img)
+ return img
def normalize_images(img, **kwargs):
- warnings.warn('''normalize_images is deprecated and
+ warnings.warn(
+ """normalize_images is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
- img = sk.exposure.equalize_hist(img, **kwargs)
-
-
-def threshold_images(img, method='otsu',
- thresh_cor=None,
- thresh=None,
- fill=False,
- block_size=10, # only for adaptive
- **kwargs):
- warnings.warn('''threshold_images is deprecated and
+ """,
+ DeprecationWarning,
+ )
+ img = sk.exposure.equalize_hist(img, **kwargs)
+
+
+def threshold_images(
+ img,
+ method="otsu",
+ thresh_cor=None,
+ thresh=None,
+ fill=False,
+ block_size=10, # only for adaptive
+ **kwargs
+):
+ warnings.warn(
+ """threshold_images is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
- if method.lower() == 'otsu':
+ if method.lower() == "otsu":
thresh = filters.threshold_otsu(img)
if thresh_cor is None:
@@ -99,21 +112,19 @@ def threshold_images(img, method='otsu',
else:
tresh_img = img > thresh * thresh_cor
- elif method.lower() == 'adaptive':
- thresh = filters.threshold_adaptive(img,
- block_size, **kwargs)
+ elif method.lower() == "adaptive":
+ thresh = filters.threshold_adaptive(img, block_size, **kwargs)
if thresh_cor is None:
tresh_img = img > thresh
else:
tresh_img = img > thresh * thresh_cor
- elif method.lower() == 'manual':
+ elif method.lower() == "manual":
if thresh is None:
- raise NameError(
- 'when using manual thresholding, supply a threshold')
+ raise NameError("when using manual thresholding, supply a threshold")
else:
- raise NameError('Invalid threshold method used')
+ raise NameError("Invalid threshold method used")
if fill:
tresh_img = sp.ndimage.binary_fill_holes(tresh_img)
@@ -122,10 +133,12 @@ def threshold_images(img, method='otsu',
def keep_max_area(tresh_img):
- warnings.warn('''keep_max_area is deprecated and
+ warnings.warn(
+ """keep_max_area is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
lab = sk.measure.label(tresh_img)
labMax = np.bincount(lab[lab > 0]).argmax()
tresh_img_max = lab == labMax
@@ -133,23 +146,27 @@ def keep_max_area(tresh_img):
def flip_img(img, axis):
- warnings.warn('''flip_img is deprecated and
+ warnings.warn(
+ """flip_img is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
if axis == 1:
img = np.fliplr(img)
elif axis == 0:
img = np.flipud(img)
else:
- raise NameError('Axis: 0: up down, 1:left right')
+ raise NameError("Axis: 0: up down, 1:left right")
def crop_img_to_binary(img, tresh_img):
- warnings.warn('''crop_img_to_binary is deprecated and
+ warnings.warn(
+ """crop_img_to_binary is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
region = sk.measure.regionprops(tresh_img)
minr, minc, maxr, maxc = region[0].bbox
@@ -158,41 +175,44 @@ def crop_img_to_binary(img, tresh_img):
return (img, tresh_img)
-def stretch_imgs_equal(img_list,
- stretch_dim='w', # w: widht, h: height, b: both
- direction='min', # min or max
- interpol=None # which interpolation algorithm
- ):
- warnings.warn('''stretch_imgs_equal is deprecated and
+def stretch_imgs_equal(
+ img_list,
+ stretch_dim="w", # w: widht, h: height, b: both
+ direction="min", # min or max
+ interpol=None, # which interpolation algorithm
+):
+ warnings.warn(
+ """stretch_imgs_equal is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
heights = np.array([float(img.shape[0]) for img in img_list])
widths = np.array([float(img.shape[1]) for img in img_list])
- if direction == 'min':
+ if direction == "min":
w_ref = widths.min()
h_ref = heights.min()
- elif direction == 'max':
+ elif direction == "max":
w_ref = widths.max()
h_ref = heights.max()
- if stretch_dim == 'w':
- w_scale = widths/float(w_ref)
+ if stretch_dim == "w":
+ w_scale = widths / float(w_ref)
h_scale = w_scale
- if stretch_dim == 'h':
- h_scale = heights/float(h_ref)
+ if stretch_dim == "h":
+ h_scale = heights / float(h_ref)
w_scale = h_scale
- if stretch_dim == 'b':
- h_scale = heights/float(h_ref)
- w_scale = widths/float(w_ref)
+ if stretch_dim == "b":
+ h_scale = heights / float(h_ref)
+ w_scale = widths / float(w_ref)
- widths = np.floor(widths/w_scale)
- heights = np.floor(heights/h_scale)
+ widths = np.floor(widths / w_scale)
+ heights = np.floor(heights / h_scale)
# stretch everything to max widht/maxheight
out_imgs = list()
for (img, w, h) in zip(img_list, widths, heights):
@@ -203,29 +223,34 @@ def stretch_imgs_equal(img_list,
def blur_img_gauss(img, sigma=1, idKeys=None):
- warnings.warn('''blur_img_gauss is deprecated and
+ warnings.warn(
+ """blur_img_gauss is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
blur_img = filters.gaussian_filter(img, sigma=sigma)
return blur_img
-def l2l_corr(img,dim=0):
- '''Calculates the line to line correlations between all lines of an image,
- represented as a 2D matrix img'''
- warnings.warn('''l2l_corr is deprecated and
+
+def l2l_corr(img, dim=0):
+ """Calculates the line to line correlations between all lines of an image,
+ represented as a 2D matrix img"""
+ warnings.warn(
+ """l2l_corr is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
if dim == 0:
img = img.T
nCol = img.shape[1]
- corrArray = np.zeros(nCol-1)
+ corrArray = np.zeros(nCol - 1)
- for i in range(nCol-1):
- corrArray[i] = np.corrcoef(img[:,i], img[:,i+1])[1,0]
- return(corrArray)
+ for i in range(nCol - 1):
+ corrArray[i] = np.corrcoef(img[:, i], img[:, i + 1])[1, 0]
+ return corrArray
def distance_transform_wrapper(logicarray, maxdist=65535):
@@ -240,10 +265,12 @@ def distance_transform_wrapper(logicarray, maxdist=65535):
:returns an array containing the distance to the next False pixel
"""
- warnings.warn('''distance_transform_wrapper is deprecated and
+ warnings.warn(
+ """distance_transform_wrapper is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
if np.all(logicarray):
shape = logicarray.shape
@@ -254,6 +281,7 @@ def distance_transform_wrapper(logicarray, maxdist=65535):
else:
return ndi.morphology.distance_transform_edt(logicarray)
+
def distance_to_border(logicarray, maxdist=65535):
"""
Returns the eucledian distance to the border of a binary logical array.
@@ -264,10 +292,12 @@ def distance_to_border(logicarray, maxdist=65535):
positive pixel is in the logicarry.
:returns an array containing the distance to the next False pixel
"""
- warnings.warn('''distance_to_border is deprecated and
+ warnings.warn(
+ """distance_to_border is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
logicarray = logicarray > 0
if np.all(logicarray) | np.all(logicarray == False):
@@ -287,6 +317,7 @@ def distance_to_border(logicarray, maxdist=65535):
## working with masks
+
def find_touching_pixels(label_img, distance=1, selem=None):
"""
Returns a mask indicating touching regions. Either provide a diameter for a disk shape
@@ -297,10 +328,12 @@ def find_touching_pixels(label_img, distance=1, selem=None):
1 the 'distance' is not true.
:return: a mask of the regions touching or are close up to a certain diameter
"""
- warnings.warn('''find_touching_pixels is deprecated and
+ warnings.warn(
+ """find_touching_pixels is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
if selem is None:
selem = morphology.disk(1)
@@ -310,40 +343,48 @@ def find_touching_pixels(label_img, distance=1, selem=None):
for i in np.unique(label_img):
if i != 0:
- cur_lab = (label_img == i)
- #touch_mask[ndi.filters.maximum_filter(cur_lab, footprint=selem) &
+ cur_lab = label_img == i
+ # touch_mask[ndi.filters.maximum_filter(cur_lab, footprint=selem) &
# not_bg & (cur_lab == False)] = 1
- touch_mask[ndi.binary_dilation(cur_lab, structure=selem, iterations=distance, mask=not_bg) &
- (cur_lab == False)] = 1
+ touch_mask[
+ ndi.binary_dilation(
+ cur_lab, structure=selem, iterations=distance, mask=not_bg
+ )
+ & (cur_lab == False)
+ ] = 1
return touch_mask
-
def scale_labelmask(labelmask, scale):
- warnings.warn('''scale_labelmask is deprecated and
+ warnings.warn(
+ """scale_labelmask is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
- #assert (scaling % 1) == 0, "only integer scaling supported!"
+ """,
+ DeprecationWarning,
+ )
+ # assert (scaling % 1) == 0, "only integer scaling supported!"
# rescale
- trans_labs = transform.rescale(labelmask+1,scale=scale, preserve_range=True)
+ trans_labs = transform.rescale(labelmask + 1, scale=scale, preserve_range=True)
- trans_labs[(trans_labs %1) > 0] =1
- trans_labs = np.round(trans_labs)-1
+ trans_labs[(trans_labs % 1) > 0] = 1
+ trans_labs = np.round(trans_labs) - 1
#
tmplabels = ndi.uniform_filter(trans_labs, size=2)
trans_labs[trans_labs != tmplabels] = 0
return trans_labs.astype(np.int)
+
def extract_mean_markers_by_mask(label_image, img_stack):
- warnings.warn('''extract_mean_markers_by_mask is deprecated and
+ warnings.warn(
+ """extract_mean_markers_by_mask is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
label_image = np.squeeze(label_image)
label_dict = dict()
objects = ndi.find_objects(label_image)
@@ -355,11 +396,14 @@ def extract_mean_markers_by_mask(label_image, img_stack):
label = i + 1
mask = label_image[sl] == label
if np.any(mask):
- label_dict[label] = np.array([np.mean(slice[sl][mask]) for slice in img_stack])
+ label_dict[label] = np.array(
+ [np.mean(slice[sl][mask]) for slice in img_stack]
+ )
return label_dict
-def apply_functions_to_labels(label_image, img_stack, fkt_list ,out_array=None):
+
+def apply_functions_to_labels(label_image, img_stack, fkt_list, out_array=None):
"""
:param label_img:
@@ -367,40 +411,44 @@ def apply_functions_to_labels(label_image, img_stack, fkt_list ,out_array=None):
:param fkt_dict: dict key: fkt_name, value: function of the form fkt(mask, img)
:return:
"""
- warnings.warn('''apply_functions_to_labels is deprecated and
+ warnings.warn(
+ """apply_functions_to_labels is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
label_image = np.squeeze(label_image)
objects = ndi.find_objects(label_image)
- objects = [(i+1, sl) for i, sl in enumerate(objects) if sl is not None]
+ objects = [(i + 1, sl) for i, sl in enumerate(objects) if sl is not None]
nobj = len(objects)
nchannels = img_stack.shape[2]
- out_shape = (nobj*nchannels, len(fkt_list)+1)
+ out_shape = (nobj * nchannels, len(fkt_list) + 1)
if out_array is None:
out_array = np.empty(out_shape)
else:
- assert out_array.shape == out_shape, (out_array.shape,out_shape)
+ assert out_array.shape == out_shape, (out_array.shape, out_shape)
for i, (label, sl) in enumerate(objects):
- out_idx = np.s_[(i*nchannels):((i+1)*nchannels)]
+ out_idx = np.s_[(i * nchannels) : ((i + 1) * nchannels)]
img_sl = img_stack[sl]
print(img_stack.shape, label_image.shape)
mask = label_image[sl] == label
sl_image = [img_sl[..., i] for i in range(img_sl.shape[2])]
t_out_array = out_array[out_idx]
- x= np.array([[fkt(mask, img) for fkt in fkt_list] for img in sl_image])
- t_out_array[:, 1:]= x
+ x = np.array([[fkt(mask, img) for fkt in fkt_list] for img in sl_image])
+ t_out_array[:, 1:] = x
t_out_array[:, 0] = label
-
return out_array
-def apply_functions_to_list_of_labels(label_image_list, img_stack_list, fkt_list ,out_array=None):
+
+def apply_functions_to_list_of_labels(
+ label_image_list, img_stack_list, fkt_list, out_array=None
+):
"""
:param ids:
@@ -410,12 +458,14 @@ def apply_functions_to_list_of_labels(label_image_list, img_stack_list, fkt_list
:param out_array:
:return:
"""
- warnings.warn('''apply_functions_to_list_of_labels is deprecated and
+ warnings.warn(
+ """apply_functions_to_list_of_labels is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
- nobjs = [len(np.unique(labs))-1 for labs in label_image_list]
+ nobjs = [len(np.unique(labs)) - 1 for labs in label_image_list]
nchannels = img_stack_list[0].shape[2]
nfkts = len(fkt_list)
@@ -424,23 +474,25 @@ def apply_functions_to_list_of_labels(label_image_list, img_stack_list, fkt_list
if out_array is None:
out_array = np.empty(out_shape)
else:
- assert(out_array.shape == out_shape)
+ assert out_array.shape == out_shape
last_idx = 0
for i, (labs, img_stack) in enumerate(zip(label_image_list, img_stack_list)):
- next_idx = (last_idx+nobjs[i]*nchannels)
+ next_idx = last_idx + nobjs[i] * nchannels
out_idx = np.s_[(last_idx):next_idx]
- t_out_array = out_array[out_idx,:]
+ t_out_array = out_array[out_idx, :]
t_out_array[:, 0] = i
- apply_functions_to_labels(labs, img_stack, fkt_list, out_array = t_out_array[:,1:])
+ apply_functions_to_labels(
+ labs, img_stack, fkt_list, out_array=t_out_array[:, 1:]
+ )
last_idx = next_idx
return out_array
-def apply_functions_to_list_of_labels_table(label_image_list,
- img_stack_list, fkt_list, fkt_names,
- channel_names, slice_ids=None):
+def apply_functions_to_list_of_labels_table(
+ label_image_list, img_stack_list, fkt_list, fkt_names, channel_names, slice_ids=None
+):
"""
:param label_image_list:
@@ -450,23 +502,26 @@ def apply_functions_to_list_of_labels_table(label_image_list,
:param channel_names:
:return:
"""
- warnings.warn('''apply_functions_to_labels_table is deprecated and
+ warnings.warn(
+ """apply_functions_to_labels_table is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
dat = apply_functions_to_list_of_labels(label_image_list, img_stack_list, fkt_list)
- dat = pd.DataFrame(dat, columns=['cut_id', 'cell_id'] + list(fkt_names))
- dat['channel'] = np.tile(np.array(channel_names), dat.shape[0]/len(channel_names))
+ dat = pd.DataFrame(dat, columns=["cut_id", "cell_id"] + list(fkt_names))
+ dat["channel"] = np.tile(np.array(channel_names), dat.shape[0] / len(channel_names))
if slice_ids is not None:
slice_ids = np.array(slice_ids)
- dat['cut_id'] = slice_ids[dat['cut_id']]
- dat = dat.set_index(['cut_id', 'cell_id', 'channel'])
- dat = dat.unstack(level='channel')
- dat.columns.names = ['stat', 'channel']
+ dat["cut_id"] = slice_ids[dat["cut_id"]]
+ dat = dat.set_index(["cut_id", "cell_id", "channel"])
+ dat = dat.unstack(level="channel")
+ dat.columns.names = ["stat", "channel"]
return dat
-def extend_slice_touple(slice_touple, extent, max_dim ,min_dim =(0,0)):
+
+def extend_slice_touple(slice_touple, extent, max_dim, min_dim=(0, 0)):
"""
Extends a numpy slice touple, e.g. corresponding to a bounding box
:param slice_touple: a numpy slice
@@ -477,12 +532,14 @@ def extend_slice_touple(slice_touple, extent, max_dim ,min_dim =(0,0)):
"""
-
- new_slice = tuple(_extend_slice(s,extent, d_max, d_min) for s, d_max, d_min in
- zip(slice_touple, max_dim, min_dim))
+ new_slice = tuple(
+ _extend_slice(s, extent, d_max, d_min)
+ for s, d_max, d_min in zip(slice_touple, max_dim, min_dim)
+ )
return new_slice
+
def _extend_slice(sl, extent, dim_max, dim_min=0):
"""
helper function to extend single slices
@@ -493,13 +550,12 @@ def _extend_slice(sl, extent, dim_max, dim_min=0):
:return: the new extended slice
"""
- x_start = max(sl.start-extent,dim_min)
- x_end = min(sl.stop+ extent, dim_max)
+ x_start = max(sl.start - extent, dim_min)
+ x_end = min(sl.stop + extent, dim_max)
return np.s_[x_start:x_end]
-
def add_slice_dimension(sl, append=True):
"""
Appends another dimension to a numpy slice
@@ -512,11 +568,11 @@ def add_slice_dimension(sl, append=True):
if append:
exsl = tuple([s for s in sl] + [np.s_[:]])
else:
- exsl = tuple([np.s_[:]]+[s for s in sl])
+ exsl = tuple([np.s_[:]] + [s for s in sl])
return exsl
-def map_series_on_mask(mask, series, label = None):
+def map_series_on_mask(mask, series, label=None):
"""
TODO: A good docstring here
:param mask:
@@ -524,25 +580,26 @@ def map_series_on_mask(mask, series, label = None):
:param label:
:return:
"""
- warnings.warn('''map_series_on_mask is deprecated and
+ warnings.warn(
+ """map_series_on_mask is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
if label is None:
label = series.index
# make a dict
-
- labeldict = np.empty(mask.max()+1)
+ labeldict = np.empty(mask.max() + 1)
labeldict[:] = np.NaN
for lab, val in zip(label, series):
labeldict[int(lab)] = val
out_img = labeldict[mask.flatten()]
- out_img = np.reshape(out_img,mask.shape)
- out_img = np.ma.array(out_img, mask = mask==0)
+ out_img = np.reshape(out_img, mask.shape)
+ out_img = np.ma.array(out_img, mask=mask == 0)
return out_img
@@ -553,10 +610,12 @@ def create_neightbourhood_dict(label_mask, bg_label=0):
:param label_mask:
:return: nb_dict: a with key=label and entry=neightbour label
"""
- warnings.warn('''create_neightbourhood_dict is deprecated and
+ warnings.warn(
+ """create_neightbourhood_dict is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
vertices, edges = make_neighbourhood_graph(label_mask)
nb_dict = dict((v, list()) for v in vertices if v != bg_label)
@@ -569,7 +628,6 @@ def create_neightbourhood_dict(label_mask, bg_label=0):
return nb_dict
-
def make_neighbourhood_graph(label_mask, uni_edges=True):
"""
Adapted from the internet
@@ -578,10 +636,12 @@ def make_neighbourhood_graph(label_mask, uni_edges=True):
:param label_mask:
:return: vertices, edges: vertices and edges of the neighbourhood graph, includes background labels
"""
- warnings.warn('''make_neighbourhood_graph is deprecated and
+ warnings.warn(
+ """make_neighbourhood_graph is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
# get unique labels
grid = label_mask
vertices = np.unique(grid)
@@ -602,8 +662,7 @@ def make_neighbourhood_graph(label_mask, uni_edges=True):
# find unique connections
edges = np.unique(edge_hash)
# undo hashing
- edges = [[vertices[x % num_vertices],
- vertices[x / num_vertices]] for x in edges]
+ edges = [[vertices[x % num_vertices], vertices[x / num_vertices]] for x in edges]
return vertices, edges
@@ -617,10 +676,12 @@ def save_object_stack(folder, basename, img_stack, slices, labels=None):
:param slices: a list of numpy slices sphecifying the regions to be saved
:return:
"""
- warnings.warn('''save_object_stack is deprecated and
+ warnings.warn(
+ """save_object_stack is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
if labels is None:
labels = range(slices)
@@ -632,7 +693,10 @@ def save_object_stack(folder, basename, img_stack, slices, labels=None):
exsl = add_slice_dimension(sl, append=False)
- fn = os.path.join(folder, basename + '_l' + str(lab + 1) + '_x' + str(x) + '_y' + str(y)+'.tiff')
+ fn = os.path.join(
+ folder,
+ basename + "_l" + str(lab + 1) + "_x" + str(x) + "_y" + str(y) + ".tiff",
+ )
with tifffile.TiffWriter(fn, imagej=True) as tif:
timg = img_stack[exsl]
@@ -640,22 +704,26 @@ def save_object_stack(folder, basename, img_stack, slices, labels=None):
for chan in range(timg.shape[0]):
tif.save(timg[chan, :, :].squeeze())
-def crop_slice(origshape, w, h=None, x=None, y=None, random_seed=None,
- flipped_axis=False):
+
+def crop_slice(
+ origshape, w, h=None, x=None, y=None, random_seed=None, flipped_axis=False
+):
"""
Returns a slicer to crop the image provided. If x and y position are not
provided, a random slice will be taken.
"""
- warnings.warn('''crop_slice is deprecated and
+ warnings.warn(
+ """crop_slice is deprecated and
will not be supported in future versions.
- ''',
- DeprecationWarning)
+ """,
+ DeprecationWarning,
+ )
if random_seed is not None:
np.random.seed(random_seed)
if h is None:
- h= w
+ h = w
outsize = (w, h)
if flipped_axis:
@@ -663,12 +731,12 @@ def crop_slice(origshape, w, h=None, x=None, y=None, random_seed=None,
x, y = y, x
outslices = list()
- for dmax, dstart, dextend in zip(origshape, (x,y), outsize):
+ for dmax, dstart, dextend in zip(origshape, (x, y), outsize):
if dmax > dextend:
if dstart is None:
- dstart = np.random.randint(0, dmax-dextend)
- dstart = min(dstart, dmax-dextend)
- outslices.append(np.s_[dstart:(dstart+dextend)])
+ dstart = np.random.randint(0, dmax - dextend)
+ dstart = min(dstart, dmax - dextend)
+ outslices.append(np.s_[dstart : (dstart + dextend)])
else:
outslices.append(np.s_[0:dmax])
outslices = tuple(outslices)
diff --git a/imctools/librarybase.py b/imctools/librarybase.py
index a98770a..8b60921 100644
--- a/imctools/librarybase.py
+++ b/imctools/librarybase.py
@@ -1,10 +1,12 @@
import re
from collections import defaultdict
import xml.etree.ElementTree as et
+
"""
Helperfunctions to deal with XML
"""
+
def etree_to_dict(t):
"""
converts an etree xml to a dictionary
@@ -16,23 +18,29 @@ def etree_to_dict(t):
for dc in map(etree_to_dict, children):
for k, v in dc.items():
dd[k].append(v)
- d = {t.tag: {k:v[0] if (len(v) == 1 and ~isinstance(v[0], type(dict()))) else v for k, v in dd.items()}}
+ d = {
+ t.tag: {
+ k: v[0] if (len(v) == 1 and ~isinstance(v[0], type(dict()))) else v
+ for k, v in dd.items()
+ }
+ }
if t.attrib:
- d[t.tag].update(('@' + k, v) for k, v in t.attrib.items())
+ d[t.tag].update(("@" + k, v) for k, v in t.attrib.items())
if t.text:
text = t.text.strip()
if children or t.attrib:
if text:
- d[t.tag]['#text'] = text
+ d[t.tag]["#text"] = text
else:
d[t.tag] = text
return d
+
def strip_ns(tag):
"""
strips the namespace from a string
"""
- return re.sub("^\{.*\}", '', tag)
+ return re.sub("^\{.*\}", "", tag)
def dict_key_apply(iterable, str_fkt):
@@ -50,6 +58,7 @@ def dict_key_apply(iterable, str_fkt):
item = dict_key_apply(item, str_fkt)
return iterable
+
def xml2dict(xml, stripns=True):
dic = etree_to_dict(xml)
if stripns:
diff --git a/imctools/load_multichannel_ome.py b/imctools/load_multichannel_ome.py
index eebc0aa..d3122e8 100644
--- a/imctools/load_multichannel_ome.py
+++ b/imctools/load_multichannel_ome.py
@@ -4,11 +4,12 @@
import os
import sys
-imctool_dir = os.path.join(IJ.getDirectory('plugins'),'imctools')
+imctool_dir = os.path.join(IJ.getDirectory("plugins"), "imctools")
sys.path.append(os.path.realpath(imctool_dir))
import imctools.imagej.library as lib
+
def view_image5d_ome(img, ome_meta):
"""
@@ -17,21 +18,22 @@ def view_image5d_ome(img, ome_meta):
:return:
"""
nchannels = ome_meta.getChannelCount(0)
- channel_names = [ome_meta.getChannelName(0,i) for i in range(nchannels)]
-
- img = lib.get_image5d(imgName=ome_meta.getImageName(0),
- img_stack=img.getStack(),
- channel_names = channel_names)
+ channel_names = [ome_meta.getChannelName(0, i) for i in range(nchannels)]
+ img = lib.get_image5d(
+ imgName=ome_meta.getImageName(0),
+ img_stack=img.getStack(),
+ channel_names=channel_names,
+ )
img.show()
+
def load_and_view(file_name):
(imag, omeMeta) = lib.load_ome_img(file_name)
view_image5d_ome(imag, omeMeta)
-
-op = OpenDialog('Choose multichannel TIFF')
+op = OpenDialog("Choose multichannel TIFF")
file = os.path.join(op.getDirectory(), op.getFileName())
load_and_view(file_name=file)
diff --git a/imctools/open_imc_file.py b/imctools/open_imc_file.py
index e02d66f..10cd095 100644
--- a/imctools/open_imc_file.py
+++ b/imctools/open_imc_file.py
@@ -6,11 +6,13 @@
import os
import sys
-imctool_dir = os.path.join(IJ.getDirectory('plugins'),'imctools')
+
+imctool_dir = os.path.join(IJ.getDirectory("plugins"), "imctools")
sys.path.append(os.path.realpath(imctool_dir))
import imctools.imagej.library as lib
-print('test')
+
+print("test")
import imctools.io.mcdparserbase as mcdparserbase
import imctools.io.txtparserbase as txtparserbase
@@ -21,11 +23,14 @@ def choose_acquisition_dialog(mcd_parser):
:param mcd_parser:
:return:
"""
- gd = gui.GenericDialog('Choose Acquisition')
+ gd = gui.GenericDialog("Choose Acquisition")
ac_ids = mcd_parser.acquisition_ids
- descriptions = [mcd_parser.get_acquisition_description(aid, default='Acquisition '+aid) for aid in ac_ids]
+ descriptions = [
+ mcd_parser.get_acquisition_description(aid, default="Acquisition " + aid)
+ for aid in ac_ids
+ ]
bools = [False for aid in ac_ids]
bools[0] = True
gd.addCheckboxGroup(len(ac_ids), 2, descriptions, bools)
@@ -36,37 +41,35 @@ def choose_acquisition_dialog(mcd_parser):
return []
-print('test2')
-op = OpenDialog('Choose mcd file')
+print("test2")
+op = OpenDialog("Choose mcd file")
fn = os.path.join(op.getDirectory(), op.getFileName())
-if fn[-4:] == '.mcd':
+if fn[-4:] == ".mcd":
with mcdparserbase.McdParserBase(fn) as mcd_parser:
ac_ids = choose_acquisition_dialog(mcd_parser)
if len(ac_ids) > 0:
- print('Load mcd acquisition: %s' %ac_ids)
+ print("Load mcd acquisition: %s" % ac_ids)
imc_acs = [mcd_parser.get_imc_acquisition(aid) for aid in ac_ids]
-if fn[-4:] == '.txt':
- print('Load txt acquisition:')
+if fn[-4:] == ".txt":
+ print("Load txt acquisition:")
imc_acs = [txtparserbase.TxtParserBase(filename=fn).get_imc_acquisition()]
for imc_ac in imc_acs:
- i5d_img = lib.convert_imc_to_image(imc_ac)
-
- i5d_img.show()
- meta = lib.generate_ome_fromimc(imc_ac)
- name = os.path.basename(imc_ac.original_file)
-
- name = name.strip('.mcd').strip('.txt')
+ i5d_img = lib.convert_imc_to_image(imc_ac)
- if imc_ac.origin == 'mcd':
- name = '_'.join([name,imc_ac.image_ID])
- path = os.path.split(imc_ac.original_file)[0]
+ i5d_img.show()
+ meta = lib.generate_ome_fromimc(imc_ac)
+ name = os.path.basename(imc_ac.original_file)
- fname = os.path.join(path, name+'.ome.tiff')
- if not(os.path.exists(fname)):
- lib.save_ome_tiff(fname, i5d_img, meta)
+ name = name.strip(".mcd").strip(".txt")
- del imc_ac
+ if imc_ac.origin == "mcd":
+ name = "_".join([name, imc_ac.image_ID])
+ path = os.path.split(imc_ac.original_file)[0]
+ fname = os.path.join(path, name + ".ome.tiff")
+ if not (os.path.exists(fname)):
+ lib.save_ome_tiff(fname, i5d_img, meta)
+ del imc_ac
diff --git a/imctools/scripts/__init__.py b/imctools/scripts/__init__.py
index 3fa4a2c..fc41f58 100644
--- a/imctools/scripts/__init__.py
+++ b/imctools/scripts/__init__.py
@@ -1,2 +1,10 @@
-__all__=['cropobjects', 'croprandomsection', 'generatedistancetospheres', 'imc2tiff', 'mcd2tiff', 'ome2micat',
- 'ometiff2analysis', 'resizeimage']
\ No newline at end of file
+__all__ = [
+ "cropobjects",
+ "croprandomsection",
+ "generatedistancetospheres",
+ "imc2tiff",
+ "mcd2tiff",
+ "ome2micat",
+ "ometiff2analysis",
+ "resizeimage",
+]
diff --git a/imctools/scripts/convertfolder2imcfolder.py b/imctools/scripts/convertfolder2imcfolder.py
index e8ee7f6..2628688 100644
--- a/imctools/scripts/convertfolder2imcfolder.py
+++ b/imctools/scripts/convertfolder2imcfolder.py
@@ -1,4 +1,6 @@
#! /usr/bin/env python
+import warnings
+
from imctools.io.mcdparser import McdParser
from imctools.io.txtparser import TxtParser
from imctools.external import temporarydirectory
@@ -7,10 +9,11 @@
import zipfile
import argparse
import logging
-TXT_FILENDING = '.txt'
-MCD_FILENDING = '.mcd'
-ZIP_FILENDING = '.zip'
-SCHEMA_FILENDING = '.schema'
+
+TXT_FILENDING = ".txt"
+MCD_FILENDING = ".mcd"
+ZIP_FILENDING = ".zip"
+SCHEMA_FILENDING = ".schema"
def convert_folder2imcfolder(fol, out_folder, dozip=True):
"""
@@ -18,6 +21,10 @@ def convert_folder2imcfolder(fol, out_folder, dozip=True):
(mcd and tiff)
to a zipfolder containing standardized names files.
"""
+ warnings.warn(
+ "imctools 1.x is deprecated, please migrate to version 2.x", DeprecationWarning
+ )
+
if fol.endswith(ZIP_FILENDING):
tmpdir = temporarydirectory.TemporaryDirectory()
with zipfile.ZipFile(fol, allowZip64=True) as zipf:
@@ -29,10 +36,13 @@ def convert_folder2imcfolder(fol, out_folder, dozip=True):
istmp = False
try:
- files = [os.path.join(root, fn) for root, dirs, files in os.walk(in_fol) for fn in files]
- mcd_files = [f for f in files
- if f.endswith(MCD_FILENDING)]
- assert(len(mcd_files) == 1)
+ files = [
+ os.path.join(root, fn)
+ for root, dirs, files in os.walk(in_fol)
+ for fn in files
+ ]
+ mcd_files = [f for f in files if f.endswith(MCD_FILENDING)]
+ assert len(mcd_files) == 1
schema_files = [f for f in files if f.endswith(SCHEMA_FILENDING)]
if len(schema_files) > 0:
schema_file = schema_files[0]
@@ -42,27 +52,24 @@ def convert_folder2imcfolder(fol, out_folder, dozip=True):
mcd = McdParser(mcd_files[0])
except:
if schema_file is not None:
- logging.exception('Mcd File corrupted, trying to rescue with schema file')
+ logging.exception(
+ "Mcd File corrupted, trying to rescue with schema file"
+ )
mcd = McdParser(mcd_files[0], metafilename=schema_file)
else:
raise
mcd_acs = mcd.get_all_imcacquistions()
- txt_acids = {_txtfn_to_ac(f): f
- for f in files if f.endswith(TXT_FILENDING)}
+ txt_acids = {_txtfn_to_ac(f): f for f in files if f.endswith(TXT_FILENDING)}
mcd_acids = set(m.image_ID for m in mcd_acs)
txtonly_acs = set(txt_acids.keys()).difference(mcd_acids)
for txta in txtonly_acs:
- print('Using TXT file for acquisition: '+txta)
+ print("Using TXT file for acquisition: " + txta)
try:
- mcd_acs.append(
- TxtParser(
- txt_acids[txta]).get_imc_acquisition())
+ mcd_acs.append(TxtParser(txt_acids[txta]).get_imc_acquisition())
except:
- print('TXT file was also corrupted.')
- imc_fol = ImcFolderWriter(out_folder,
- mcddata=mcd,
- imcacquisitions=mcd_acs)
+ print("TXT file was also corrupted.")
+ imc_fol = ImcFolderWriter(out_folder, mcddata=mcd, imcacquisitions=mcd_acs)
imc_fol.write_imc_folder(zipfolder=dozip)
if istmp:
tmpdir.cleanup()
@@ -74,24 +81,31 @@ def convert_folder2imcfolder(fol, out_folder, dozip=True):
def _txtfn_to_ac(fn):
return TxtParser._txtfn_to_ac(fn)
+
if __name__ == "__main__":
parser = argparse.ArgumentParser(
- description='Convert a folder or zip of IMC rawdat'+
- ' (.mcd+.txt) into an IMC folder.',
- prog='fol2imcfol',
- usage='%(prog)s folder_path [options]')
- parser.add_argument('folder_path', metavar='folder_path',
- type=str,
- help='The path to the folder/zip archive containing the IMC rawdata')
- parser.add_argument('--out_folder', metavar='out_folder',
- type=str,
- default='',
- help='Path to the output folder')
+ description="Convert a folder or zip of IMC rawdat"
+ + " (.mcd+.txt) into an IMC folder.",
+ prog="fol2imcfol",
+ usage="%(prog)s folder_path [options]",
+ )
+ parser.add_argument(
+ "folder_path",
+ metavar="folder_path",
+ type=str,
+ help="The path to the folder/zip archive containing the IMC rawdata",
+ )
+ parser.add_argument(
+ "--out_folder",
+ metavar="out_folder",
+ type=str,
+ default="",
+ help="Path to the output folder",
+ )
args = parser.parse_args()
in_fol = args.folder_path
out_fol = args.out_folder
- if out_fol == '':
+ if out_fol == "":
out_fol = os.path.split(in_fol)[0]
convert_folder2imcfolder(in_fol, out_fol)
-
diff --git a/imctools/scripts/cropobjects.py b/imctools/scripts/cropobjects.py
index 3dffad5..52b84b4 100644
--- a/imctools/scripts/cropobjects.py
+++ b/imctools/scripts/cropobjects.py
@@ -7,6 +7,7 @@
import os
import numpy as np
+
def crop_objects(fn_stack, fn_label, outfolder, basename, extend, order=None):
"""
@@ -18,74 +19,108 @@ def crop_objects(fn_stack, fn_label, outfolder, basename, extend, order=None):
:param extend:
:return:
"""
- warnings.warn('''crop_objects is deprecated and will not be supported in future versions.\n
+ warnings.warn(
+ """crop_objects is deprecated and will not be supported in future versions.\n
Please use the `SaveObjectCrops` module from Bodenmillergroup/ImcPluginsCP
- in CellProfiler!''',
- DeprecationWarning)
+ in CellProfiler!""",
+ DeprecationWarning,
+ )
if order is None:
- order = 'cxy'
+ order = "cxy"
with tifffile.TiffFile(fn_label) as tif:
labelmask = tif.asarray()
-
with tifffile.TiffFile(fn_stack) as tif:
stack = tif.asarray()
- if order == 'xyc':
+ if order == "xyc":
stack = np.rollaxis(stack, 2, 0)
- if np.any(labelmask >0):
+ if np.any(labelmask > 0):
if len(stack.shape) == 2:
- stack = stack.reshape([1]+list(stack.shape))
+ stack = stack.reshape([1] + list(stack.shape))
slices = ndi.find_objects(labelmask)
- slices, labels = zip(*[(s, label) for label, s in enumerate(slices) if s is not None])
+ slices, labels = zip(
+ *[(s, label) for label, s in enumerate(slices) if s is not None]
+ )
print(stack.shape)
print(labelmask.shape)
- ext_slices = [lib.extend_slice_touple(sl, extend, [stack.shape[1], stack.shape[2]]) for sl in slices]
+ ext_slices = [
+ lib.extend_slice_touple(sl, extend, [stack.shape[1], stack.shape[2]])
+ for sl in slices
+ ]
lib.save_object_stack(outfolder, basename, stack, ext_slices, labels)
else:
- print('No object in image:' + fn_stack)
-
+ print("No object in image:" + fn_stack)
+
+
if __name__ == "__main__":
# Setup the command line arguments
parser = argparse.ArgumentParser(
- description='Crops objects out of images.', prog='crop_objects')
-
- parser.add_argument('image_filename', type=str,
- help='The path to the image filename. If the image is a stack it needs to be CXY ordered')
-
- parser.add_argument('object_filename', type=str, default=None,
- help='Filename to the tiff that contains the object masks.')
-
- parser.add_argument('--out_folder', type=str, default=None,
- help='Folder to save the images in. Default a subfolder with the basename object_filename in the image_filename folder.')
-
- parser.add_argument('--extend', type=int, default=0,
- help='How many pixels to extend around the object.')
-
- parser.add_argument('--basename', type=str, default=None,
- help='Basename for the output image. Default: image_filename')
-
- parser.add_argument('--postfix', type=str, default=None,
- help='Postfix to append to the basename.'
- )
+ description="Crops objects out of images.", prog="crop_objects"
+ )
+
+ parser.add_argument(
+ "image_filename",
+ type=str,
+ help="The path to the image filename. If the image is a stack it needs to be CXY ordered",
+ )
+
+ parser.add_argument(
+ "object_filename",
+ type=str,
+ default=None,
+ help="Filename to the tiff that contains the object masks.",
+ )
+
+ parser.add_argument(
+ "--out_folder",
+ type=str,
+ default=None,
+ help="Folder to save the images in. Default a subfolder with the basename object_filename in the image_filename folder.",
+ )
+
+ parser.add_argument(
+ "--extend",
+ type=int,
+ default=0,
+ help="How many pixels to extend around the object.",
+ )
+
+ parser.add_argument(
+ "--basename",
+ type=str,
+ default=None,
+ help="Basename for the output image. Default: image_filename",
+ )
+
+ parser.add_argument(
+ "--postfix", type=str, default=None, help="Postfix to append to the basename."
+ )
args = parser.parse_args()
if args.basename is None:
- args.basename = os.path.split(args.image_filename)[1].strip('.tif').strip('.tiff')
+ args.basename = (
+ os.path.split(args.image_filename)[1].strip(".tif").strip(".tiff")
+ )
if args.postfix is not None:
args.basename = args.basename + args.postfix
if args.out_folder is None:
args.out_folder = os.path.split(args.image_filename)[0]
- tmpname = os.path.split(args.object_filename)[1].strip('.tif').strip('.tiff')
+ tmpname = os.path.split(args.object_filename)[1].strip(".tif").strip(".tiff")
args.out_folder = os.path.join(args.out_folder, tmpname)
- if not(os.path.exists(args.out_folder)):
+ if not (os.path.exists(args.out_folder)):
os.mkdir(args.out_folder)
- crop_objects(args.image_filename, args.object_filename, args.out_folder,
- args.basename, args.extend)
+ crop_objects(
+ args.image_filename,
+ args.object_filename,
+ args.out_folder,
+ args.basename,
+ args.extend,
+ )
diff --git a/imctools/scripts/croprandomsection.py b/imctools/scripts/croprandomsection.py
index 188c254..c7e1421 100644
--- a/imctools/scripts/croprandomsection.py
+++ b/imctools/scripts/croprandomsection.py
@@ -19,18 +19,20 @@ def crop_random_section(fn_stack, outfolder, basename, size, random_seed=None):
:param extend:
:return:
"""
- warnings.warn('''crop_random_section is deprecated and
+ warnings.warn(
+ """crop_random_section is deprecated and
will not be supported in future versions.
Please use the `Crop bb` module from
Bodenmillergroup/ImcPluginsCP
- in CellProfiler!''',
- DeprecationWarning)
+ in CellProfiler!""",
+ DeprecationWarning,
+ )
with tifffile.TiffFile(fn_stack) as tif:
stack = tif.asarray()
if len(stack.shape) == 2:
- stack = stack.reshape([1]+list(stack.shape))
+ stack = stack.reshape([1] + list(stack.shape))
slice = []
xmax = stack.shape[1]
@@ -38,15 +40,15 @@ def crop_random_section(fn_stack, outfolder, basename, size, random_seed=None):
if random_seed is not None:
np.random.seed(random_seed)
if xmax > size:
- x_start = np.random.randint(0,xmax-size)
- slice.append(np.s_[x_start:(x_start+size)])
+ x_start = np.random.randint(0, xmax - size)
+ slice.append(np.s_[x_start : (x_start + size)])
else:
slice.append(np.s_[0:xmax])
ymax = stack.shape[2]
if ymax > size:
- x_start = np.random.randint(0,ymax-size)
- slice.append(np.s_[x_start:(x_start+size)])
+ x_start = np.random.randint(0, ymax - size)
+ slice.append(np.s_[x_start : (x_start + size)])
else:
slice.append(np.s_[0:ymax])
@@ -54,49 +56,70 @@ def crop_random_section(fn_stack, outfolder, basename, size, random_seed=None):
lib.save_object_stack(outfolder, basename, stack, [slice])
+
if __name__ == "__main__":
# Setup the command line arguments
parser = argparse.ArgumentParser(
- description='Crops a random section out of an image.', prog='croprandomsection')
-
- parser.add_argument('image_filename', type=str,
- help='The path to the image filename. If the image is a stack it needs to be CXY ordered')
-
- parser.add_argument('size', type=int, default=100,
- help='How many pixels should the side of the square of the cutout be. If the image is smaller')
-
- parser.add_argument('--out_folder', type=str, default=None,
- help='Folder to save the images in. Default a subfolder with the basename image_filename in the image_filename folder.')
-
- parser.add_argument('--basename', type=str, default=None,
- help='Basename for the output image. Default: image_filename')
-
- parser.add_argument('--postfix', type=str, default=None,
- help='Postfix to append to the basename.'
- )
-
- parser.add_argument('--randomseed', type=float, default=None,
- help='Random seed. Not set per default.'
- )
+ description="Crops a random section out of an image.", prog="croprandomsection"
+ )
+
+ parser.add_argument(
+ "image_filename",
+ type=str,
+ help="The path to the image filename. If the image is a stack it needs to be CXY ordered",
+ )
+
+ parser.add_argument(
+ "size",
+ type=int,
+ default=100,
+ help="How many pixels should the side of the square of the cutout be. If the image is smaller",
+ )
+
+ parser.add_argument(
+ "--out_folder",
+ type=str,
+ default=None,
+ help="Folder to save the images in. Default a subfolder with the basename image_filename in the image_filename folder.",
+ )
+
+ parser.add_argument(
+ "--basename",
+ type=str,
+ default=None,
+ help="Basename for the output image. Default: image_filename",
+ )
+
+ parser.add_argument(
+ "--postfix", type=str, default=None, help="Postfix to append to the basename."
+ )
+
+ parser.add_argument(
+ "--randomseed",
+ type=float,
+ default=None,
+ help="Random seed. Not set per default.",
+ )
args = parser.parse_args()
if args.basename is None:
- args.basename = os.path.split(args.image_filename)[1].strip('.tif').strip('.tiff')
+ args.basename = (
+ os.path.split(args.image_filename)[1].strip(".tif").strip(".tiff")
+ )
if args.postfix is not None:
args.basename = args.basename + args.postfix
if args.out_folder is None:
args.out_folder = os.path.split(args.image_filename)[0]
- tmpname = os.path.split(args.image_filename)[1].strip('.tif').strip('.tiff')
+ tmpname = os.path.split(args.image_filename)[1].strip(".tif").strip(".tiff")
args.out_folder = os.path.join(args.out_folder, tmpname)
- if not(os.path.exists(args.out_folder)):
+ if not (os.path.exists(args.out_folder)):
os.mkdir(args.out_folder)
if args.randomseed is not None:
np.random.seed(args.randomseed)
- crop_random_section(args.image_filename, args.out_folder,
- args.basename, args.size)
+ crop_random_section(args.image_filename, args.out_folder, args.basename, args.size)
diff --git a/imctools/scripts/cropsection.py b/imctools/scripts/cropsection.py
index bcd538d..267bf34 100644
--- a/imctools/scripts/cropsection.py
+++ b/imctools/scripts/cropsection.py
@@ -18,66 +18,87 @@ def crop_section(fn_stack, outfolder, slice, basename=None):
:param slice:
:return:
"""
- warnings.warn('''crop_section is deprecated and
+ warnings.warn(
+ """crop_section is deprecated and
will not be supported in future versions.
Please use the `Crop bb` module from
Bodenmillergroup/ImcPluginsCP
- in CellProfiler!''',
- DeprecationWarning)
+ in CellProfiler!""",
+ DeprecationWarning,
+ )
if basename is None:
- basename = os.path.split(fn_stack)[1].strip('.tif').strip('.tiff')
+ basename = os.path.split(fn_stack)[1].strip(".tif").strip(".tiff")
with tifffile.TiffFile(fn_stack) as tif:
stack = tif.asarray()
if len(stack.shape) == 2:
- stack = stack.reshape([1]+list(stack.shape))
+ stack = stack.reshape([1] + list(stack.shape))
slice = tuple(slice)
lib.save_object_stack(outfolder, basename, stack, [slice])
+
if __name__ == "__main__":
# Setup the command line arguments
parser = argparse.ArgumentParser(
- description='Crops a section out of an image.\n'+
- 'The coordinates of the section have to be specified as the coordinates of the upper left'+
- 'corner (x0, y0) as well as the width and height (w, h) of the section in pixels.', prog='cropsection')
-
- parser.add_argument('image_filename', type=str,
- help='The path to the image filename. If the image is a stack it needs to be CXY ordered')
-
- parser.add_argument('section', type=int, nargs=4,
- help='Specify the section as 4 integers: x0 y0 w h')
-
- parser.add_argument('--out_folder', type=str, default=None,
- help='Folder to save the images in. Default a subfolder with the basename image_filename in the image_filename folder.')
-
- parser.add_argument('--basename', type=str, default=None,
- help='Basename for the output image. Default: image_filename')
-
- parser.add_argument('--postfix', type=str, default=None,
- help='Postfix to append to the basename.'
- )
+ description="Crops a section out of an image.\n"
+ + "The coordinates of the section have to be specified as the coordinates of the upper left"
+ + "corner (x0, y0) as well as the width and height (w, h) of the section in pixels.",
+ prog="cropsection",
+ )
+
+ parser.add_argument(
+ "image_filename",
+ type=str,
+ help="The path to the image filename. If the image is a stack it needs to be CXY ordered",
+ )
+
+ parser.add_argument(
+ "section",
+ type=int,
+ nargs=4,
+ help="Specify the section as 4 integers: x0 y0 w h",
+ )
+
+ parser.add_argument(
+ "--out_folder",
+ type=str,
+ default=None,
+ help="Folder to save the images in. Default a subfolder with the basename image_filename in the image_filename folder.",
+ )
+
+ parser.add_argument(
+ "--basename",
+ type=str,
+ default=None,
+ help="Basename for the output image. Default: image_filename",
+ )
+
+ parser.add_argument(
+ "--postfix", type=str, default=None, help="Postfix to append to the basename."
+ )
args = parser.parse_args()
if args.basename is None:
- args.basename = os.path.split(args.image_filename)[1].strip('.tif').strip('.tiff')
+ args.basename = (
+ os.path.split(args.image_filename)[1].strip(".tif").strip(".tiff")
+ )
if args.postfix is not None:
args.basename = args.basename + args.postfix
if args.out_folder is None:
args.out_folder = os.path.split(args.image_filename)[0]
- tmpname = os.path.split(args.image_filename)[1].strip('.tif').strip('.tiff')
+ tmpname = os.path.split(args.image_filename)[1].strip(".tif").strip(".tiff")
args.out_folder = os.path.join(args.out_folder, tmpname)
- if not(os.path.exists(args.out_folder)):
+ if not (os.path.exists(args.out_folder)):
os.mkdir(args.out_folder)
if args.randomseed is not None:
np.random.seed(args.randomseed)
- crop_section(args.image_filename, args.out_folder,
- args.section, args.basename)
+ crop_section(args.image_filename, args.out_folder, args.section, args.basename)
diff --git a/imctools/scripts/exportacquisitioncsv.py b/imctools/scripts/exportacquisitioncsv.py
index c931656..0df0205 100644
--- a/imctools/scripts/exportacquisitioncsv.py
+++ b/imctools/scripts/exportacquisitioncsv.py
@@ -1,53 +1,73 @@
#!/usr/bin/env python
import argparse
import os
+import warnings
+
import pandas as pd
import imctools.io.mcdxmlparser as mcdmeta
-SUFFIX_ACMETA = '_' + mcdmeta.ACQUISITION + mcdmeta.META_CSV
+SUFFIX_ACMETA = "_" + mcdmeta.ACQUISITION + mcdmeta.META_CSV
COL_MCD_ID = mcdmeta.ID
COL_ACID = mcdmeta.ACQUISITIONID
-COL_ACSESSION = 'AcSession'
-SUF_CSV = '.csv'
-AC_META = 'acquisition_metadata'
+COL_ACSESSION = "AcSession"
+SUF_CSV = ".csv"
+AC_META = "acquisition_metadata"
"""
Reads all the acquisition metadata from the ome folders and concatenates them
to a csv that contains all the metadata.
"""
+
def _read_and_concat(fol_ome, suffix, idname):
ac_names = os.listdir(fol_ome)
- dat = pd.concat([pd.read_csv(os.path.join(fol_ome, a, a+suffix)) for a in ac_names],
- keys=ac_names, names=[COL_ACSESSION])
+ dat = pd.concat(
+ [pd.read_csv(os.path.join(fol_ome, a, a + suffix)) for a in ac_names],
+ keys=ac_names,
+ names=[COL_ACSESSION],
+ )
dat = dat.reset_index(COL_ACSESSION, drop=False)
dat = dat.rename(columns={COL_MCD_ID: idname})
return dat
+
def read_acmeta(fol_ome):
dat_acmeta = _read_and_concat(fol_ome, SUFFIX_ACMETA, COL_ACID)
return dat_acmeta
+
def export_acquisition_csv(fol_ome, fol_out, outname=AC_META):
+ warnings.warn(
+ "imctools 1.x is deprecated, please migrate to version 2.x", DeprecationWarning
+ )
dat_meta = read_acmeta(fol_ome)
- dat_meta.to_csv(os.path.join(fol_out, outname+SUF_CSV), index=False)
+ dat_meta.to_csv(os.path.join(fol_out, outname + SUF_CSV), index=False)
if __name__ == "__main__":
# Setup the command line arguments
parser = argparse.ArgumentParser(
- description='Generates a metadatacsv for all acquisitions', prog='exportacquisitioncsv')
+ description="Generates a metadatacsv for all acquisitions",
+ prog="exportacquisitioncsv",
+ )
- parser.add_argument('fol_ome', type=str,
- help='The path to the folders containing the ome tiffs.')
+ parser.add_argument(
+ "fol_ome", type=str, help="The path to the folders containing the ome tiffs."
+ )
- parser.add_argument('out_folder', type=str,
- help='Folder where the metadata csv should be stored in.')
+ parser.add_argument(
+ "out_folder",
+ type=str,
+ help="Folder where the metadata csv should be stored in.",
+ )
- parser.add_argument('--outname', type=str, default=AC_META,
- help='Filename of the acquisition metadata csv')
+ parser.add_argument(
+ "--outname",
+ type=str,
+ default=AC_META,
+ help="Filename of the acquisition metadata csv",
+ )
args = parser.parse_args()
- export_acquisition_csv(args.fol_ome, args.out_folder,
- args.outname)
+ export_acquisition_csv(args.fol_ome, args.out_folder, args.outname)
diff --git a/imctools/scripts/generatedistancetospheres.py b/imctools/scripts/generatedistancetospheres.py
index b609153..0124d8e 100644
--- a/imctools/scripts/generatedistancetospheres.py
+++ b/imctools/scripts/generatedistancetospheres.py
@@ -6,7 +6,6 @@
import warnings
-
def generate_distanceto_spheres(fn_label, cur_label, out_file, bg_label=0):
"""
@@ -18,22 +17,24 @@ def generate_distanceto_spheres(fn_label, cur_label, out_file, bg_label=0):
:param extend:
:return:
"""
- warnings.warn('''generate_distanceto_spheres is deprecated and
+ warnings.warn(
+ """generate_distanceto_spheres is deprecated and
will not be supported in future versions.
Please use the `MaskToBinstack` together with
`Transform Binary`
module from Bodenmillergroup/ImcPluginsCP
- in CellProfiler!''',
- DeprecationWarning)
+ in CellProfiler!""",
+ DeprecationWarning,
+ )
with tifffile.TiffFile(fn_label) as tif:
labels = tif.asarray()
- is_cur = (labels != cur_label)
- is_bg = (labels != bg_label)
+ is_cur = labels != cur_label
+ is_bg = labels != bg_label
is_other = (is_bg == False) | (is_cur == False)
- with tifffile.TiffWriter(out_file+'.tif', imagej=True) as tif:
+ with tifffile.TiffWriter(out_file + ".tif", imagej=True) as tif:
tif.save(lib.distance_transform_wrapper(is_cur).astype(np.float32))
tif.save(lib.distance_transform_wrapper(is_bg).astype(np.float32))
tif.save(lib.distance_transform_wrapper(is_other).astype(np.float32))
@@ -41,7 +42,9 @@ def generate_distanceto_spheres(fn_label, cur_label, out_file, bg_label=0):
return 1
-def generate_distanceto_binary(fns_binary, out_file, allinverted=False, addinverted=False):
+def generate_distanceto_binary(
+ fns_binary, out_file, allinverted=False, addinverted=False
+):
"""
:param fn_stack:
@@ -52,12 +55,14 @@ def generate_distanceto_binary(fns_binary, out_file, allinverted=False, addinver
:param extend:
:return:
"""
- warnings.warn('''generate_distanceto_binary is deprecated and
+ warnings.warn(
+ """generate_distanceto_binary is deprecated and
will not be supported in future versions.
Please use the `Transform Binary` module from
Bodenmillergroup/ImcPluginsCP
- in CellProfiler!''',
- DeprecationWarning)
+ in CellProfiler!""",
+ DeprecationWarning,
+ )
imgs = list()
with tifffile.TiffWriter(out_file, imagej=True) as outtif:
@@ -70,10 +75,13 @@ def generate_distanceto_binary(fns_binary, out_file, allinverted=False, addinver
img = img > 0
outtif.save(lib.distance_transform_wrapper(img).astype(np.float32))
if addinverted:
- outtif.save(lib.distance_transform_wrapper(img == False).astype(np.float32))
+ outtif.save(
+ lib.distance_transform_wrapper(img == False).astype(np.float32)
+ )
return 1
+
def generate_binary(fn_label, cur_label, out_file, bg_label=0):
"""
@@ -93,7 +101,7 @@ def generate_binary(fn_label, cur_label, out_file, bg_label=0):
is_bg = labels == bg_label
is_other = (is_bg == False) & (is_cur == False)
- with tifffile.TiffWriter(out_file+'.tif', imagej=True) as tif:
+ with tifffile.TiffWriter(out_file + ".tif", imagej=True) as tif:
tif.save(is_cur.astype(np.uint8))
tif.save(is_bg.astype(np.uint8))
tif.save(is_other.astype(np.uint8))
diff --git a/imctools/scripts/imc2tiff.py b/imctools/scripts/imc2tiff.py
index ca1c58c..683d9ce 100755
--- a/imctools/scripts/imc2tiff.py
+++ b/imctools/scripts/imc2tiff.py
@@ -1,4 +1,6 @@
#! /usr/bin/env python
+import warnings
+
from imctools.io import mcdparser
from imctools.io import txtparser
import argparse
@@ -7,19 +9,26 @@
from imctools.external import temporarydirectory
import zipfile
-TXT_FILENDING = '.txt'
-MCD_FILENDING = '.mcd'
-TIFF_FILENDING = '.tiff'
-OME_FILENDING = '.ome.tiff'
-ZIP_FILENDING = '.zip'
+TXT_FILENDING = ".txt"
+MCD_FILENDING = ".mcd"
+TIFF_FILENDING = ".tiff"
+OME_FILENDING = ".ome.tiff"
+ZIP_FILENDING = ".zip"
IMC_FILENDINGS = (TXT_FILENDING, MCD_FILENDING)
-def save_imc_to_tiff(imc_acquisition, acquisition='all', tifftype='ome',
- compression=0, outname=None, outpath=None,
- zip_filetype=None, verbose=False):
- """
+def save_imc_to_tiff(
+ imc_acquisition,
+ acquisition="all",
+ tifftype="ome",
+ compression=0,
+ outname=None,
+ outpath=None,
+ zip_filetype=None,
+ verbose=False,
+):
+ """
:param imc_acquisition:
:param acquisition:
:param tifftype:
@@ -29,15 +38,18 @@ def save_imc_to_tiff(imc_acquisition, acquisition='all', tifftype='ome',
:param verbose:
:return:
"""
+ warnings.warn(
+ "imctools 1.x is deprecated, please migrate to version 2.x", DeprecationWarning
+ )
if verbose:
- print('Load filename %s' %imc_acquisition)
+ print("Load filename %s" % imc_acquisition)
if outpath is None:
outpath = os.path.split(imc_acquisition)[0]
if zip_filetype is None:
- zip_filetype = ''
+ zip_filetype = ""
if imc_acquisition.endswith(IMC_FILENDINGS):
if outname is None:
@@ -45,17 +57,18 @@ def save_imc_to_tiff(imc_acquisition, acquisition='all', tifftype='ome',
for end in IMC_FILENDINGS:
outname = outname.rstrip(end)
if imc_acquisition.endswith(MCD_FILENDING):
- acquisition_generator = _get_mcd_acquisition(imc_acquisition,
- acquisition=acquisition,
- verbose=verbose)
+ acquisition_generator = _get_mcd_acquisition(
+ imc_acquisition, acquisition=acquisition, verbose=verbose
+ )
elif imc_acquisition.endswith(TXT_FILENDING):
acquisition_generator = _get_txt_acquisition(
- imc_acquisition, acquisition_name='0', verbose=verbose)
+ imc_acquisition, acquisition_name="0", verbose=verbose
+ )
for aid, imc_img in acquisition_generator:
- cur_outname = outname+'_a'+aid
+ cur_outname = outname + "_a" + aid
- if tifftype == 'ome':
+ if tifftype == "ome":
cur_outname += OME_FILENDING
else:
cur_outname += TIFF_FILENDING
@@ -63,24 +76,29 @@ def save_imc_to_tiff(imc_acquisition, acquisition='all', tifftype='ome',
cur_outname = os.path.join(outpath, cur_outname)
if verbose:
- print('Save %s as %s' %(aid,cur_outname))
+ print("Save %s as %s" % (aid, cur_outname))
iw = imc_img.get_image_writer(cur_outname)
iw.save_image(mode=tifftype, compression=compression)
elif imc_acquisition.endswith(ZIP_FILENDING):
- convert_imczip2tiff(imc_acquisition, outpath, common_filepart=zip_filetype,
- acquisition=acquisition,
- tifftype=tifftype, compression=compression,
- outname=outname, verbose=False)
+ convert_imczip2tiff(
+ imc_acquisition,
+ outpath,
+ common_filepart=zip_filetype,
+ acquisition=acquisition,
+ tifftype=tifftype,
+ compression=compression,
+ outname=outname,
+ verbose=False,
+ )
else:
- raise NameError('%s is not of type .mcd, .txt or .zip' %imc_acquisition)
+ raise NameError("%s is not of type .mcd, .txt or .zip" % imc_acquisition)
if verbose:
- print('Finished!')
+ print("Finished!")
-def convert_imcfolders2tiff(folders, output_folder, common_filepart=None,
- **kwargs):
+def convert_imcfolders2tiff(folders, output_folder, common_filepart=None, **kwargs):
"""
Converts a list of folders into ome.tiffs
:param folder:
@@ -91,41 +109,44 @@ def convert_imcfolders2tiff(folders, output_folder, common_filepart=None,
failed_images = list()
if common_filepart is None:
- common_filepart = ''
+ common_filepart = ""
for fol in folders:
- for fn in glob.glob(os.path.join(fol, '*')):
- if (common_filepart in os.path.basename(fn)) & (fn.endswith(IMC_FILENDINGS) |
- fn.endswith(ZIP_FILENDING)):
+ for fn in glob.glob(os.path.join(fol, "*")):
+ if (common_filepart in os.path.basename(fn)) & (
+ fn.endswith(IMC_FILENDINGS) | fn.endswith(ZIP_FILENDING)
+ ):
txtname = fn
try:
- save_imc_to_tiff(txtname,
- outpath=output_folder, **kwargs)
+ save_imc_to_tiff(txtname, outpath=output_folder, **kwargs)
except:
failed_images.append(txtname)
if len(failed_images) > 0:
- print('Failed images:\n')
+ print("Failed images:\n")
print(failed_images)
+
def convert_imczip2tiff(zipfn, output_folder, common_filepart=None, **kwargs):
"""
Converts a zip archive containing IMC files to tiff
"""
if common_filepart is None:
- common_filepart = ''
+ common_filepart = ""
with temporarydirectory.TemporaryDirectory() as tempdir:
with zipfile.ZipFile(zipfn, allowZip64=True) as zipf:
for fn in zipf.namelist():
if (common_filepart in fn) & fn.endswith(IMC_FILENDINGS):
zipf.extract(fn, tempdir)
- convert_imcfolders2tiff([tempdir], output_folder,
- common_filepart=common_filepart, **kwargs)
+ convert_imcfolders2tiff(
+ [tempdir], output_folder, common_filepart=common_filepart, **kwargs
+ )
-def _get_mcd_acquisition(mcd_acquisition, acquisition='all', verbose=False,
- filehandle=None):
+def _get_mcd_acquisition(
+ mcd_acquisition, acquisition="all", verbose=False, filehandle=None
+):
"""
A generator the returns the acquisitions
:param mcd_acquisition:
@@ -136,15 +157,15 @@ def _get_mcd_acquisition(mcd_acquisition, acquisition='all', verbose=False,
with mcdparser.McdParser(mcd_acquisition, filehandle) as mcd:
n_ac = mcd.n_acquisitions
if verbose:
- print('containing %i acquisitions:' % n_ac)
+ print("containing %i acquisitions:" % n_ac)
ac_ids = mcd.acquisition_ids
if verbose:
for aid in ac_ids:
- print('%s \n' % aid)
- print('Print acquisition: %s' % acquisition)
+ print("%s \n" % aid)
+ print("Print acquisition: %s" % acquisition)
- if acquisition == 'all':
+ if acquisition == "all":
acquisitions = ac_ids
else:
acquisitions = [acquisition]
@@ -155,8 +176,9 @@ def _get_mcd_acquisition(mcd_acquisition, acquisition='all', verbose=False,
yield (acquisition, imc_img)
-def _get_txt_acquisition(txt_acquisition, acquisition_name=None,
- verbose=False, filehandle=None):
+def _get_txt_acquisition(
+ txt_acquisition, acquisition_name=None, verbose=False, filehandle=None
+):
"""
A generator the returns the acquisitions
:param mcd_acquisition:
@@ -165,45 +187,62 @@ def _get_txt_acquisition(txt_acquisition, acquisition_name=None,
:return:
"""
if acquisition_name is None:
- acquisition_name='0'
+ acquisition_name = "0"
txt = txtparser.TxtParser(txt_acquisition, filehandle)
if verbose:
- print('containing 1 acquisition')
+ print("containing 1 acquisition")
imc_img = txt.get_imc_acquisition()
acquisition = acquisition_name
yield (acquisition, imc_img)
-
if __name__ == "__main__":
# Setup the command line arguments
- parser = argparse.ArgumentParser(description='Convert an IMC mcd or txt image to ImageJ Tiffs', prog='imc2tiff',
- usage='%(prog)s imc_filename [options]')
- parser.add_argument('imc_filename', metavar='mcd_filename', type=str,
- help='The path to the mcd or txt IMC file to be converted')
- parser.add_argument('--acquisition', metavar='acquisition', type=str, default='all',
- help='all or acquisition ID: acquisitions to write as tiff.')
-
- parser.add_argument('--tifftype', type=str, default='ome',
- help='ome or imagej: Write the files either with ome metadata or imagej compatible mode.'
- )
- parser.add_argument('--compression', type=int, default=0,
- help='0-9: Tiff compression level')
-
- parser.add_argument('--outname', type=str, default=None,
- help='the name of the output file.')
- parser.add_argument('--outpath',type=str, default=None,
- help='the output path.')
+ parser = argparse.ArgumentParser(
+ description="Convert an IMC mcd or txt image to ImageJ Tiffs",
+ prog="imc2tiff",
+ usage="%(prog)s imc_filename [options]",
+ )
+ parser.add_argument(
+ "imc_filename",
+ metavar="mcd_filename",
+ type=str,
+ help="The path to the mcd or txt IMC file to be converted",
+ )
+ parser.add_argument(
+ "--acquisition",
+ metavar="acquisition",
+ type=str,
+ default="all",
+ help="all or acquisition ID: acquisitions to write as tiff.",
+ )
+
+ parser.add_argument(
+ "--tifftype",
+ type=str,
+ default="ome",
+ help="ome or imagej: Write the files either with ome metadata or imagej compatible mode.",
+ )
+ parser.add_argument(
+ "--compression", type=int, default=0, help="0-9: Tiff compression level"
+ )
+
+ parser.add_argument(
+ "--outname", type=str, default=None, help="the name of the output file."
+ )
+ parser.add_argument("--outpath", type=str, default=None, help="the output path.")
# parse the arguments
args = parser.parse_args()
imc_filename = args.imc_filename
- save_imc_to_tiff(imc_acquisition=args.imc_filename,
- acquisition=args.acquisition,
- tifftype=args.tifftype,
- compression=args.compression, outname=args.outname,
- outpath=args.outpath, verbose=True)
-
-
+ save_imc_to_tiff(
+ imc_acquisition=args.imc_filename,
+ acquisition=args.acquisition,
+ tifftype=args.tifftype,
+ compression=args.compression,
+ outname=args.outname,
+ outpath=args.outpath,
+ verbose=True,
+ )
diff --git a/imctools/scripts/mcd2tiff.py b/imctools/scripts/mcd2tiff.py
index c4e626f..deef027 100644
--- a/imctools/scripts/mcd2tiff.py
+++ b/imctools/scripts/mcd2tiff.py
@@ -1,10 +1,20 @@
+import warnings
+
from imctools.io import mcdparser
import argparse
import os
-def save_mcd_tiff(mcd_filename, acquisition='all', tifftype='ome', compression=0, outname=None, outpath=0,verbose=False):
- """
+def save_mcd_tiff(
+ mcd_filename,
+ acquisition="all",
+ tifftype="ome",
+ compression=0,
+ outname=None,
+ outpath=0,
+ verbose=False,
+):
+ """
:param mcd_filename:
:param acquisition:
:param tifftype:
@@ -13,15 +23,18 @@ def save_mcd_tiff(mcd_filename, acquisition='all', tifftype='ome', compression=0
:param outpath:
:return:
"""
+ warnings.warn(
+ "imctools 1.x is deprecated, please migrate to version 2.x", DeprecationWarning
+ )
# parse the arguments
args = parser.parse_args()
if verbose:
- print('Load filename %s' %mcd_filename)
+ print("Load filename %s" % mcd_filename)
if outname is None:
outname = os.path.split(mcd_filename)[1]
- outname = outname.replace('.mcd', '')
+ outname = outname.replace(".mcd", "")
if outpath is None:
outpath = os.path.split(mcd_filename)[0]
@@ -29,63 +42,85 @@ def save_mcd_tiff(mcd_filename, acquisition='all', tifftype='ome', compression=0
with mcdparser.McdParser(mcd_filename) as mcd:
n_ac = mcd.n_acquisitions
if verbose:
- print('containing %i acquisitions:' % n_ac)
+ print("containing %i acquisitions:" % n_ac)
ac_ids = mcd.acquisition_ids
if verbose:
for aid in ac_ids:
- print('%s \n' %aid)
- print('Print acquisition: %s' %acquisition)
+ print("%s \n" % aid)
+ print("Print acquisition: %s" % acquisition)
- if args.acquisition == 'all':
+ if args.acquisition == "all":
acquisitions = ac_ids
else:
acquisitions = [acquisition]
for aid in acquisitions:
imc_img = mcd.get_imc_acquisition(aid)
- cur_outname = outname + '_a' + aid
+ cur_outname = outname + "_a" + aid
- if tifftype == 'ome':
- cur_outname += '.ome.tiff'
+ if tifftype == "ome":
+ cur_outname += ".ome.tiff"
else:
- cur_outname +='.tiff'
+ cur_outname += ".tiff"
cur_outname = os.path.join(outpath, cur_outname)
if verbose:
- print('Save %s as %s' %(aid,cur_outname))
+ print("Save %s as %s" % (aid, cur_outname))
iw = imc_img.get_image_writer(cur_outname)
iw.save_image(mode=tifftype, compression=compression)
if verbose:
- print('Finished!')
+ print("Finished!")
if __name__ == "__main__":
# Setup the command line arguments
- parser = argparse.ArgumentParser(description='Convert MCD to ImageJ Tiffs', prog='mcd2tiff', usage='%(prog)s mcd_filename [options]')
- parser.add_argument('mcd_filename', metavar='mcd_filename', type=str,
- help='The path to the MCD file to be converted')
- parser.add_argument('--acquisition', metavar='acquisition', type=str, default='all',
- help='all or acquisition ID: acquisitions to write as tiff.')
-
- parser.add_argument('--tifftype', type=str, default='ome',
- help='ome or imagej: Write the files either with ome metadata or imagej compatible mode.'
- )
- parser.add_argument('--compression', type=int, default=0,
- help='0-9: Tiff compression level')
-
- parser.add_argument('--outname', type=str, default=None,
- help='the name of the output file.')
- parser.add_argument('--outpath',type=str, default=None,
- help='the output path.')
+ parser = argparse.ArgumentParser(
+ description="Convert MCD to ImageJ Tiffs",
+ prog="mcd2tiff",
+ usage="%(prog)s mcd_filename [options]",
+ )
+ parser.add_argument(
+ "mcd_filename",
+ metavar="mcd_filename",
+ type=str,
+ help="The path to the MCD file to be converted",
+ )
+ parser.add_argument(
+ "--acquisition",
+ metavar="acquisition",
+ type=str,
+ default="all",
+ help="all or acquisition ID: acquisitions to write as tiff.",
+ )
+
+ parser.add_argument(
+ "--tifftype",
+ type=str,
+ default="ome",
+ help="ome or imagej: Write the files either with ome metadata or imagej compatible mode.",
+ )
+ parser.add_argument(
+ "--compression", type=int, default=0, help="0-9: Tiff compression level"
+ )
+
+ parser.add_argument(
+ "--outname", type=str, default=None, help="the name of the output file."
+ )
+ parser.add_argument("--outpath", type=str, default=None, help="the output path.")
# parse the arguments
args = parser.parse_args()
- save_mcd_tiff(mcd_filename=args.mcd_filename, acquisition=args.acquisition, tifftype=args.tifftype,
- compression=args.compression, outname=args.outname, outpath=args.outpath, verbose=True)
-
-
+ save_mcd_tiff(
+ mcd_filename=args.mcd_filename,
+ acquisition=args.acquisition,
+ tifftype=args.tifftype,
+ compression=args.compression,
+ outname=args.outname,
+ outpath=args.outpath,
+ verbose=True,
+ )
diff --git a/imctools/scripts/ome2micat.py b/imctools/scripts/ome2micat.py
index 8ba08f9..98cbdf3 100644
--- a/imctools/scripts/ome2micat.py
+++ b/imctools/scripts/ome2micat.py
@@ -1,4 +1,6 @@
#!/usr/bin/env python
+import warnings
+
from imctools.io import ometiffparser
import argparse
import os
@@ -17,14 +19,15 @@ def ome2singletiff(path_ome, outfolder, basename=None, dtype=None):
ome = ometiffparser.OmetiffParser(path_ome)
imc_img = ome.get_imc_acquisition()
if basename is None:
- fn_new = os.path.split(path_ome)[1].rstrip('.ome.tiff') + '_'
+ fn_new = os.path.split(path_ome)[1].rstrip(".ome.tiff") + "_"
else:
fn_new = basename
for label, metal in zip(imc_img.channel_labels, imc_img.channel_metals):
- label = re.sub('[^a-zA-Z0-9]', '-', label)
- new_path = os.path.join(outfolder, fn_new +label+'_'+metal)
- writer = imc_img.get_image_writer(new_path + '.tiff', metals=[metal])
- writer.save_image(mode='imagej', dtype=dtype)
+ label = re.sub("[^a-zA-Z0-9]", "-", label)
+ new_path = os.path.join(outfolder, fn_new + label + "_" + metal)
+ writer = imc_img.get_image_writer(new_path + ".tiff", metals=[metal])
+ writer.save_image(mode="imagej", dtype=dtype)
+
def ome2micatfolder(path_ome, basefolder, path_mask=None, dtype=None):
"""
@@ -34,19 +37,24 @@ def ome2micatfolder(path_ome, basefolder, path_mask=None, dtype=None):
:param fn_mask:
:return:
"""
+ warnings.warn(
+ "imctools 1.x is deprecated, please migrate to version 2.x", DeprecationWarning
+ )
fn = os.path.split(path_ome)[1]
- fn = fn.rstrip('.ome.tiff')
+ fn = fn.rstrip(".ome.tiff")
outfolder = os.path.join(basefolder, fn)
- if not(os.path.exists(outfolder)):
+ if not (os.path.exists(outfolder)):
os.makedirs(outfolder)
- ome2singletiff(path_ome, outfolder, basename='', dtype=dtype)
+ ome2singletiff(path_ome, outfolder, basename="", dtype=dtype)
if path_mask is not None:
fn_mask_base = os.path.split(path_mask)[1]
fn_mask_new = os.path.join(outfolder, fn_mask_base)
shutil.copy2(path_mask, fn_mask_new)
-def omefolder2micatfolder(fol_ome, outfolder, fol_masks=None, mask_suffix=None, dtype=None):
+def omefolder2micatfolder(
+ fol_ome, outfolder, fol_masks=None, mask_suffix=None, dtype=None
+):
"""
:param fol_ome:
@@ -55,17 +63,28 @@ def omefolder2micatfolder(fol_ome, outfolder, fol_masks=None, mask_suffix=None,
:param mask_suffix:
:return:
"""
+ warnings.warn(
+ "imctools 1.x is deprecated, please migrate to version 2.x", DeprecationWarning
+ )
if mask_suffix is None:
- mask_suffix = '_mask.tiff'
+ mask_suffix = "_mask.tiff"
- ome_files = [os.path.basename(fn) for fn in glob.glob(os.path.join(fol_ome, '*')) if fn.endswith('.ome.tiff')]
+ ome_files = [
+ os.path.basename(fn)
+ for fn in glob.glob(os.path.join(fol_ome, "*"))
+ if fn.endswith(".ome.tiff")
+ ]
if fol_masks is not None:
- fn_masks = [os.path.basename(fn) for fn in glob.glob(os.path.join(fol_masks, '*')) if fn.endswith(mask_suffix)]
+ fn_masks = [
+ os.path.basename(fn)
+ for fn in glob.glob(os.path.join(fol_masks, "*"))
+ if fn.endswith(mask_suffix)
+ ]
else:
fn_masks = []
for fn_ome in ome_files:
- len_suffix = len('.ome.tiff')
+ len_suffix = len(".ome.tiff")
basename_ome = fn_ome[:-len_suffix]
cur_mask = [fn for fn in fn_masks if fn.startswith(basename_ome)]
if len(cur_mask) > 0:
@@ -79,21 +98,35 @@ def omefolder2micatfolder(fol_ome, outfolder, fol_masks=None, mask_suffix=None,
if __name__ == "__main__":
# Setup the command line arguments
parser = argparse.ArgumentParser(
- description='Convertes an ome folder (or file) to a micat folder', prog='ome2micat')
-
- parser.add_argument('ome_folder', type=str,
- help='A folder with ome images or a single ome file')
-
- parser.add_argument('out_folder', type=str,
- help='Folder to output the micat folders')
-
- parser.add_argument('--mask_folder', type=str, default=None,
- help='Folder containing the masks, or single mask file.')
- parser.add_argument('--mask_suffix', type=str, default='_mask.tiff',
- help='suffix of the mask tiffs')
-
- parser.add_argument('--imagetype', type=str, default=None,choices=[None, 'uint16', 'int16', 'float'],
- help='The output image type')
+ description="Convertes an ome folder (or file) to a micat folder",
+ prog="ome2micat",
+ )
+
+ parser.add_argument(
+ "ome_folder", type=str, help="A folder with ome images or a single ome file"
+ )
+
+ parser.add_argument(
+ "out_folder", type=str, help="Folder to output the micat folders"
+ )
+
+ parser.add_argument(
+ "--mask_folder",
+ type=str,
+ default=None,
+ help="Folder containing the masks, or single mask file.",
+ )
+ parser.add_argument(
+ "--mask_suffix", type=str, default="_mask.tiff", help="suffix of the mask tiffs"
+ )
+
+ parser.add_argument(
+ "--imagetype",
+ type=str,
+ default=None,
+ choices=[None, "uint16", "int16", "float"],
+ help="The output image type",
+ )
# parser.add_argument('--postfix', type=str, default=None,
# help='Postfix to append to the basename.'
@@ -101,17 +134,21 @@ def omefolder2micatfolder(fol_ome, outfolder, fol_masks=None, mask_suffix=None,
args = parser.parse_args()
-
-
ome_folder = args.ome_folder
mask_folder = args.mask_folder
out_folder = args.out_folder
mask_suffix = args.mask_suffix
- if not(os.path.exists(out_folder)):
+ if not (os.path.exists(out_folder)):
os.mkdir(out_folder)
- if ome_folder.endswith('.ome.tiff'):
+ if ome_folder.endswith(".ome.tiff"):
ome2micatfolder(ome_folder, out_folder, mask_folder, dtype=args.imagetype)
else:
- omefolder2micatfolder(ome_folder, out_folder, mask_folder, mask_suffix=mask_suffix, dtype=args.imagetype)
+ omefolder2micatfolder(
+ ome_folder,
+ out_folder,
+ mask_folder,
+ mask_suffix=mask_suffix,
+ dtype=args.imagetype,
+ )
diff --git a/imctools/scripts/ometiff2analysis.py b/imctools/scripts/ometiff2analysis.py
index d024925..507d2e7 100644
--- a/imctools/scripts/ometiff2analysis.py
+++ b/imctools/scripts/ometiff2analysis.py
@@ -1,12 +1,29 @@
import argparse
import os
+import warnings
+
import pandas as pd
import numpy as np
from imctools.io import ometiffparser
-def ometiff_2_analysis(filename, outfolder, basename, pannelcsv=None, metalcolumn=None, masscolumn=None, usedcolumn=None,
- addsum=False, bigtiff=True, sort_channels=True, pixeltype=None):
+
+def ometiff_2_analysis(
+ filename,
+ outfolder,
+ basename,
+ pannelcsv=None,
+ metalcolumn=None,
+ masscolumn=None,
+ usedcolumn=None,
+ addsum=False,
+ bigtiff=True,
+ sort_channels=True,
+ pixeltype=None,
+):
+ warnings.warn(
+ "imctools 1.x is deprecated, please migrate to version 2.x", DeprecationWarning
+ )
# read the pannelcsv to find out which channels should be loaded
selmetals = None
selmass = None
@@ -23,26 +40,28 @@ def ometiff_2_analysis(filename, outfolder, basename, pannelcsv=None, metalcolum
else:
selmass = [str(n) for s, n in zip(selected, pannel[masscolumn]) if s]
else:
- selmetals = [pannel.columns[0]] + pannel.iloc[:,0].tolist()
+ selmetals = [pannel.columns[0]] + pannel.iloc[:, 0].tolist()
ome = ometiffparser.OmetiffParser(filename)
imc_img = ome.get_imc_acquisition()
if sort_channels:
if selmetals is not None:
+
def mass_from_met(x):
- return (''.join([m for m in x if m.isdigit()]), x)
+ return ("".join([m for m in x if m.isdigit()]), x)
+
selmetals = sorted(selmetals, key=mass_from_met)
if selmass is not None:
selmass = sorted(selmass)
- writer = imc_img.get_image_writer(outname + '.tiff', metals=selmetals, mass=selmass)
+ writer = imc_img.get_image_writer(outname + ".tiff", metals=selmetals, mass=selmass)
if addsum:
img_sum = np.sum(writer.img_stack, axis=2)
- img_sum = np.reshape(img_sum, list(img_sum.shape)+[1])
+ img_sum = np.reshape(img_sum, list(img_sum.shape) + [1])
writer.img_stack = np.append(img_sum, writer.img_stack, axis=2)
- writer.save_image(mode='imagej', bigtiff=bigtiff, dtype=pixeltype)
+ writer.save_image(mode="imagej", bigtiff=bigtiff, dtype=pixeltype)
if selmass is not None:
savenames = selmass
@@ -53,84 +72,140 @@ def mass_from_met(x):
savenames = [s for s in imc_img.channel_metals]
if addsum:
- savenames = ['sum'] + savenames
- with open(outname + '.csv', 'w') as f:
+ savenames = ["sum"] + savenames
+ with open(outname + ".csv", "w") as f:
for n in savenames:
- f.write(n + '\n')
+ f.write(n + "\n")
if __name__ == "__main__":
# Setup the command line arguments
- parser = argparse.ArgumentParser(description='Convert OME tiffs to analysis tiffs that are more compatible with tools.\n'+
- 'A csv with a boolean column can be used to select subsets of channels or metals from the stack\n'+
- 'The channels of the tiff will have the same order as in the csv.', prog='mcd2tiff',
- usage='%(prog)s ome_filename [options]')
-
- parser.add_argument('ome_filename', type=str,
- help='The path to the ome.tiff file to be converted')
-
- parser.add_argument('--outpostfix', type=str, default=None,
- help='the string to append to the name.')
-
- parser.add_argument('--outfolder', type=str, default=None,
- help='the output folder, Default is a subfolder called analysis in the current folder.')
-
- parser.add_argument('--pannelcsv', type=str, default=None,
- help='name of the csv that contains the channels to be written out.')
-
- parser.add_argument('--metalcolumn', type=str, default='metal',
- help='Column name of the metal names.'
- )
-
- parser.add_argument('--masscolumn', type=str, default=None,
- help='Column name of the mass names. If provided the metal column will be ignored.'
- )
-
- parser.add_argument('--usedcolumn', type=str, default='ilastik',
- help='Column that should contain booleans (0, 1) if the channel should be used.'
- )
- parser.add_argument('--outformat', type=str, default=None, choices=['float', 'uint16', 'uint8', 'uint32'],
- help='''original or float, uint32, uint16, unit8\n
- Per default the original pixeltype is taken''')
-
- parser.add_argument('--scale', type=str, default='no', choices=['no', 'max', 'percentile99, percentile99.9, percentile99.99'],
- help='scale the data?' )
-
- parser.add_argument('--addsum', type=str, default='no', choices=['no', 'yes'],
- help='Add the sum of the data as the first layer.' )
-
- parser.add_argument('--bigtiff', type=str, default='yes', choices=['no', 'yes'],
- help='Add the sum of the data as the first layer.' )
- parser.add_argument('--sort_channels', type=str, default='yes', choices=['no', 'yes'],
- help='Should the channels be sorted by mass?')
+ parser = argparse.ArgumentParser(
+ description="Convert OME tiffs to analysis tiffs that are more compatible with tools.\n"
+ + "A csv with a boolean column can be used to select subsets of channels or metals from the stack\n"
+ + "The channels of the tiff will have the same order as in the csv.",
+ prog="mcd2tiff",
+ usage="%(prog)s ome_filename [options]",
+ )
+
+ parser.add_argument(
+ "ome_filename", type=str, help="The path to the ome.tiff file to be converted"
+ )
+
+ parser.add_argument(
+ "--outpostfix", type=str, default=None, help="the string to append to the name."
+ )
+
+ parser.add_argument(
+ "--outfolder",
+ type=str,
+ default=None,
+ help="the output folder, Default is a subfolder called analysis in the current folder.",
+ )
+
+ parser.add_argument(
+ "--pannelcsv",
+ type=str,
+ default=None,
+ help="name of the csv that contains the channels to be written out.",
+ )
+
+ parser.add_argument(
+ "--metalcolumn",
+ type=str,
+ default="metal",
+ help="Column name of the metal names.",
+ )
+
+ parser.add_argument(
+ "--masscolumn",
+ type=str,
+ default=None,
+ help="Column name of the mass names. If provided the metal column will be ignored.",
+ )
+
+ parser.add_argument(
+ "--usedcolumn",
+ type=str,
+ default="ilastik",
+ help="Column that should contain booleans (0, 1) if the channel should be used.",
+ )
+ parser.add_argument(
+ "--outformat",
+ type=str,
+ default=None,
+ choices=["float", "uint16", "uint8", "uint32"],
+ help="""original or float, uint32, uint16, unit8\n
+ Per default the original pixeltype is taken""",
+ )
+
+ parser.add_argument(
+ "--scale",
+ type=str,
+ default="no",
+ choices=["no", "max", "percentile99, percentile99.9, percentile99.99"],
+ help="scale the data?",
+ )
+
+ parser.add_argument(
+ "--addsum",
+ type=str,
+ default="no",
+ choices=["no", "yes"],
+ help="Add the sum of the data as the first layer.",
+ )
+
+ parser.add_argument(
+ "--bigtiff",
+ type=str,
+ default="yes",
+ choices=["no", "yes"],
+ help="Add the sum of the data as the first layer.",
+ )
+ parser.add_argument(
+ "--sort_channels",
+ type=str,
+ default="yes",
+ choices=["no", "yes"],
+ help="Should the channels be sorted by mass?",
+ )
args = parser.parse_args()
-
- default_subfolder = 'analysis'
+ default_subfolder = "analysis"
fn = args.ome_filename
- assert (fn[-9:] == '.ome.tiff') or (fn[-8:] == '.ome.tif') is True, 'Must be an .ome.tiff or .ome.tif'
+ assert (fn[-9:] == ".ome.tiff") or (
+ fn[-8:] == ".ome.tif"
+ ) is True, "Must be an .ome.tiff or .ome.tif"
- fn_out = os.path.basename(fn).strip('.ome.tiff').strip('.ome.tif')
+ fn_out = os.path.basename(fn).strip(".ome.tiff").strip(".ome.tif")
outpostifx = args.outpostfix
if outpostifx is not None:
- fn_out = '_'.join([fn_out, outpostifx])
+ fn_out = "_".join([fn_out, outpostifx])
outfolder = args.outfolder
if outfolder is None:
outfolder = os.path.join(os.path.split(fn)[0], default_subfolder)
# create path if it doesnt exist
- if not(os.path.exists(outfolder)):
+ if not (os.path.exists(outfolder)):
os.mkdir(outfolder)
# finalize the outname
outname = os.path.join(outfolder, fn_out)
- ometiff_2_analysis(args.ome_filename, outfolder, fn_out, args.pannelcsv, args.metalcolumn, args.masscolumn,
- args.usedcolumn, args.addsum == 'yes',
- bigtiff=args.bigtiff == 'yes',
- sort_channels=args.sort_channels == 'yes',
- pixeltype=args.outformat)
+ ometiff_2_analysis(
+ args.ome_filename,
+ outfolder,
+ fn_out,
+ args.pannelcsv,
+ args.metalcolumn,
+ args.masscolumn,
+ args.usedcolumn,
+ args.addsum == "yes",
+ bigtiff=args.bigtiff == "yes",
+ sort_channels=args.sort_channels == "yes",
+ pixeltype=args.outformat,
+ )
diff --git a/imctools/scripts/probablity2uncertainty.py b/imctools/scripts/probablity2uncertainty.py
index 98ffeca..b094fbb 100644
--- a/imctools/scripts/probablity2uncertainty.py
+++ b/imctools/scripts/probablity2uncertainty.py
@@ -1,11 +1,10 @@
#!/usr/bin/env python
+import warnings
+
import tifffile
-from scipy import ndimage as ndi
-from imctools import library as lib
import argparse
import os
import numpy as np
-from skimage import transform
def probability2uncertainty(fn_probability, outfolder, basename=None, suffix=None):
@@ -18,26 +17,28 @@ def probability2uncertainty(fn_probability, outfolder, basename=None, suffix=Non
:param scalefactor: Factor to scale by
:return:
"""
+ warnings.warn(
+ "imctools 1.x is deprecated, please migrate to version 2.x", DeprecationWarning
+ )
with tifffile.TiffFile(fn_probability) as tif:
stack = tif.asarray()
if len(stack.shape) == 2:
- stack = stack.reshape([1]+list(stack.shape))
+ stack = stack.reshape([1] + list(stack.shape))
if basename is None:
basename = os.path.splitext(os.path.basename(fn_probability))[0]
if suffix is None:
- suffix = '_uncertainty'
-
+ suffix = "_uncertainty"
- fn = os.path.join(outfolder, basename+suffix+'.tiff')
+ fn = os.path.join(outfolder, basename + suffix + ".tiff")
timg = np.max(stack, 2)
if stack.dtype == np.float:
- timg = 1-timg
+ timg = 1 - timg
else:
- timg = np.iinfo(stack.dtype).max-timg
+ timg = np.iinfo(stack.dtype).max - timg
with tifffile.TiffWriter(fn, imagej=True) as tif:
tif.save(timg.squeeze())
@@ -45,18 +46,28 @@ def probability2uncertainty(fn_probability, outfolder, basename=None, suffix=Non
if __name__ == "__main__":
# Setup the command line arguments
parser = argparse.ArgumentParser(
- description='Converts probailiy masks to uncertainties.', prog='probability2uncertainty')
-
- parser.add_argument('probab_filename', type=str,
- help='The path to the probablitity tiff')
-
- parser.add_argument('--out_folder', type=str, default=None,
- help='Folder to save the images in. Default a subfolder with the basename image_filename in the image_filename folder.')
-
- parser.add_argument('--basename', type=str, default=None,
- help='Basename for the output image. Default: image_filename')
-
+ description="Converts probailiy masks to uncertainties.",
+ prog="probability2uncertainty",
+ )
+
+ parser.add_argument(
+ "probab_filename", type=str, help="The path to the probablitity tiff"
+ )
+
+ parser.add_argument(
+ "--out_folder",
+ type=str,
+ default=None,
+ help="Folder to save the images in. Default a subfolder with the basename image_filename in the image_filename folder.",
+ )
+
+ parser.add_argument(
+ "--basename",
+ type=str,
+ default=None,
+ help="Basename for the output image. Default: image_filename",
+ )
args = parser.parse_args()
- raise Exception('Not implemented')
+ raise Exception("Not implemented")
diff --git a/imctools/scripts/resizeimage.py b/imctools/scripts/resizeimage.py
index fa8aae4..f4838b4 100644
--- a/imctools/scripts/resizeimage.py
+++ b/imctools/scripts/resizeimage.py
@@ -8,6 +8,7 @@
from skimage import transform
import warnings
+
def resize_image(fn_stack, outfolder, basename, scalefactor):
"""
Resizes an image
@@ -18,42 +19,61 @@ def resize_image(fn_stack, outfolder, basename, scalefactor):
:param scalefactor: Factor to scale by
:return:
"""
-
- warnings.warn('''resize_image is deprecated and
+
+ warnings.warn(
+ """resize_image is deprecated and
will not be supported in future versions.
Please use the `resize` module
- in CellProfiler!''',
- DeprecationWarning)
+ in CellProfiler!""",
+ DeprecationWarning,
+ )
with tifffile.TiffFile(fn_stack) as tif:
stack = tif.asarray()
if len(stack.shape) == 2:
- stack = stack.reshape([1]+list(stack.shape))
+ stack = stack.reshape([1] + list(stack.shape))
- fn = os.path.join(outfolder, basename+'.tiff')
+ fn = os.path.join(outfolder, basename + ".tiff")
with tifffile.TiffWriter(fn, imagej=True) as tif:
for chan in range(stack.shape[0]):
timg = stack[chan, :, :]
timg = transform.rescale(timg, scalefactor, preserve_range=True, order=3)
tif.save(timg.astype(np.float32).squeeze())
+
if __name__ == "__main__":
# Setup the command line arguments
parser = argparse.ArgumentParser(
- description='Scales image by a factor.', prog='scaleimage')
-
- parser.add_argument('image_filename', type=str,
- help='The path to the image filename. If the image is a stack it needs to be CXY ordered')
-
- parser.add_argument('scalingfactor', type=float, default=2,
- help='How much should the image be scaled.')
-
- parser.add_argument('--out_folder', type=str, default=None,
- help='Folder to save the images in. Default a subfolder with the basename image_filename in the image_filename folder.')
-
- parser.add_argument('--basename', type=str, default=None,
- help='Basename for the output image. Default: image_filename')
+ description="Scales image by a factor.", prog="scaleimage"
+ )
+
+ parser.add_argument(
+ "image_filename",
+ type=str,
+ help="The path to the image filename. If the image is a stack it needs to be CXY ordered",
+ )
+
+ parser.add_argument(
+ "scalingfactor",
+ type=float,
+ default=2,
+ help="How much should the image be scaled.",
+ )
+
+ parser.add_argument(
+ "--out_folder",
+ type=str,
+ default=None,
+ help="Folder to save the images in. Default a subfolder with the basename image_filename in the image_filename folder.",
+ )
+
+ parser.add_argument(
+ "--basename",
+ type=str,
+ default=None,
+ help="Basename for the output image. Default: image_filename",
+ )
# parser.add_argument('--postfix', type=str, default=None,
# help='Postfix to append to the basename.'
@@ -62,18 +82,21 @@ def resize_image(fn_stack, outfolder, basename, scalefactor):
args = parser.parse_args()
if args.basename is None:
- args.basename = os.path.split(args.image_filename)[1].strip('.tif').strip('.tiff')
+ args.basename = (
+ os.path.split(args.image_filename)[1].strip(".tif").strip(".tiff")
+ )
if args.postfix is not None:
args.basename = args.basename + args.postfix
if args.out_folder is None:
args.out_folder = os.path.split(args.image_filename)[0]
- tmpname = os.path.split(args.image_filename)[1].strip('.tif').strip('.tiff')
+ tmpname = os.path.split(args.image_filename)[1].strip(".tif").strip(".tiff")
args.out_folder = os.path.join(args.out_folder, tmpname)
- if not(os.path.exists(args.out_folder)):
+ if not (os.path.exists(args.out_folder)):
os.mkdir(args.out_folder)
- resize_image(args.image_filename, args.out_folder,
- args.basename, args.scalingfactor)
+ resize_image(
+ args.image_filename, args.out_folder, args.basename, args.scalingfactor
+ )
diff --git a/pyproject.toml b/pyproject.toml
index 0b9479d..7730f27 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,10 +1,10 @@
[build-system]
-requires = ["poetry>=1.0.3"]
+requires = ["poetry>=1.0.5"]
build-backend = "poetry.masonry.api"
[tool.poetry]
name = "imctools"
-version = "1.0.6"
+version = "1.0.7"
description = "Tools to handle IMC data"
license = "LICENSE"
authors = [
diff --git a/setup.py b/setup.py
index 952e36a..a9e2915 100644
--- a/setup.py
+++ b/setup.py
@@ -10,7 +10,7 @@
setup(
name='imctools',
- version='1.0.6',
+ version='1.0.7',
description='Tools to handle IMC data',
long_description=readme,
author='Vito Zanotelli',