Esempio n. 1
0
 def setup(self, path,
              extensions=None, ignore_prefixes=None, multi_image=None):
     self.path = os.path.normpath(path)
     self.extensions = self.EXTENSIONS if extensions is None \
                       else extensions
     self.ignore_prefixes = self.IGNORE_PREFIXES if ignore_prefixes is None \
                            else ignore_prefixes
     self.multi_image = self.MULTIIMAGE_USE_ZSLICE if multi_image is None \
                        else multi_image
     self.has_multi_images = False
     self.timestamps_from_file = None
     self.use_frame_indices = False
     self.dimension_lookup = {}
     self.meta_data = MetaData()
Esempio n. 2
0
 def setup(self, path, extensions=None, ignore_prefixes=None, multi_image=None):
     self.path = os.path.normpath(path)
     self.extensions = self.EXTENSIONS if extensions is None else extensions
     self.ignore_prefixes = self.IGNORE_PREFIXES if ignore_prefixes is None else ignore_prefixes
     self.multi_image = self.MULTIIMAGE_USE_ZSLICE if multi_image is None else multi_image
     self.has_multi_images = False
     self.timestamps_from_file = None
     self.use_frame_indices = False
     self.dimension_lookup = {}
     self.meta_data = MetaData()
Esempio n. 3
0
class AbstractImporter(XmlSerializer):

    EXTENSIONS = [".tif", ".png", ".png"]
    IGNORE_PREFIXES = ["."]

    MULTIIMAGE_IGNORE = "ignore"
    MULTIIMAGE_USE_ZSLICE = "zslice"

    def __init__(self):
        super(AbstractImporter, self).__init__()

    def setup(self, path, extensions=None, ignore_prefixes=None, multi_image=None):
        self.path = os.path.normpath(path)
        self.extensions = self.EXTENSIONS if extensions is None else extensions
        self.ignore_prefixes = self.IGNORE_PREFIXES if ignore_prefixes is None else ignore_prefixes
        self.multi_image = self.MULTIIMAGE_USE_ZSLICE if multi_image is None else multi_image
        self.has_multi_images = False
        self.timestamps_from_file = None
        self.use_frame_indices = False
        self.dimension_lookup = {}
        self.meta_data = MetaData()

    def __setstate__(self, state):
        for k, v in state.iteritems():
            self.__dict__[k] = v

    def scan(self):
        self.dimension_lookup = self._build_dimension_lookup()
        self.meta_data.setup()

    @property
    def is_valid(self):
        """
        Return the import success. For now only the number of identified files
        is checked.
        """
        return self.meta_data.image_files > 0

    def get_image(self, coordinate):
        index = 0
        zslice = coordinate.zslice
        if self.has_multi_images and self.multi_image == self.MULTIIMAGE_USE_ZSLICE:
            index = zslice - 1
            zslice = None

        filename_rel = self.dimension_lookup[coordinate.position][coordinate.time][coordinate.channel][zslice]
        filename_abs = os.path.join(self.path, filename_rel)
        # make sure no back-slashes are left in the path
        filename_abs = filename_abs.replace("\\", "/")
        if self.meta_data.pixel_type == PixelType.name(PixelType.Uint8):
            image = ccore.readImage(filename_abs, index)
        elif self.meta_data.pixel_type == PixelType.name(PixelType.Uint16):
            image = ccore.readImageUInt16(filename_abs, index)
        else:
            image = ccore.readImageUInt16(filename_abs, index)
        return image

    def _build_dimension_lookup(self):
        s = StopWatch(start=True)
        lookup = {}
        has_xy = False
        positions = []
        times = []
        channels = []
        zslices = []

        dimension_items = self._get_dimension_items()
        print("Get dimensions: %s" % s.interim())
        s.reset(start=True)

        # if use_frame_indices is set in the ini file,
        # we make a first scan of the items and determine for each position
        # the list of timepoints.
        # Then, we can assign to each position a dictionary that assigns to each timepoint
        # its index (after ordering).
        if self.use_frame_indices:
            # all_times = list(set([int(item[Dimensions.Time]) if Dimensions.Time in item else 0
            #                      for item in dimension_items]))
            # all_times.sort()
            first_pass = {}
            for item in dimension_items:
                position = item[Dimensions.Position]
                if not position in first_pass:
                    first_pass[position] = []

                if Dimensions.Time in item:
                    time_val = int(item[Dimensions.Time])
                else:
                    time_val = 0
                first_pass[position].append(time_val)

            time_index_correspondence = {}
            for pos in first_pass.keys():
                first_pass[position].sort()
                time_index_correspondence[pos] = dict(zip(first_pass[position], range(len(first_pass[position]))))

        for item in dimension_items:
            # import image info only once
            if not has_xy:
                has_xy = True
                info = ccore.ImageImportInfo(os.path.join(self.path, item["filename"]))

                self.meta_data.set_image_info(info)
                self.has_multi_images = False  # info.images > 1

            # position
            position = item[Dimensions.Position]
            if not position in lookup:
                lookup[position] = {}

            # time
            if Dimensions.Time in item:
                time_from_filename = int(item[Dimensions.Time])
            else:
                time_from_filename = 0
                item[Dimensions.Time] = str(time_from_filename)

            if self.use_frame_indices:
                time = time_index_correspondence[position][time_from_filename]
            else:
                time = time_from_filename
            if not time in lookup[position]:
                lookup[position][time] = {}

            # channels
            if Dimensions.Channel in item:
                channel = item[Dimensions.Channel]
            else:
                channel = "1"
                item[Dimensions.Channel] = channel
            if not channel in lookup[position][time]:
                lookup[position][time][channel] = {}

            # leave zslice optional.
            # in case of multi-images it must not be defined
            if Dimensions.ZSlice in item:
                zslice = item[Dimensions.ZSlice]
            else:
                zslice = 0
                item[Dimensions.ZSlice] = zslice
            if zslice == "":
                zslice = None
            if not zslice is None:
                zslice = int(zslice)
            if not zslice in lookup[position][time][channel]:
                lookup[position][time][channel][zslice] = item["filename"]

            # allow to read timestamps from file if not present
            if MetaInfo.Timestamp in item:
                timestamp = float(item[MetaInfo.Timestamp])
                self.meta_data.append_absolute_time(position, time, timestamp)
            elif self.timestamps_from_file in ["mtime", "ctime"]:
                filename_full = os.path.join(self.path, item["filename"])
                if self.timestamps_from_file == "mtime":
                    timestamp = os.path.getmtime(filename_full)
                else:
                    timestamp = os.path.getctime(filename_full)
                item[MetaInfo.Timestamp] = timestamp
                self.meta_data.append_absolute_time(position, time, timestamp)

            if MetaInfo.Well in item:
                well = item[MetaInfo.Well]
                subwell = item.get(MetaInfo.Subwell, None)
                self.meta_data.append_well_subwell_info(position, well, subwell)

            if self.has_multi_images and self.multi_image == self.MULTIIMAGE_USE_ZSLICE:
                if not zslice is None:
                    raise ValueError("Multi-image assigned for zslice conflicts" " with zslice token in filename!")
                zslices.extend(range(1, info.images + 1))
            else:
                zslices.append(zslice)

            positions.append(position)
            times.append(time)
            channels.append(channel)

        self.meta_data.positions = tuple(sorted(set(positions)))

        # assure that all items of one dimension are of same length
        times = set(times)
        channels = set(channels)
        zslices = set(zslices)
        # find overall valid number of frames
        for p in lookup:
            times = times.intersection(lookup[p].keys())
        # find overall valid channels/zslices based on overall valid frames
        for p in lookup:
            for t in times:
                channels = channels.intersection(lookup[p][t].keys())
                for c in channels:
                    zslices = zslices.intersection(lookup[p][t][c].keys())
        self.meta_data.times = sorted(times)
        self.meta_data.channels = sorted(channels)
        self.meta_data.zslices = sorted(zslices)
        self.meta_data.image_files = len(dimension_items)

        print("Build time: %s" % s.stop())
        return lookup

    def _get_dimension_items(self):
        raise NotImplementedError()
