Exemplo n.º 1
0
def averageImages(
    listImages,
    output=None,
    threshold=0.1,
    minimum=None,
    maximum=None,
    darks=None,
    flats=None,
    filter_="mean",
    correct_flat_from_dark=False,
    cutoff=None,
    quantiles=None,
    fformat="edf",
):
    """
    Takes a list of filenames and create an average frame discarding all saturated pixels.

    @param listImages: list of string representing the filenames
    @param output: name of the optional output file
    @param threshold: what is the upper limit? all pixel > max*(1-threshold) are discareded.
    @param minimum: minimum valid value or True
    @param maximum: maximum valid value
    @param darks: list of dark current images for subtraction
    @param flats: list of flat field images for division
    @param filter_: can be maximum, mean or median (default=mean)
    @param correct_flat_from_dark: shall the flat be re-corrected ?
    @param cutoff: keep all data where (I-center)/std < cutoff
    @param quantiles: 2-tuple containing the lower and upper quantile (0<q<1) to average out.
    @param fformat: file format of the output image, default: edf
    @return: filename with the data or the data ndarray in case format=None
    """
    if filter_ not in ["min", "max", "median", "mean", "sum", "quantiles"]:
        logger.warning("Filter %s not understood. switch to mean filter" % filter_)
        filter_ = "mean"
    ld = len(listImages)
    sumImg = None
    do_dark = darks is not None
    do_flat = flats is not None
    dark = None
    flat = None
    big_img = None
    for idx, fn in enumerate(listImages[:]):
        if isinstance(fn, six.string_types):
            logger.info("Reading %s" % fn)
            ds = fabio.open(fn).data
        else:
            ds = fn
            fn = "numpy_array"
            listImages[idx] = fn
        logger.debug("Intensity range for %s is %s --> %s", fn, ds.min(), ds.max())
        shape = ds.shape
        if do_dark and (dark is None):
            if "ndim" in dir(darks) and darks.ndim == 3:
                dark = averageDark(darks, center_method="mean", cutoff=4)
            elif ("__len__" in dir(darks)) and isinstance(darks[0], six.string_types):
                dark = averageDark([fabio.open(f).data for f in darks if exists(f)], center_method="mean", cutoff=4)
            elif ("__len__" in dir(darks)) and ("ndim" in dir(darks[0])) and (darks[0].ndim == 2):
                dark = averageDark(darks, center_method="mean", cutoff=4)
        if do_flat and (flat is None):
            if "ndim" in dir(flats) and flats.ndim == 3:
                flat = averageDark(flats, center_method="mean", cutoff=4)
            elif ("__len__" in dir(flats)) and isinstance(flats[0], six.string_types):
                flat = averageDark([fabio.open(f).data for f in flats if exists(f)], center_method="mean", cutoff=4)
            elif ("__len__" in dir(flats)) and ("ndim" in dir(flats[0])) and (flats[0].ndim == 2):
                flat = averageDark(flats, center_method="mean", cutoff=4)
            else:
                logger.warning("there is some wrong with flats=%s" % (flats))
            if correct_flat_from_dark:
                flat -= dark
            flat[numpy.where(flat <= 0)] = 1.0
        correctedImg = numpy.ascontiguousarray(ds, numpy.float32)
        if threshold or minimum or maximum:
            correctedImg = removeSaturatedPixel(correctedImg, threshold, minimum, maximum)
        if do_dark:
            correctedImg -= dark
        if do_flat:
            correctedImg /= flat
        if cutoff or quantiles or (filter_ in ["median", "quantiles"]):
            if big_img is None:
                logger.info("Big array allocation for median filter or cut-off")
                big_img = numpy.zeros((ld, shape[0], shape[1]), dtype=numpy.float32)
            big_img[idx, :, :] = correctedImg
        elif filter_ == "max":
            if sumImg is None:
                sumImg = correctedImg
            else:
                sumImg = numpy.maximum(correctedImg, sumImg)
        elif filter_ == "min":
            if sumImg is None:
                sumImg = correctedImg
            else:
                sumImg = numpy.minimum(correctedImg, sumImg)
        elif filter_ == "mean":
            if sumImg is None:
                sumImg = correctedImg
            else:
                sumImg += correctedImg
        elif filter_ == "sum":
            if sumImg is None:
                sumImg = correctedImg
            else:
                sumImg += correctedImg
    if cutoff or quantiles or (filter_ in ["median", "quantiles"]):
        datared = averageDark(big_img, filter_, cutoff, quantiles)
    else:
        if filter_ in ["max", "min"]:
            datared = numpy.ascontiguousarray(sumImg, dtype=numpy.float32)
        elif filter_ == "mean":
            datared = sumImg / numpy.float32(ld)
        elif filter_ == "sum":
            datared = sumImg / numpy.float32(ld)
    logger.debug("Intensity range in merged dataset : %s --> %s", datared.min(), datared.max())
    if fformat is not None:
        if fformat.startswith("."):
            fformat = fformat.lstrip(".")
        if output is None:
            prefix = ""
            for ch in zip(*listImages):
                c = ch[0]
                good = True
                if c in ["*", "?", "[", "{", "("]:
                    good = False
                    break
                for i in ch:
                    if i != c:
                        good = False
                        break
                if good:
                    prefix += c
                else:
                    break
            if filter_ == "max":
                output = "maxfilt%02i-%s.%s" % (ld, prefix, fformat)
            elif filter_ == "median":
                output = "medfilt%02i-%s.%s" % (ld, prefix, fformat)
            elif filter_ == "median":
                output = "meanfilt%02i-%s.%s" % (ld, prefix, fformat)
            else:
                output = "merged%02i-%s.%s" % (ld, prefix, fformat)
        if fformat and output:
            if "." in fformat:  # in case "edf.gz"
                fformat = fformat.split(".")[0]
            fabiomod = fabio.__getattribute__(fformat + "image")
            fabioclass = fabiomod.__getattribute__(fformat + "image")
            header = {"method": filter_, "nframes": ld, "cutoff": str(cutoff), "quantiles": str(quantiles)}
            form = "merged_file_%%0%ii" % len(str(len(listImages)))
            header_list = ["method", "nframes", "cutoff"]
            for i, f in enumerate(listImages):
                name = form % i
                header[name] = f
                header_list.append(name)
            fimg = fabioclass(data=datared, header=header)
            #            if "header_keys" in dir(fimg):
            fimg.header_keys = header_list

            if filter_ == "sum":
                fimg = fabioclass(data=numpy.int32(datared * numpy.float32(ld)), header=header)

            fimg.write(output)
            logger.info("Wrote %s" % output)
        return output
    else:
        return datared
