Example #1
0
    def fix(self, mode=None, microscope=None, out=None, pad=0, start=1):
        """
        Fixes wrong data in headers.

        Mode determines which values are fixed. Currently defined modes are:
          - 'polara_fei-tomo': images obtained on Polara (at MPI of 
          Biochemistry) using FEI tomography package and saved in EM 
          format.
          - 'krios_fei-tomo': images obtained on Krios (at MPI of 
          Biochemistry) using FEI tomography package and saved in EM 
          format.
          - 'cm300': images from cm300 in EM format
          - None: doesn't do anyhing
          
        If mode is 'polara_fei-tomo', then arg microscope has to be specified. 
        The allowed values are specified in microscope_db.py. Currently (r564)
        these are: 'polara-1_01-07', 'polara-1_01-09' and 'polara-2_01-09'.

        Works for individual images only (not for stacks), because stacks
        are typically recorded by SerialEM and do not need fixing.

        Arguments:
          - out: directory where the fixed images are written. The fixed and
          the original images have the same base names.
          - mode: fix mode
        """

        # parse arguments
        #if path is None: path = self.path
        #if mode is None: mode = self.mode

        # check for out, pad and start also?

        # make out directory if it doesn't exists
        if (out is not None) and (not os.path.isdir(out)):
            os.makedirs(out)

        # loop over images
        images_iter = self.images(out=out, pad=pad, start=start)
        for (in_path, out_path) in images_iter:

            # read image file
            image = ImageIO(file=in_path)
            image.read()

            # fix
            image.fix(mode=mode, microscope=microscope)

            # write fixed files
            image.write(file=out_path)
Example #2
0
    def sort(self,
             seq=None,
             out=None,
             pad=0,
             start=1,
             fix_mode=None,
             microscope=None,
             limit=None,
             limit_mode='std',
             size=5,
             byte_order=None,
             test=False):
        """
        Sorts series, fixes image headers, corrects the data and writes the
        sorted and corrected images. 

        A series is sorted by tilt angle that is read from each image, or by the
        elements of seq (not necessarily angles) if given.

        Sorted images names have the form:
          directory/name + number + extension.
        where out is: directory/name_.extension and numbers start with start
        argument and are padded with pad (argument) number of zeros (see
        self.images).

        Argument fix_mode detemines how the headers are fixed:
          - None: no fixing
          - 'polara_fei-tomo': for series obtained on polara with the FEI tomo
          software
          - 'krios_fei-tomo': for series obtained on krios with the FEI tomo
          software
          - 'cm300': for series from CM300
        (see pyto.io.image_io). 

        If fix_mode is 'polara_fei-tomo', then arg microscope has to be 
        specified. The allowed values are specified in microscope_db.py. 
        Currently (r564) these are: 'polara-1_01-07', 'polara-1_01-09' and 
        'polara-2_01-09'.

        If fix_mode is None, microscope does nor need to be specified.
        Series recorded by SerialEM typically do not need fixing.

        Works for individual images only (not for stacks).

        Arguments:
          - seq: if specified this sequence used for sorting projection,
          otherwise tilt angles are used
          - out: sorted series path
          - pad: number of digits of a projection number in the sorted 
          series file name
          - start: start number for sorted series file names 
          - fix_mode: determined if and how headers are fixed
          - microscope: microscope type, see pyto.io.microscope_db
          - limit_mode: 'abs' or 'std'
          - limit: absolute greyscale limit if limit_mode is 'abs', or the 
          number of stds above and below the mean 
          - size: size of the subarray used to find the replacement value 
          for a voxel that's out of the limits 
          - byte_order: '<' or '>', default is the byte order of the machine
          - test: if True all steps are done except writing corrected images
        
        """

        # shortcuts
        path = self.path
        match_mode = self.mode

        # make tilt angles - file names dictionary
        # ToDo: use self.sortPath() instead
        in_paths = []
        images_iter = self.images(mode=match_mode)
        if seq is None:
            seq = []

            # get tilt angles from file headers
            for in_path in images_iter:
                image = ImageIO(file=in_path)
                image.readHeader()
                seq.append(image.tiltAngle)
                in_paths.append(in_path)
                image.file_.close()

        else:

            # use seq to sort
            for in_path in images_iter:
                in_paths.append(in_path)

        # sort (note: dictionary angle:in_path fails for multiple files with
        # same angles)
        seq_arr = numpy.array(seq)
        in_paths_arr = numpy.array(in_paths)
        sort_ind = seq_arr.argsort()
        sorted_seq = seq_arr[sort_ind]
        sorted_in_paths = in_paths_arr[sort_ind]

        # parse out and make out directory if it doesn't exists
        if out is not None:
            out_dir, out_base_pat = os.path.split(out)
            if out_dir == '':
                out_dir = '.'
            if (not test) and (not os.path.isdir(out_dir)):
                os.makedirs(out_dir)
        else:
            out_path = None

        # initialize file counter
        if start is None:
            ind = None
        else:
            ind = start - 1

        # loop over sorted in files
        for (item, in_path) in zip(sorted_seq, sorted_in_paths):
            if ind is not None: ind += 1

            # parse in file path
            in_dir, in_base = os.path.split(in_path)

            if out is not None:

                # make out file path
                out_base = self.convertBase(in_base=in_base,
                                            out_base=out_base_pat,
                                            pad=pad,
                                            index=ind)
                out_path = os.path.join(out_dir, out_base)

                # read files
                im_io = ImageIO(file=in_path)
                im_io.read()

                # log
                logging.info("%5.1f: %s -> %s  %6.1f %6.1f" \
                                 % (item, in_path, out_path, \
                                        im_io.data.mean(), im_io.data.std()))

                # fix
                if fix_mode is not None:
                    im_io.fix(mode=fix_mode, microscope=microscope)

                # limit
                if limit is not None:
                    image = Image(im_io.data)
                    image.limit(limit=limit, mode=limit_mode, size=size)

                # write fixed file
                if not test:
                    if byte_order is None:
                        byte_order = im_io.machineByteOrder
                    im_io.write(file=out_path,
                                byteOrder=byte_order,
                                data=image.data)

            else:

                logging.info(" " + str(item) + ": " + in_path + " -> "\
                             + str(out_path))