Beispiel #1
0
    def map_name_to_coordinate(name):
        '''Maps identifier string representation to coordinate.

        Parameters
        ----------
        name: str
            well name

        Returns
        -------
        Tuple[int]
            zero-based row, column position of a given well within the plate

        Examples
        --------
        >>> Well.map_name_to_coordinate("A02")
        (0, 1)
        '''
        row_name, col_name = re.match(r'([A-Z])(\d+)', name).group(1, 2)
        row_index = utils.map_letter_to_number(row_name) - 1
        col_index = int(col_name) - 1
        return (row_index, col_index)
Beispiel #2
0
    def map_name_to_coordinate(name):
        '''Maps identifier string representation to coordinate.

        Parameters
        ----------
        name: str
            well name

        Returns
        -------
        Tuple[int]
            zero-based row, column position of a given well within the plate

        Examples
        --------
        >>> Well.map_name_to_coordinate("A02")
        (0, 1)
        '''
        row_name, col_name = re.match(r'([A-Z])(\d+)', name).group(1, 2)
        row_index = utils.map_letter_to_number(row_name) - 1
        col_index = int(col_name) - 1
        return (row_index, col_index)
Beispiel #3
0
    def read(self, microscope_metadata_files, microscope_image_filenames):
        '''Reads metadata from "mlf" and "mrf" metadata files in case they
        are provided.

        Parameters
        ----------
        microscope_metadata_files: List[str]
            absolute path to microscope metadata files
        microscope_image_filenames: List[str]
            names of the corresponding microscope image files

        Returns
        -------
        bioformats.omexml.OMEXML
            OMEXML image metadata

        '''
        microscope_image_filenames = natsorted(microscope_image_filenames)
        metadata = bioformats.OMEXML(XML_DECLARATION)
        if len(microscope_metadata_files) == 0:
            logger.warn('no microscope metadata files found')
            return None
        elif len(microscope_metadata_files) != 2:
            logger.warn('expected two microscope metadata files')
            return None
        for f in microscope_metadata_files:
            if f.endswith('mlf'):
                mlf_filename = f
            elif f.endswith('mrf'):
                mrf_filename = f

        mrf_tree = etree.parse(mrf_filename)
        mrf_root = mrf_tree.getroot()
        mrf_ns = mrf_root.nsmap['bts']

        # Obtain the positional information for each image acquisition site
        # from the ".mlf" file:
        mlf_tree = etree.parse(mlf_filename)
        mlf_root = mlf_tree.getroot()
        record_elements = mlf_root.xpath('.//bts:MeasurementRecord',
                                         namespaces=mlf_root.nsmap)
        mlf_ns = mlf_root.nsmap['bts']

        metadata.image_count = len([
            e for e in record_elements
            if e.attrib['{%s}Type' % mlf_ns] != 'ERR'
        ])
        lookup = defaultdict(list)

        for e in record_elements:
            # Translate positional information into well identifier string
            well_row = utils.map_number_to_letter(
                int(e.attrib['{%s}Row' % mlf_ns]))
            well_col = int(e.attrib['{%s}Column' % mlf_ns])
            well_id = '%s%.2d' % (well_row, well_col)
            if e.attrib['{%s}Type' % mlf_ns] == 'ERR':
                field_index = int(e.attrib['{%s}FieldIndex' % mlf_ns])
                logger.error(
                    'erroneous acquisition - no channel and z-position '
                    'information available at well %s field %d' %
                    (well_id, field_index))
                continue
            # This microscope stores each plane in a separate file. Therefore,
            # we can use the filename to match images.
            name = e.text
            index = microscope_image_filenames.index(name)
            img = metadata.image(index)
            img.AcquisitionDate = e.attrib['{%s}Time' % mlf_ns]

            # Image files always contain only a single plane
            img.Pixels.SizeT = 1
            img.Pixels.SizeC = 1
            img.Pixels.SizeZ = 1
            img.Pixels.plane_count = 1
            # A name has to be set as a flag for the handler to update
            # the metadata
            img.Name = name
            # Make channel name consistent with how it is encoded in the image
            # file name to ensure that the result is the same, independent of
            # whether it was obtained from the metadata or the image file name.
            img.Pixels.Channel(0).Name = e.attrib['{%s}Ch' % mlf_ns]
            img.Pixels.Plane(0).PositionX = float(e.attrib['{%s}X' % mlf_ns])
            img.Pixels.Plane(0).PositionY = float(e.attrib['{%s}Y' % mlf_ns])
            img.Pixels.Plane(0).PositionZ = float(e.attrib['{%s}Z' % mlf_ns])
            img.Pixels.Plane(0).TheZ = int(e.attrib['{%s}ZIndex' % mlf_ns])
            img.Pixels.Plane(0).TheT = int(e.attrib['{%s}TimelineIndex' %
                                                    mlf_ns])

            idx = microscope_image_filenames.index(img.Name)
            lookup[well_id].append(idx)

        # Obtain the general experiment information and well plate format
        # specifications from the ".mrf" file:
        name = mrf_root.attrib['{%s}Title' % mrf_ns]
        plate = metadata.PlatesDucktype(metadata.root_node).newPlate(name=name)
        plate.RowNamingConvention = 'letter'
        plate.ColumnNamingConvention = 'number'
        plate.Rows = mrf_root.attrib['{%s}RowCount' % mrf_ns]
        plate.Columns = mrf_root.attrib['{%s}ColumnCount' % mrf_ns]
        wells = lookup.keys()
        for w in set(wells):
            # Create a *Well* element for each imaged well in the plate
            row = utils.map_letter_to_number(w[0]) - 1
            col = int(w[1:]) - 1
            well = metadata.WellsDucktype(plate).new(row=row, column=col)
            well_samples = metadata.WellSampleDucktype(well.node)
            for i, ref in enumerate(lookup[w]):
                # Create a *WellSample* element for each acquisition site
                well_samples.new(index=i)
                well_samples[i].ImageRef = ref

        return metadata
