Source code for LaueTools.IOimagefile

# -*- coding: utf-8 -*-
r"""
IOimagefile module is made for reading data contained in binary image file
fully or partially.

More tools can be found in LaueTools package at sourceforge.net and gitlab.esrf.fr
March 2020
"""
__author__ = "Jean-Sebastien Micha, CRG-IF BM32 @ ESRF"

# built-in modules
import sys
import os
import copy
import struct

# third party modules
try:
    import fabio

    FABIO_EXISTS = True
except ImportError:
    print("Missing fabio module. Please install it if you need open some tiff images "
            "from the sCMOS camera")
    FABIO_EXISTS = False

try:
    from libtiff import TIFF, libtiff_ctypes

    libtiff_ctypes.suppress_warnings()
    LIBTIFF_EXISTS = True
except ImportError:
    print("Missing library libtiff, Please install: pylibtiff if you need open some tiff images")
    LIBTIFF_EXISTS = False

try:
    from PIL import Image

    PIL_EXISTS = True
except ImportError:
    print("Missing python module called PIL. Please install it if you need open some tiff "
            "images from vhr camera")
    PIL_EXISTS = False
import numpy as np


# lauetools modules
if sys.version_info.major == 3:
    from . import dict_LaueTools as DictLT
    from . import imageprocessing as ImProc
else:
    import dict_LaueTools as DictLT
    import imageprocessing as ImProc

listfile = os.listdir(os.curdir)