Esempio n. 4
0
class AbstractImporter(XmlSerializer):

    EXTENSIONS = ['.tif', '.png', '.png']
    IGNORE_PREFIXES = ['.']

    MULTIIMAGE_IGNORE = 'ignore'
    MULTIIMAGE_USE_ZSLICE = 'zslice'

    def __init__(self):
        super(AbstractImporter, self).__init__()

    def setup(self,
              path,
              extensions=None,
              ignore_prefixes=None,
              multi_image=None):
        self.path = os.path.normpath(path)
        self.extensions = self.EXTENSIONS if extensions is None \
                          else extensions
        self.ignore_prefixes = self.IGNORE_PREFIXES if ignore_prefixes is None \
                               else ignore_prefixes
        self.multi_image = self.MULTIIMAGE_USE_ZSLICE if multi_image is None \
                           else multi_image
        self.has_multi_images = False
        self.timestamps_from_file = None
        self.use_frame_indices = False
        self.dimension_lookup = {}
        self.meta_data = MetaData()

    def __setstate__(self, state):
        for k, v in state.iteritems():
            self.__dict__[k] = v

    def scan(self):
        self.dimension_lookup = self._build_dimension_lookup()
        self.meta_data.setup()

    @property
    def is_valid(self):
        """
        Return the import success. For now only the number of identified files
        is checked.
        """
        return self.meta_data.image_files > 0

    def get_image(self, coordinate):
        index = 0
        zslice = coordinate.zslice
        if (self.has_multi_images
                and self.multi_image == self.MULTIIMAGE_USE_ZSLICE):
            index = zslice - 1
            zslice = None

        filename_rel = self.dimension_lookup[coordinate.position] \
                                            [coordinate.time] \
                                            [coordinate.channel] \
                                            [zslice]
        filename_abs = os.path.join(self.path, filename_rel)
        # make sure no back-slashes are left in the path
        filename_abs = filename_abs.replace('\\', '/')
        if self.meta_data.pixel_type == PixelType.name(PixelType.Uint8):
            image = ccore.readImage(filename_abs, index)
        elif self.meta_data.pixel_type == PixelType.name(PixelType.Uint16):
            image = ccore.readImageUInt16(filename_abs, index)
        else:
            image = ccore.readImageUInt16(filename_abs, index)
        return image

    def _build_dimension_lookup(self):
        s = StopWatch(start=True)
        lookup = {}
        has_xy = False
        positions = []
        times = []
        channels = []
        zslices = []

        dimension_items = self._get_dimension_items()
        print("Get dimensions: %s" % s.interim())
        s.reset(start=True)

        # if use_frame_indices is set in the ini file,
        # we make a first scan of the items and determine for each position
        # the list of timepoints.
        # Then, we can assign to each position a dictionary that assigns to each timepoint
        # its index (after ordering).
        if self.use_frame_indices:
            #all_times = list(set([int(item[Dimensions.Time]) if Dimensions.Time in item else 0
            #                      for item in dimension_items]))
            #all_times.sort()
            first_pass = {}
            for item in dimension_items:
                position = item[Dimensions.Position]
                if not position in first_pass:
                    first_pass[position] = []

                if Dimensions.Time in item:
                    time_val = int(item[Dimensions.Time])
                else:
                    time_val = 0
                first_pass[position].append(time_val)

            time_index_correspondence = {}
            for pos in first_pass.keys():
                first_pass[position].sort()
                time_index_correspondence[pos] = dict(
                    zip(first_pass[position],
                        range(len(first_pass[position]))))

        for item in dimension_items:
            # import image info only once
            if not has_xy:
                has_xy = True
                info = ccore.ImageImportInfo(
                    os.path.join(self.path, item['filename']))

                self.meta_data.set_image_info(info)
                self.has_multi_images = False  #info.images > 1

            # position
            position = item[Dimensions.Position]
            if not position in lookup:
                lookup[position] = {}

            # time
            if Dimensions.Time in item:
                time_from_filename = int(item[Dimensions.Time])
            else:
                time_from_filename = 0
                item[Dimensions.Time] = str(time_from_filename)

            if self.use_frame_indices:
                time = time_index_correspondence[position][time_from_filename]
            else:
                time = time_from_filename
            if not time in lookup[position]:
                lookup[position][time] = {}

            # channels
            if Dimensions.Channel in item:
                channel = item[Dimensions.Channel]
            else:
                channel = '1'
                item[Dimensions.Channel] = channel
            if not channel in lookup[position][time]:
                lookup[position][time][channel] = {}

            # leave zslice optional.
            # in case of multi-images it must not be defined
            if Dimensions.ZSlice in item:
                zslice = item[Dimensions.ZSlice]
            else:
                zslice = 0
                item[Dimensions.ZSlice] = zslice
            if zslice == '':
                zslice = None
            if not zslice is None:
                zslice = int(zslice)
            if not zslice in lookup[position][time][channel]:
                lookup[position][time][channel][zslice] = item['filename']

            # allow to read timestamps from file if not present
            if MetaInfo.Timestamp in item:
                timestamp = float(item[MetaInfo.Timestamp])
                self.meta_data.append_absolute_time(position, time, timestamp)
            elif self.timestamps_from_file in ['mtime', 'ctime']:
                filename_full = os.path.join(self.path, item['filename'])
                if self.timestamps_from_file == 'mtime':
                    timestamp = os.path.getmtime(filename_full)
                else:
                    timestamp = os.path.getctime(filename_full)
                item[MetaInfo.Timestamp] = timestamp
                self.meta_data.append_absolute_time(position, time, timestamp)

            if MetaInfo.Well in item:
                well = item[MetaInfo.Well]
                subwell = item.get(MetaInfo.Subwell, None)
                self.meta_data.append_well_subwell_info(
                    position, well, subwell)

            if (self.has_multi_images
                    and self.multi_image == self.MULTIIMAGE_USE_ZSLICE):
                if not zslice is None:
                    raise ValueError(
                        'Multi-image assigned for zslice conflicts'
                        ' with zslice token in filename!')
                zslices.extend(range(1, info.images + 1))
            else:
                zslices.append(zslice)

            positions.append(position)
            times.append(time)
            channels.append(channel)

        self.meta_data.positions = tuple(sorted(set(positions)))

        # assure that all items of one dimension are of same length
        times = set(times)
        channels = set(channels)
        zslices = set(zslices)
        # find overall valid number of frames
        for p in lookup:
            times = times.intersection(lookup[p].keys())
        # find overall valid channels/zslices based on overall valid frames
        for p in lookup:
            for t in times:
                channels = channels.intersection(lookup[p][t].keys())
                for c in channels:
                    zslices = zslices.intersection(lookup[p][t][c].keys())
        self.meta_data.times = sorted(times)
        self.meta_data.channels = sorted(channels)
        self.meta_data.zslices = sorted(zslices)
        self.meta_data.image_files = len(dimension_items)

        print('Build time: %s' % s.stop())
        return lookup

    def _get_dimension_items(self):
        raise NotImplementedError()