Beispiel #4
0
    def read(self, microscope_metadata_files, microscope_image_filenames):
        '''Reads metadata from "mlf" and "mrf" metadata files in case they
        are provided.

        Parameters
        ----------
        microscope_metadata_files: List[str]
            absolute path to microscope metadata files
        microscope_image_filenames: List[str]
            names of the corresponding microscope image files

        Returns
        -------
        bioformats.omexml.OMEXML
            OMEXML image metadata

        '''
        microscope_image_filenames = natsorted(microscope_image_filenames)
        metadata = bioformats.OMEXML(XML_DECLARATION)
        if len(microscope_metadata_files) == 0:
            logger.warn('no microscope metadata files found')
            return None
        elif len(microscope_metadata_files) != 2:
            logger.warn('expected two microscope metadata files')
            return None
        for f in microscope_metadata_files:
            if f.endswith('mlf'):
                mlf_filename = f
            elif f.endswith('mrf'):
                mrf_filename = f

        mrf_tree = etree.parse(mrf_filename)
        mrf_root = mrf_tree.getroot()
        mrf_ns = mrf_root.nsmap['bts']

        # Obtain the positional information for each image acquisition site
        # from the ".mlf" file:
        mlf_tree = etree.parse(mlf_filename)
        mlf_root = mlf_tree.getroot()
        record_elements = mlf_root.xpath(
            './/bts:MeasurementRecord', namespaces=mlf_root.nsmap
        )
        mlf_ns = mlf_root.nsmap['bts']

        metadata.image_count = len([
            e for e in record_elements
            if e.attrib['{%s}Type' % mlf_ns] != 'ERR'
        ])
        lookup = defaultdict(list)

        for e in record_elements:
            # Translate positional information into well identifier string
            well_row = utils.map_number_to_letter(
                int(e.attrib['{%s}Row' % mlf_ns]))
            well_col = int(e.attrib['{%s}Column' % mlf_ns])
            well_id = '%s%.2d' % (well_row, well_col)
            if e.attrib['{%s}Type' % mlf_ns] == 'ERR':
                field_index = int(e.attrib['{%s}FieldIndex' % mlf_ns])
                logger.error(
                    'erroneous acquisition - no channel and z-position '
                    'information available at well %s field %d'
                    % (well_id, field_index)
                )
                continue
            # This microscope stores each plane in a separate file. Therefore,
            # we can use the filename to match images.
            name = e.text

            # Check for .tif to .png/.jpg conversion
            if microscope_image_filenames[0].endswith('.png'):
                name = name.replace('.tif','.png')
            elif microscope_image_filenames[0].endswith('.jpg'):
                name = name.replace('.tif','.jpg')


            index = microscope_image_filenames.index(name)
            img = metadata.image(index)
            img.AcquisitionDate = e.attrib['{%s}Time' % mlf_ns]

            # Image files always contain only a single plane
            img.Pixels.SizeT = 1
            img.Pixels.SizeC = 1
            img.Pixels.SizeZ = 1
            img.Pixels.plane_count = 1
            # A name has to be set as a flag for the handler to update
            # the metadata
            img.Name = name
            # Make channel name consistent with how it is encoded in the image
            # file name to ensure that the result is the same, independent of
            # whether it was obtained from the metadata or the image file name.
            img.Pixels.Channel(0).Name = e.attrib['{%s}Ch' % mlf_ns]
            img.Pixels.Plane(0).PositionX = float(e.attrib['{%s}X' % mlf_ns])
            img.Pixels.Plane(0).PositionY = float(e.attrib['{%s}Y' % mlf_ns])
            img.Pixels.Plane(0).PositionZ = float(e.attrib['{%s}Z' % mlf_ns])
            img.Pixels.Plane(0).TheZ = int(e.attrib['{%s}ZIndex' % mlf_ns])
            img.Pixels.Plane(0).TheT = int(e.attrib['{%s}TimelineIndex' % mlf_ns])

            idx = microscope_image_filenames.index(img.Name)
            lookup[well_id].append(idx)

        # Obtain the general experiment information and well plate format
        # specifications from the ".mrf" file:
        name = mrf_root.attrib['{%s}Title' % mrf_ns]
        plate = metadata.PlatesDucktype(metadata.root_node).newPlate(name=name)
        plate.RowNamingConvention = 'letter'
        plate.ColumnNamingConvention = 'number'
        plate.Rows = mrf_root.attrib['{%s}RowCount' % mrf_ns]
        plate.Columns = mrf_root.attrib['{%s}ColumnCount' % mrf_ns]
        wells = lookup.keys()
        for w in set(wells):
            # Create a *Well* element for each imaged well in the plate
            row = utils.map_letter_to_number(w[0]) - 1
            col = int(w[1:]) - 1
            well = metadata.WellsDucktype(plate).new(row=row, column=col)
            well_samples = metadata.WellSampleDucktype(well.node)
            for i, ref in enumerate(lookup[w]):
                # Create a *WellSample* element for each acquisition site
                well_samples.new(index=i)
                well_samples[i].ImageRef = ref

        return metadata