Exemplo n.º 2
0
def averageImages(listImages,
                  output=None,
                  threshold=0.1,
                  minimum=None,
                  maximum=None,
                  darks=None,
                  flats=None,
                  filter_="mean",
                  correct_flat_from_dark=False,
                  cutoff=None,
                  format="edf"):
    """
    Takes a list of filenames and create an average frame discarding all saturated pixels.

    @param listImages: list of string representing the filenames
    @param output: name of the optional output file
    @param threshold: what is the upper limit? all pixel > max*(1-threshold) are discareded.
    @param minimum: minimum valid value or True
    @param maximum: maximum valid value
    @param darks: list of dark current images for subtraction
    @param flats: list of flat field images for division
    @param filter_: can be maximum, mean or median (default=mean)
    @param correct_flat_from_dark: shall the flat be re-corrected ?
    @param cutoff: keep all data where (I-center)/std < cutoff
    @return: filename with the data or the data ndarray in case format=None
    """
    if filter_ not in ["min", "max", "median", "mean"]:
        logger.warning("Filter %s not understood. switch to mean filter")
        filter_ = "mean"
    ld = len(listImages)
    sumImg = None
    do_dark = (darks is not None)
    do_flat = (flats is not None)
    dark = None
    flat = None
    big_img = None
    for idx, fn in enumerate(listImages[:]):
        if type(fn) in types.StringTypes:
            logger.info("Reading %s" % fn)
            ds = fabio.open(fn).data
        else:
            ds = fn
            fn = "numpy_array"
            listImages[idx] = fn
        logger.debug("Intensity range for %s is %s --> %s", fn, ds.min(),
                     ds.max())
        shape = ds.shape
        if sumImg is None:
            sumImg = numpy.zeros((shape[0], shape[1]), dtype=numpy.float32)
        if do_dark and (dark is None):
            if "ndim" in dir(darks) and darks.ndim == 3:
                dark = averageDark(darks, center_method="mean", cutoff=4)
            elif ("__len__" in dir(darks)) and (type(darks[0])
                                                in types.StringTypes):
                dark = averageDark(
                    [fabio.open(f).data for f in darks if os.path.exists(f)],
                    center_method="mean",
                    cutoff=4)
            elif ("__len__" in dir(darks)) and ("ndim" in dir(
                    darks[0])) and (darks[0].ndim == 2):
                dark = averageDark(darks, center_method="mean", cutoff=4)
        if do_flat and (flat is None):
            if "ndim" in dir(flats) and flats.ndim == 3:
                flat = averageDark(flats, center_method="mean", cutoff=4)
            elif ("__len__" in dir(flats)) and (type(flats[0])
                                                in types.StringTypes):
                flat = averageDark(
                    [fabio.open(f).data for f in flats if os.path.exists(f)],
                    center_method="mean",
                    cutoff=4)
            elif ("__len__" in dir(flats)) and ("ndim" in dir(
                    flats[0])) and (flats[0].ndim == 2):
                flat = averageDark(flats, center_method="mean", cutoff=4)
            else:
                logger.warning("there is some wrong with flats=%s" % (flats))
            if correct_flat_from_dark:
                flat -= dark
            flat[numpy.where(flat <= 0)] = 1.0
        correctedImg = numpy.ascontiguousarray(ds, numpy.float32)
        if threshold or minimum or maximum:
            correctedImg = removeSaturatedPixel(correctedImg, threshold,
                                                minimum, maximum)
        if do_dark:
            correctedImg -= dark
        if do_flat:
            correctedImg /= flat
        if (cutoff or (filter_ == "median")):
            if big_img is None:
                logger.info(
                    "Big array allocation for median filter or cut-off")
                big_img = numpy.zeros((ld, shape[0], shape[1]),
                                      dtype=numpy.float32)
            big_img[idx, :, :] = correctedImg
        elif filter_ == "max":
            sumImg = numpy.maximum(correctedImg, sumImg)
        elif filter_ == "min":
            sumImg = numpy.minimum(correctedImg, sumImg)
        elif filter_ == "mean":
            sumImg += correctedImg
    if cutoff or (filter_ == "median"):
        datared = averageDark(big_img, filter_, cutoff)
    else:
        if filter_ in ["max", "min"]:
            datared = numpy.ascontiguousarray(sumImg, dtype=numpy.float32)
        elif filter_ == "mean":
            datared = sumImg / numpy.float32(ld)
    logger.debug("Intensity range in merged dataset : %s --> %s",
                 datared.min(), datared.max())
    if format is not None:
        if format.startswith("."):
            format = format.lstrip(".")
        if (output is None):
            prefix = ""
            for ch in zip(*listImages):
                c = ch[0]
                good = True
                for i in ch:
                    if i != c:
                        good = False
                        break
                if good:
                    prefix += c
                else:
                    break
            if filter_ == "max":
                output = "maxfilt%02i-%s.%s" % (ld, prefix, format)
            elif filter_ == "median":
                output = "medfilt%02i-%s.%s" % (ld, prefix, format)
            elif filter_ == "median":
                output = "meanfilt%02i-%s.%s" % (ld, prefix, format)
            else:
                output = "merged%02i-%s.%s" % (ld, prefix, format)
        if format and output:
            if "." in format:  # in case "edf.gz"
                format = format.split(".")[0]
            fabiomod = fabio.__getattribute__(format + "image")
            fabioclass = fabiomod.__getattribute__(format + "image")
            header = {"method": filter_, "nframes": ld, "cutoff": str(cutoff)}
            form = "merged_file_%%0%ii" % len(str(len(listImages)))
            header_list = ["method", "nframes", "cutoff"]
            for i, f in enumerate(listImages):
                name = form % i
                header[name] = f
                header_list.append(name)
            fimg = fabioclass(data=datared, header=header)
            #            if "header_keys" in dir(fimg):
            fimg.header_keys = header_list

            fimg.write(output)
            logger.info("Wrote %s" % output)
        return output
    else:
        return datared