[docs]def stringint(k, n): r""" returns string of integer k with n zeros padding (by placing zeros before to have n characters) :param k: integer to convert :param n: nb of digits for zero padding :return: string of length n containing integer k Example: 1 -> '0001' 15 -> '0015' """ # strint = str(k) # res = '0' * (n - len(strint)) + strint encodingdigits = "{" + ":0{}".format(int(n)) + "}" res = encodingdigits % k return res
# --- ---------------- read images functions
[docs]def setfilename(imagefilename, imageindex, nbdigits=4, CCDLabel=None): r""" reconstruct filename string from imagefilename and update filename index with imageindex :param imagefilename: filename string (full path or not) :param imageindex: index in filename :type imageindex: string :return filename: input filename with index replaced by input imageindex :rtype: string """ # print "imagefilename",imagefilename if imagefilename.endswith("mccd"): lenext = 5 #length of extension including '.' imagefilename = imagefilename[: -(lenext + nbdigits)] + "{:04d}.mccd".format(imageindex) elif CCDLabel in ("sCMOS", "sCMOS_fliplr"): #default file extension for sCMOS camera ext = "tif" lenext = 4 #length of extension including '.' if imagefilename.endswith("tiff"): ext = "tiff" lenext = 5 # zero padded index for filename if nbdigits is not None: if imagefilename.endswith(ext): imagefilename = imagefilename[: -(lenext + nbdigits)] + "{:04d}.{}".format( imageindex, ext) elif imagefilename.endswith(ext+".gz"): imagefilename = imagefilename[: -(lenext+3 + nbdigits)] + "{:04d}.{}.gz".format(imageindex, ext) # no zero padded index for filename else: if imagefilename.endswith(ext): prefix, _ = imagefilename.split(".") prefix0 = prefix.split("_")[0] if imageindex > 9999: imagefilename = prefix0 + "_{}.{}".format(imageindex, ext) else: imagefilename = prefix0 + "_{:04d}.{}".format(imageindex, ext) elif CCDLabel in ("EIGER_4Mstack",): # only stackimageindex is changed not imagefilename pass # print "imagefilename archetype", imagefilename elif imagefilename.endswith("mar.tiff"): imagefilename = imagefilename[: -(9 + nbdigits)] + "{:04d}_mar.tiff".format(imageindex) elif imagefilename.endswith("mar.tif"): # requires two underscores with number in between # map1_105_mar.tif sname = imagefilename.split("_") if len(sname) >= 4: # pathfilename contain more than 1 underscore sname2 = sname[-2] + "_" + sname[-1] prefix = imagefilename.rstrip(sname2) else: prefix = imagefilename.split("_")[0] imagefilename = prefix + "_{}_mar.tif".format(imageindex) # special case for image id15 frelon corrected form distorsion elif imagefilename.endswith((".tif", ".edf")): if CCDLabel in ("ImageStar_raw", ): prefixwihtindex = imagefilename[:-4] prefixwithindex_list = list(prefixwihtindex) indexnodigit = 0 while len(prefixwithindex_list) > 0: lastelem = prefixwithindex_list.pop(-1) print("lastelem", lastelem) if not lastelem.isdigit(): break indexnodigit += 1 prefix = prefixwihtindex[:-(indexnodigit)] print("prefix", prefix) imagefilename = prefix + "{}.tif".format(imageindex) else: suffix = imagefilename[-4:] prefix = imagefilename[: -(4 + nbdigits)] imagefilename = prefix + "{:04d}{}".format(imageindex, suffix) elif imagefilename.endswith("mccd"): imagefilename = imagefilename[: -(5 + nbdigits)] + "{:04d}.mccd".format(imageindex) elif imagefilename.endswith("edf"): imagefilename = imagefilename[: -(4 + nbdigits)] + "{:04d}.edf".format(imageindex) elif imagefilename.endswith("unstacked"): imagefilename = imagefilename[: -(10 + nbdigits)] + "{:04d}.unstacked".format(imageindex) # print "set filename to:", imagefilename return imagefilename
[docs]def getIndex_fromfilename(imagefilename, nbdigits=4, CCDLabel=None, stackimageindex=-1): r""" get integer index from imagefilename string :param imagefilename: filename string (full path or not) :return: file index """ if CCDLabel in ("sCMOS", "sCMOS_fliplr"): #default file extension for sCMOS camera ext = "tif" lenext = 4 #length of extension including '.' if imagefilename.endswith("tiff"): ext = "tiff" lenext = 5 print(imagefilename) if nbdigits is not None: if imagefilename.endswith(ext): imageindex = int(imagefilename[-(lenext + nbdigits) : -(lenext)]) elif imagefilename.endswith(ext+".gz"): imageindex = int(imagefilename[-(lenext+3 + nbdigits) : -(lenext+3)]) else: if imagefilename.endswith(ext): prefix, _ = imagefilename.split(".") imageindex = int(prefix.split("_")[1]) # for stacked images we return the position of image data in the stack as imagefileindex elif CCDLabel in ("EIGER_4Mstack",): imageindex = stackimageindex elif imagefilename.endswith("mar.tiff"): imageindex = int(imagefilename[-(9 + nbdigits) : -9]) elif imagefilename.endswith("tiff"): imageindex = int(imagefilename[-(5 + nbdigits) : -5]) elif imagefilename.endswith("mar.tif"): imageindex = int(imagefilename.split("_")[-2]) elif imagefilename.endswith(".tif"): # TODO: treat the case of HN56.tif without underscore (see setfilename) imageindex = int(imagefilename.split("_")[-1][:-4]) elif imagefilename.endswith("mccd"): imageindex = int(imagefilename[-(5 + nbdigits) : -5]) elif imagefilename.endswith("edf"): imageindex = int(imagefilename[-(4 + nbdigits) : -4]) elif imagefilename.endswith("unstacked"): imageindex = int(imagefilename[-(10 + nbdigits) : -10]) return imageindex
[docs]def getfilename(dirname, imfileprefix, imfilesuffix=None, numim=None, nbdigits_filename=4): """ to get the global file name (name+path) for given components of the name put %4d instead of stringint """ fileim = imfileprefix + stringint(numim, nbdigits_filename) + imfilesuffix filename = os.path.join(dirname, fileim) return filename
[docs]def getwildcardstring(CCDlabel): r""" return smart wildcard to open binary CCD image file with priority of CCD type of CCDlabel :param CCDlabel: string label defining the CCD type :type CCDlabel: str :return: string from concatenated strings to be used in wxpython open file dialog box :rtype: str .. see also:: - :func:`getIndex_fromfilename` - LaueToolsGUI.AskUserfilename - wx.FileDialog .. example:: >>> from readmccd import getwildcardstring >>> getwildcardstring('MARCCD165') 'MARCCD, ROPER(*.mccd)|*mccd|mar tif(*.tif)|*_mar.tiff|tiff(*.tiff)|*tiff|Princeton(*.spe)|*spe|Frelon(*.edf)|*edf|tif(*.tif)|*tif|All files(*)|*' """ ALL_EXTENSIONS = ["mccd", "_mar.tiff", "tiff", "spe", "edf", "tif", "h5", ""] INFO_EXTENSIONS = ["MARCCD, ROPER(*.mccd)", "mar tif(*.tif)", "tiff(*.tiff)", "Princeton(*.spe)", "Frelon(*.edf)", "tif(*.tif)", "hdf5(*.h5)", "All files(*)"] extensions = copy.copy(ALL_EXTENSIONS) infos = copy.copy(INFO_EXTENSIONS) chosen_extension = DictLT.dict_CCD[CCDlabel][7] if chosen_extension in ALL_EXTENSIONS: index = ALL_EXTENSIONS.index(chosen_extension) ce = extensions.pop(index) extensions.insert(0, ce) inf = infos.pop(index) infos.insert(0, inf) wcd = "" for inf, ext in zip(infos, extensions): wcd += "{}|*{}|".format(inf, ext) wildcard_extensions = wcd[:-1] return wildcard_extensions
[docs]def getpixelValue(filename, x, y, ccdtypegeometry="edf"): r"""return pixel value at x,y .. warning:: Very old function. To be checked. Use better readpixelvalue in plotdip.py :param filename: path to image file :type filename: str :param x: x pixel value :type x: int :param y: y pixel value :type y: int :param ccdtypegeometry: CCD label, defaults to "edf" :type ccdtypegeometry: str, optional :return: pixel intensity :rtype: int """ if ccdtypegeometry == "edf": # frelon camera as mounted on BM32 Oct2012 y = 2047 - y if ccdtypegeometry in ("mccd",): pass f = open(filename, "rb") f.seek(1024 + 2 * (2048 * y + x)) val = struct.unpack("H", f.read(2)) f.close() return val[0]
[docs]def readheader(filename, offset=4096, CCDLabel="MARCCD165"): r""" return header in a raw format default offset for marccd image """ if CCDLabel.startswith("sCMOS"): filesize = os.path.getsize(filename) framedim = DictLT.dict_CCD[CCDLabel][0] offset = filesize - np.prod(framedim) * 2 f = open(filename, "rb") myheader = f.read(offset) myheader.replace("\x00", " ") f.close() return myheader
[docs]def read_header_marccd(filename): r""" return string of parameters found in header in marccd image file .mccd - print allsentences displays the header - use allsentences.split('\n') to get a list """ f = open(filename, "rb") f.seek(2048) posbyte = 0 allsentences = "" for _ in list(range(32)): tt = f.read(32) s1 = tt.strip("\x00") if s1 != "": allsentences += s1 + "\n" # print posbyte, s1 posbyte += 32 tt = f.read(1024) s1 = tt.strip("\x00") if s1 != "": allsentences += s1 + "\n" f.close() return allsentences
[docs]def read_header_marccd2(filename): r""" return string of parameters comments and exposure time found in header in marccd image file .mccd - print allsentences displays the header - use allsentences.split('\n') to get a list """ f = open(filename, "rb") f.seek(3072) tt = f.read(512) # from beamline designed input dataset_comments = tt.strip("\x00") f.seek(1024 + 2 * 256 + 128 + 12) s = struct.Struct("I I I") unpacked_data = s.unpack(f.read(3 * 4)) # print 'Unpacked Values:', unpacked_data #integration_time, expo_time, readout_time = unpacked_data _, expo_time, _ = unpacked_data f.close() return dataset_comments, expo_time
[docs]def read_header_scmos(filename): r""" return string of parameters comments and exposure time found in header in scmis image file .tif - print allsentences displays the header - use allsentences.split('\n') to get a list """ if not PIL_EXISTS: return {} img = Image.open(filename) # img.tag.keys() # tag[270] = (u'0 (thf=-50.4850 mon=24923 exposure=0.400)',) dictpar = {} strcom = img.tag[270][0] print('read_header_scmos', strcom, type(strcom)) si = strcom.index("(") fi = strcom.index(")") listpar = strcom[si + 1 : fi].split() # print "listpar",listpar for elem in listpar: if "=" in elem: key, val = elem.split("=") dictpar[key] = float(val) return dictpar
[docs]def read_motorsposition_fromheader(filename, CCDLabel="MARCCD165"): r""" return xyzpositions, expo_time from image file header available for "MARCCD165", "sCMOS", "sCMOS_fliplr" """ if CCDLabel in ("MARCCD165",): dataset_comments, expo_time = read_header_marccd2(filename) xyz = dataset_comments.split(" ")[:3] xyzpositions = [] for pos in xyz: xyzpositions.append(float(pos)) elif CCDLabel in ("sCMOS", "sCMOS_fliplr"): dictpar = {} import re img = Image.open(filename) ff = img.tag[315] aa = re.findall(r"([^:]+)=([^:]+)(?:,|$)", ff[0]) listeq = aa[0][0].split(" ") for elem in listeq: if "Xech" in elem or "Yech" in elem or "Zech" in elem: dictpar[elem.lstrip("(")] = float(elem.rstrip(")")) headerdict = read_header_scmos(filename) if headerdict: expo_time = headerdict["exposure"] xyzpositions = [] for motorname in ("Xech", "Yech", "Zech"): xyzpositions.append(dictpar[motorname]) return xyzpositions, expo_time
[docs]def readoneimage_full(filename, frametype="mccd", dirname=None): r""" too SLOW! reads 1 entire image (marCCD format) :return: PILimage, image object of PIL module (16 bits integer) and arrayofdata: 2D array of intensity #TODO: manage framedim like readoneimage() just below""" if frametype == "mccd": shapeCCD = (2048, 2048) elif frametype == "martiff": # opposite of fit2d displays in loading data shapeCCD = (2591, 2751) elif frametype == "spe": # opposite of fit2d displays in loading data shapeCCD = (2048, 2048) if dirname is None: dirname = os.curdir pilimage = Image.open(os.path.join(dirname, filename)) ravdata = np.array(pilimage.getdata()) return pilimage, np.reshape(ravdata, shapeCCD)
[docs]def readCCDimage(filename, CCDLabel="MARCCD165", dirname=None, stackimageindex=-1, verbose=0): r"""Read raw data binary image file. Read raw data binary image file and return pixel intensity 2D array such as to fit the data (2theta, chi) scattering angles representation convention. :param filename: path to image file (fullpath if ` dirname` =None) :type filename: str :param CCDLabel: label, defaults to "MARCCD165" :type CCDLabel: str, optional :param dirname: folder path, defaults to None :type dirname: str, optional :param stackimageindex: index of images bunch, defaults to -1 :type stackimageindex: int, optional :param verbose: 0 or 1, defaults to 0 :type verbose: int, optional :raises ValueError: if data format and CCD parameters from label are not compatible :return: - dataimage, 2D array image data pixel intensity properly oriented - framedim, iterable of 2 integers shape of dataimage - fliprot : string, key for CCD frame transform to orient image :rtype: tuple of 3 elements """ (framedim, _, _, fliprot, offsetheader, formatdata, _, _) = DictLT.dict_CCD[CCDLabel] USE_RAW_METHOD = False print("CCDLabel in readCCDimage", CCDLabel) # if extension != extension: # print "warning : file extension does not match CCD type set in Set CCD File Parameters" if FABIO_EXISTS: if CCDLabel in ('MARCCD165', "EDF", "EIGER_4M", "EIGER_1M", "sCMOS", "sCMOS_fliplr", "sCMOS_fliplr_16M", "sCMOS_16M", "Rayonix MX170-HS", 'psl_weiwei'): print('----> Using fabio ... to open %s\n'%filename) # warning import Image # for well read of header only if dirname is not None: img = fabio.open(os.path.join(dirname, filename)) else: img = fabio.open(filename) dataimage = img.data framedim = dataimage.shape # pythonic way to change immutable tuple... initframedim = list(DictLT.dict_CCD[CCDLabel][0]) initframedim[0] = framedim[0] initframedim[1] = framedim[1] initframedim = tuple(initframedim) else: USE_RAW_METHOD = True elif CCDLabel in ("EIGER_4Mstack", ): import tables as Tab if dirname is not None: pathtofile = os.path.join(dirname, filename) else: pathtofile = filename # TODO check to correct version transition if Tab.__version__ >= "3.4.2": hdf5file = Tab.open_file(pathtofile) else: hdf5file = Tab.openFile(pathtofile) print("opening hdf5 stacked data table") alldata = hdf5file.root.entry.data.data print("alldata.shape", alldata.shape) dataimage = alldata[stackimageindex] framedim = dataimage.shape elif LIBTIFF_EXISTS: print("----> Using libtiff...") if CCDLabel in ("sCMOS", "MARCCD165", "TIFF Format", "FRELONID15_corrected", "VHR_PSI", "VHR_DLS", "MARCCD225", "Andrea", "pnCCD_Tuba"): # print "tiff format", CCDLabel # print "dirname, filename", dirname, filename if dirname is not None: tifimage = TIFF.open(os.path.join(dirname, filename), mode="r") else: tifimage = TIFF.open(filename, mode="r") dataimage = tifimage.read_image() framedim = (int(tifimage.GetField("ImageLength")), int(tifimage.GetField("ImageWidth"))) if tifimage.IsByteSwapped(): dataimage = dataimage.byteswap() else: USE_RAW_METHOD = True elif PIL_EXISTS: print("using PIL's module Image") if CCDLabel in ("sCMOS", "MARCCD165"): print('PIL is too slow. Better install libtiff or fabio. Meanwhile ...') USE_RAW_METHOD = True elif CCDLabel in ("VHR_PSI", "VHR_DLS", "MARCCD225", "Andrea", "pnCCD_Tuba"): # data are compressed! if dirname is not None: fullpath = os.path.join(dirname, filename) else: fullpath = filename im = Image.open(fullpath, "r") dataimage = np.array(im.getdata()).reshape(framedim) # RAW method knowing or deducing offsetheader and dataformat if USE_RAW_METHOD: print("----> not using libtiff, nor fabio, nor PIL!!! ") if CCDLabel in ("MARCCD165",): print("for MARCCD not using libtiff, raw method ...") # offsetheader may change ... #filesize = os.path.getsize(os.path.join(dirname, filename)) offsetheader = 4096 #filesize - 2048*2048 * 2 # offset header varying elif CCDLabel.startswith("ImageStar_raw"): filesize = os.path.getsize(os.path.join(dirname, filename)) bytes_per_pixels = 2 if CCDLabel.endswith("32bits"): bytes_per_pixels = 4 nbpixels = 1500 if CCDLabel in ("ImageStar_1528x1528",): nbpixels = 1528 offsetheader = filesize - nbpixels * nbpixels * bytes_per_pixels elif CCDLabel in ("sCMOS",): print("for sCMOS not using libtiff, raw method ...") # offsetheader may change ... filesize = os.path.getsize(os.path.join(dirname, filename)) offsetheader = filesize - 2016*2018 * 2 dataimage = readoneimage(filename, framedim=framedim, dirname=dirname, offset=offsetheader, formatdata=formatdata) if CCDLabel in ("FRELONID15_corrected",): dataimage = dataimage.byteswap() if CCDLabel in ("EIGER_4Munstacked",): print("framedim", framedim) print("offsetheader", offsetheader) print("formatdata", formatdata) dataimage = np.ma.masked_where(dataimage > 4000000, dataimage) print("dataimage", dataimage) if verbose: print("CCDLabel: ", CCDLabel) print("nb of pixels", np.shape(dataimage)) # need to reshape data from 1D to 2D try: if len(dataimage.shape) == 1: print("nb elements", len(dataimage)) print("framedim", framedim) print("framedim nb of elements", framedim[0] * framedim[1]) dataimage = np.reshape(dataimage, framedim) except ValueError: raise ValueError( "Selected CCD type :{} may be wrong (or nb of pixels, dimensions...)".format( CCDLabel)) # some array transformations if needed depending on the CCD mounting if fliprot == "spe": dataimage = np.rot90(dataimage, k=1) elif fliprot == "VHR_Feb13": # self.dataimage_ROI = np.rot90(self.dataimage_ROI, k=3) # TODO: do we need this left and right flip ? dataimage = np.fliplr(dataimage) elif fliprot == "sCMOS_fliplr": dataimage = np.fliplr(dataimage) elif fliprot == "vhr": # july 2012 close to diamond monochromator crystal dataimage = np.rot90(dataimage, k=3) dataimage = np.fliplr(dataimage) elif fliprot == "vhrdiamond": # july 2012 close to diamond monochromator crystal dataimage = np.rot90(dataimage, k=3) dataimage = np.fliplr(dataimage) elif fliprot == "frelon2": dataimage = np.flipud(dataimage) # print "framedim",framedim, fliprot return dataimage, framedim, fliprot
[docs]def readoneimage(filename, framedim=(2048, 2048), dirname=None, offset=4096, formatdata="uint16"): r""" returns a 1d array of integers from a binary image file (full data) :param filename: image file name (full path if dirname=0) :type filename: str :param framedim: detector dimensions, defaults to (2048, 2048) :type framedim: tuple of 2 integers, optional :param dirname: folder path, defaults to None :type dirname: str, optional :param offset: file header in byte (octet), defaults to 4096 :type offset: int, optional :param formatdata: numpy format of raw binary image pixel value, defaults to "uint16" :type formatdata: str, optional :return: dataimage : image data pixel intensity :rtype: 1D array """ nb_elem = framedim[0] * framedim[1] if dirname is None: dirname = os.curdir f = open(os.path.join(dirname, filename), "rb") f.seek(offset) # d=scipy.io.fread(f,2048*2048,np.oldnumeric.Int16) # d = scipy.io.fread(f,nb_elem,np.oldnumeric.UInt16) d = np.fromfile(f, dtype=formatdata, count=nb_elem) f.close() return d
[docs]def readoneimage_band(filename, framedim=(2048, 2048), dirname=None, offset=4096, line_startindex=0, line_finalindex=2047, formatdata="uint16"): r""" returns a 1d array of integers from a binary image file. Data located in band according shape of data (framedim) :param filename: string path to image file (fullpath if `dirname`=None) :param offset: integer nb of file header bytes :param framedim: iterable of 2 integers shape of expected 2D data :param formatdata: string key for numpy dtype to decode binary file :return: dataimage, 1D array, image data pixel intensity """ if dirname is None: dirname = os.curdir if formatdata in ("uint16",): nbBytesPerElement = 2 if formatdata in ("uint32",): nbBytesPerElement = 4 nbElems = (line_finalindex - line_startindex + 1) * framedim[1] f = open(os.path.join(dirname, filename), "rb") f.seek(offset + line_startindex * framedim[1] * nbBytesPerElement) # d=scipy.io.fread(f,2048*2048,np.oldnumeric.Int16) # d = scipy.io.fread(f,nb_elem,np.oldnumeric.UInt16) # print "line_finalindex-line_startindex",line_finalindex-line_startindex # print "line_startindex*framedim[1]*nbBytesPerElement",line_startindex*framedim[1]*nbBytesPerElement # print "line_startindex*framedim[1]",line_startindex*framedim[1] # print "nbElems",nbElems band = np.fromfile(f, dtype=formatdata, count=nbElems) f.close() return band
[docs]def readoneimage_crop_fast(filename, dirname=None, CCDLabel="MARCCD165", firstElemIndex=0, lastElemIndex=2047): r""" Returns a 2d array of integers from a binary image file. Data are taken only from a rectangle with respect to firstElemIndex and lastElemIndex. :param filename: string, path to image file (fullpath if ` dirname`=None) :param offset: integer, nb of file header bytes :param framedim: iterable of 2 integers, shape of expected 2D data :param formatdata: string, key for numpy dtype to decode binary file :return: dataimage : 1D array image data pixel intensity """ (framedim, _, _, fliprot, offsetheader, formatdata, _, _) = DictLT.dict_CCD[CCDLabel] print("framedim read from DictLT.dict_CCD in readoneimage_crop_fast()", framedim) print("formatdata", formatdata) print("offsetheader", offsetheader) if dirname is None: dirname = os.curdir # if formatdata in ("uint16",): # nbBytesPerElement = 2 # if formatdata in ("uint32",): # nbBytesPerElement = 4 dataimage2D = np.zeros(framedim) # colFirstElemIndex = firstElemIndex % framedim[1] lineFirstElemIndex = firstElemIndex // framedim[1] # colLastElemIndex = lastElemIndex % framedim[1] lineLastElemIndex = lastElemIndex // framedim[1] band1D = readoneimage_band(filename, framedim=framedim, dirname=dirname, offset=offsetheader, line_startindex=lineFirstElemIndex, line_finalindex=lineLastElemIndex, formatdata=formatdata) # print "band1D.shape",band1D.shape # print "(lineLastElemIndex-lineFirstElemIndex,framedim[1])",(lineLastElemIndex-lineFirstElemIndex,framedim[1]) # print "((lineLastElemIndex-lineFirstElemIndex)*framedim[1])",((lineLastElemIndex-lineFirstElemIndex)*framedim[1]) band2D = band1D.reshape((lineLastElemIndex - lineFirstElemIndex + 1, framedim[1])) dataimage2D[lineFirstElemIndex : lineLastElemIndex + 1, :] = band2D return dataimage2D, framedim, fliprot
[docs]def readrectangle_in_image(filename, pixx, pixy, halfboxx, halfboxy, dirname=None, CCDLabel="MARCCD165", verbose=True): r""" returns a 2d array of integers from a binary image file. Data are taken only from a rectangle centered on pixx, pixy :return: dataimage : 2D array, image data pixel intensity """ (framedim, _, _, fliprot, offsetheader, formatdata, _, _) = DictLT.dict_CCD[CCDLabel] if verbose: print("framedim read from DictLT.dict_CCD in readrectangle_in_image()", framedim) print("formatdata", formatdata) print("offsetheader", offsetheader) # recompute headersize if dirname is not None: fullpathfilename = os.path.join(dirname, filename) else: dirname = os.curdir fullpathfilename = filename if formatdata in ("uint16",): nbBytesPerElement = 2 if formatdata in ("uint32",): nbBytesPerElement = 4 if verbose: print("fullpathfilename", fullpathfilename) try: filesize = os.path.getsize(fullpathfilename) except OSError: print("missing file {}\n".format(fullpathfilename)) return None # uint16 offsetheader = filesize - (framedim[0] * framedim[1]) * nbBytesPerElement if verbose: print("calculated offset of header from file size...", offsetheader) x = int(pixx) y = int(pixy) if fliprot in ("sCMOS_fliplr",): x = framedim[1] - x boxx = int(halfboxx) boxy = int(halfboxy) xpixmin = x - boxx xpixmax = x + boxx ypixmin = y - boxy ypixmax = y + boxy # ymin= (y-boxy)*framedim[1] # ymax= (y+boxy)*framedim[1] lineFirstElemIndex = ypixmin lineLastElemIndex = ypixmax if verbose: print("lineFirstElemIndex", lineFirstElemIndex) print("lineLastElemIndex", lineLastElemIndex) band = readoneimage_band(fullpathfilename, framedim=framedim, dirname=None, offset=offsetheader, line_startindex=lineFirstElemIndex, line_finalindex=lineLastElemIndex, formatdata=formatdata) nblines = lineLastElemIndex - lineFirstElemIndex + 1 band2D = np.reshape(band, (nblines, framedim[1])) # dataimage2D = np.zeros(framedim) if verbose: print("band2D.shape", band2D.shape) rectangle2D = band2D[:, xpixmin : xpixmax + 1] if verbose: print("rectangle2D.shape", rectangle2D.shape) return rectangle2D
[docs]def readoneimage_crop(filename, center, halfboxsize, CCDLabel="PRINCETON", dirname=None): r""" return a cropped array of data read in an image file :param filename: string, path to image file (fullpath if ` dirname`=None) :param center: iterable of 2 integers, (x,y) pixel coordinates :param halfboxsize: integer or iterable of 2 integers, ROI half size in both directions :return: dataimage : 1D array, image data pixel intensity .. todo:: useless? """ if dirname is None: dirname = os.curdir else: filename = os.path.join(dirname, filename) if isinstance(halfboxsize, int): boxsizex, boxsizey = halfboxsize, halfboxsize elif len(halfboxsize) == 2: boxsizex, boxsizey = halfboxsize xpic, ypic = center dataimage, framedim, _ = readCCDimage(filename, CCDLabel=CCDLabel, dirname=None) x1 = np.maximum(0, xpic - boxsizex) x2 = np.minimum(framedim[1], xpic + boxsizex + 1) # framedim[0] y1 = np.maximum(0, ypic - boxsizey) y2 = np.minimum(framedim[0], ypic + boxsizey + 1) # framedim[1] return None, dataimage[y1:y2, x1:x2]
[docs]def readoneimage_manycrops(filename, centers, boxsize, stackimageindex=-1, CCDLabel="MARCCD165", addImax=False, use_data_corrected=None): r""" reads 1 image and extract many regions centered on center_pixel with xyboxsize dimensions in pixel unit :param filename: string,fullpath to image file :param centers: list or array of [int,int] centers (x,y) pixel coordinates :param use_data_corrected: enter data instead of reading data from file must be a tuple of 3 elements: fulldata, framedim, fliprot where fulldata is a numpy.ndarray as output by :func:`readCCDimage` :param boxsize: iterable 2 elements or integer boxsizes [in x, in y] direction or integer to set a square ROI :return: Data, list of 2D array pixel intensity or Data and Imax """ # use alternate data (for instance for data from filename without background) if use_data_corrected is not None: if isinstance(use_data_corrected, tuple): if len(use_data_corrected) == 3: fulldata, framedim, _ = use_data_corrected # use data by reading file else: fulldata, framedim, _ = readCCDimage(filename, stackimageindex=stackimageindex, CCDLabel=CCDLabel, dirname=None) if isinstance(boxsize, int): boxsizex, boxsizey = boxsize, boxsize elif len(boxsize) == 2: boxsizex, boxsizey = boxsize # xpic, ypic = np.array(centers).T # x1 = np.array(np.maximum(0, xpic - boxsizex), dtype=np.int) # x2 = np.array(np.minimum(framedim[0], xpic + boxsizex), dtype=np.int) # y1 = np.array(np.maximum(0, ypic - boxsizey), dtype=np.int) # y2 = np.array(np.minimum(framedim[1], ypic + boxsizey), dtype=np.int) Data = [] Imax = [] print("framedim in readoneimage_manycrops", framedim) framedim = framedim[1], framedim[0] for center in centers: i1, i2, j1, j2 = ImProc.getindices2cropArray(center, (boxsizex, boxsizey), framedim) # print "i1, i2, j1, j2-----", i1, i2, j1, j2 cropdata = fulldata[i1:i2, j1:j2] # # print "cropdata.shape", cropdata.shape # print "i2-i1",i2-i1 # print "boxsizey*2+1",boxsizey*2+1 # print "j2-j1",j2-j1 # print "boxsizex*2+1",boxsizex*2+1 # for spot near border, replace by zeros array if i2 - i1 != boxsizey * 2 or j2 - j1 != boxsizex * 2: cropdata = np.zeros((boxsizey * 2 + 1, boxsizex * 2 + 1)) Data.append(cropdata) if addImax: Imax.append(np.amax(cropdata)) # print "max in cropped data", np.amax(cropdata) if addImax: return Data, Imax else: return Data
[docs]def writeimage(outputname, _header, data, dataformat=np.uint16): r""" from data 1d array of integers with header coming from a f.open('imagefile'); f.read(headersize);f.close() .. warning:: header contain dimensions for subsequent data. Check before the compatibility of data with header infos(nb of byte per pixel and array dimensions """ newfile = open(outputname, "wb") newfile.write(_header) data = np.array(data, dtype=dataformat) data.tofile(newfile) newfile.close() print("image written in ", outputname)
[docs]def write_rawbinary(outputname, data, dataformat=np.uint16): r""" write a binary file without header of a 2D array used ? """ newfile = open(outputname, "wb") data = np.array(data, dtype=dataformat) data.tofile(newfile) newfile.close() print("image written in ", outputname)
[docs]def SumImages(prefixname, suffixname, ind_start, ind_end, dirname=None, plot=0, output_filename=None, CCDLabel=None, nbdigits=0): r""" sum images and write image with 32 bits per pixel format (4 bytes) used? """ # prefixname = 'HN08_' # suffixname = '.tif' # CCDLabel = 'ImageStar_raw' # dirname = '/home/micha/LaueProjects/Vita' output_filename = "mean_{}_{:04d}_{}{}".format(prefixname, ind_start, ind_end, suffixname) filename = "{}{:04d}{}".format(prefixname, ind_start, suffixname) data, shape, _ = readCCDimage(filename, CCDLabel=CCDLabel, dirname=dirname) if CCDLabel == "ImageStar_raw": # Add addition of 32 bits image => replace 2 by 4 nb of bytes per pixel filesize = os.path.getsize(os.path.join(dirname, filename)) offsetheader = filesize - 1500 * 1500 * 2 if CCDLabel == "EIGER_1M": filesize = os.path.getsize(os.path.join(dirname, filename)) offsetheader = filesize - 1065 * 1030 * 4 else: # Add addition of 32 bits image => replace 2 by 4 nb of bytes per pixel filesize = os.path.getsize(os.path.join(dirname, filename)) offsetheader = filesize - 2048 * 2048 * 2 # print "shape = ", np.shape(datastart) datasum = np.zeros(shape, dtype=np.uint32) # nb_images = ind_end - ind_start + 1 indexscanlist = list(range(ind_start, ind_end + 1, 1)) for k in indexscanlist: # print k filename = "{}{:04d}{}".format(prefixname, k, suffixname) # print filename1 data, shape, _ = readCCDimage(filename, CCDLabel=CCDLabel, dirname=dirname) # print max(data1), np.argmax(data1) datasum = data + datasum if output_filename: outputfilename = output_filename header = readheader(os.path.join(dirname, filename), offset=offsetheader) writeimage(os.path.join(dirname, outputfilename), header, datasum, dataformat=np.uint32) print("Added images with prefix {} from {} to {} written in {}".format( prefixname, ind_start, ind_end, outputfilename)) if plot: print("later") return datasum
[docs]def Add_Images2(prefixname, ind_start, ind_end, plot=0, writefilename=None, CCDLabel="MARCCD165", average=True): """ in dev """ suffixname = "." + DictLT.dict_CCD[CCDLabel][-1] filename = prefixname + stringint(ind_start, 4) + suffixname datastart, _, _ = readCCDimage(filename, CCDLabel) # print "shape = ", np.shape(datastart) datastart = np.array(datastart, dtype=float) indexscanlist = list(range(ind_start + 1, ind_end + 1, 1)) for k in indexscanlist: # print k filename1 = prefixname + stringint(k, 4) + suffixname # print filename1 data1, _, _ = readCCDimage(filename1, CCDLabel) # print max(data1), np.argmax(data1) datastart = np.array(data1, dtype=float) + datastart # datastart= datastart/((len(indexscanlist)+1)*1.) # print "final" # print max(datastart), np.argmax(datastart) if average: datastart = datastart / (float(len(indexscanlist)) + 1.0) # print max(datastart), np.argmax(datastart) datastart = np.array(datastart, dtype=np.uint16) # print max(datastart), np.argmax(datastart) if writefilename: outputfilename = writefilename header = readheader(filename1, CCDLabel=CCDLabel) writeimage(outputfilename, header, datastart) print("written in ", outputfilename) if plot: print("later") return datastart
[docs]def Add_Images(prefixname, ind_start, ind_end, plot=0, writefilename=None): r""" Add continuous sequence of images .. note:: Add_Images2 exists :param prefixname: string, prefix common part of name of files :param ind_start: int, starting image index :param ind_end: int, final image index :param writefilename: string, new image filename where to write datastart (with last image file header read) :return: datastart, array accumulation of 2D data from each image """ suffixname = ".mccd" datastart = readoneimage(prefixname + stringint(ind_start, 4) + suffixname) # print "shape = ", np.shape(datastart) datastart = np.array(datastart, dtype=float) indexscanlist = list(range(ind_start + 1, ind_end + 1, 1)) for k in indexscanlist: # print k filename1 = prefixname + stringint(k, 4) + suffixname # print filename1 data1 = readoneimage(filename1) # print max(data1), np.argmax(data1) datastart = np.array(data1, dtype=float) + datastart # datastart= datastart/((len(indexscanlist)+1)*1.) # print "final" # print max(datastart), np.argmax(datastart) datastart = datastart / (float(len(indexscanlist)) + 1.0) # print max(datastart), np.argmax(datastart) datastart = np.array(datastart, dtype=np.uint16) # print max(datastart), np.argmax(datastart) if writefilename: outputfilename = writefilename header = readheader(filename1) writeimage(outputfilename, header, datastart) print("written in ", outputfilename) if plot: print("later") return datastart
[docs]def get_imagesize(framedim, nbbits_per_pixel, headersize_bytes): r""" return size of image in byte (= 1 octet = 8 bits) """ return (framedim[0] * framedim[1] * nbbits_per_pixel + headersize_bytes * 8) // 8