Beispiel #5
0
    def read(self, microscope_metadata_files, microscope_image_filenames):
        '''Read metadata from "nd" metadata file.

        Parameters
        ----------
        microscope_metadata_files: List[str]
            absolute path to the microscope metadata files
        microscope_image_filenames: List[str]
            names of the corresponding microscope image files

        Returns
        -------
        bioformats.omexml.OMEXML
            OMEXML image metadata

        Raises
        ------
        ValueError
            when `microscope_metadata_files` doesn't have length one
        '''
        microscope_image_filenames = natsorted(microscope_image_filenames)
        if len(microscope_metadata_files) != 1:
            raise ValueError('Expected one microscope metadata file.')
        nd_filename = microscope_metadata_files[0]
        metadata = bioformats.OMEXML(XML_DECLARATION)
        # 1) Obtain the general experiment information and well plate format
        #    specifications from the ".nd" file:
        nd = read_nd_file(nd_filename)

        metadata.image_count = nd['NStagePositions']
        if nd['DoWave']:
            metadata.image_count *= nd['NWavelengths']
        if nd['DoTimelapse']:
            metadata.image_count *= nd['NTimePoints']

        for i in xrange(metadata.image_count):
            img = metadata.image(i)
            img.Name = ''
            # Images files may contain a variable number of z-stacks
            # (SizeZ >= 1), but only one time point (SizeT == 1)
            # and one channel (SizeC == 1)
            img.Pixels.SizeT = 1
            img.Pixels.SizeC = 1
            img.Pixels.SizeZ = nd['NZSteps']
            img.Pixels.plane_count = nd['NZSteps']

        # TODO: case when no stage positions are available (manual acquisition)

        name = os.path.splitext(os.path.basename(nd_filename))[0]
        plate = metadata.PlatesDucktype(metadata.root_node).newPlate(name=name)
        plate.RowNamingConvention = 'letter'
        plate.ColumnNamingConvention = 'number'
        rows = [
            nd['Stage%d' % (i+1)]['row']
            for i in xrange(nd['NStagePositions'])
        ]
        plate.Rows = len(set(rows))
        columns = [
            nd['Stage%d' % (i+1)]['column']
            for i in xrange(nd['NStagePositions'])
        ]
        plate.Columns = len(set(columns))

        # Create a lut table to get all images planes per well
        sites = [
            nd['Stage%d' % (i+1)]['site']
            for i in xrange(nd['NStagePositions'])
        ]
        wells = [
            '%s%.2d' % (rows[i], columns[i])
            for i in xrange(len(sites))
        ]
        lut = defaultdict(list)
        for i, filename in enumerate(natsorted(microscope_image_filenames)):
            fields = MetadataHandler.extract_fields_from_filename(
                IMAGE_FILE_REGEX_PATTERN, filename, defaults=False
            )
            # NOTE: We assume that the "site" id is global per plate
            field_index = sites.index(int(fields.s))
            lut[wells[field_index]].append(i)

        for w in set(wells):
            # Create a "Well" instance for each imaged well in the plate
            row_index = utils.map_letter_to_number(w[0]) - 1
            col_index = int(w[1:]) - 1
            well = metadata.WellsDucktype(plate).new(
                row=row_index, column=col_index
            )
            well_samples = metadata.WellSampleDucktype(well.node)
            for i, ref in enumerate(lut[w]):
                # Create a *WellSample* element for each acquisition site
                well_samples.new(index=i)
                well_samples[i].ImageRef = ref

        return metadata