# -*- 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 warnings
with warnings.catch_warnings():
warnings.filterwarnings("ignore",category=FutureWarning)
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, ValueError):
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, verbose=0):
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
"""
if nbdigits in (0,'0','None'):
nbdigits = None
# 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
prepart = str(imagefilename).rsplit('.',1)[0]
prefix0, strindex = str(prepart).rsplit('_', 1)
if nbdigits is not None or nbdigits == 0: # zero padded (4 digits)
SPEC_controlled_SCMOS = True
imagefilename = prefix0 + "_{:04d}.{}".format(imageindex, ext)
else: # bliss psl control of sCMOS
SPEC_controlled_SCMOS = False
imagefilename = prefix0 + "_{}.{}".format(imageindex, ext)
# if int(strindex)<1000:
# if len(strindex)<4: # no zero padded
# SPEC_controlled_SCMOS = False
# imagefilename = prefix0 + "_{}.{}".format(imageindex, ext)
# else: # 4 only zeros padded
# SPEC_controlled_SCMOS = True
# imagefilename = prefix0 + "_{:04d}.{}".format(imageindex, ext)
# # zero padded index for filename
# if nbdigits is not None:
# if imagefilename.endswith(ext):
# #imagefilename = imagefilename[: - (lenext + nbdigits)] + "{:04d}.{}".format(imageindex, ext)
# #imagefilename = imagefilename[: - (lenext + nbdigits)].zfill(nbdigits) + "%s" % ext
# prepart = str(imagefilename).rsplit('.',1)[0]
# prefix, strindex = str(prepart).rsplit('_', 1)
# current_nbdigits = len(strindex)
# imagefilename = prefix + "_" + str(imageindex).zfill(current_nbdigits) + "." + 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, strindex = prefix.rsplit("_",1)
# if len(strindex)<=4:
# if
# SPEC_controlled_SCMOS = True
# # version SPEC and SCMOS up to March 2022
# if imageindex > 9999:
# imagefilename = prefix0 + "_{}.{}".format(imageindex, ext)
# else: # 4 0s padding for index < 10000
# 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.rsplit("_")[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)
if verbose>0: print("lastelem", lastelem)
if not lastelem.isdigit():
break
indexnodigit += 1
prefix = prefixwihtindex[:-(indexnodigit)]
if verbose > 0: 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, verbose=0):
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
if verbose > 0: print('imagefilename', imagefilename)
if nbdigits is not None:
if imagefilename.endswith(ext):
#imageindex = int(imagefilename[-(lenext + nbdigits): - (lenext)])
prepart = str(imagefilename).rsplit('.',1)[0]
digitpart = str(prepart).rsplit('_',1)[-1]
print("prepart", prepart)
print("digitpart",digitpart)
imageindex = int(digitpart)
elif imagefilename.endswith(ext+".gz"):
imageindex = int(imagefilename[-(lenext+3 + nbdigits) : -(lenext+3)])
else:
if imagefilename.endswith(ext):
prefix, _ = imagefilename.rsplit(".")
imageindex = int(prefix.rsplit("_")[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 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"""general function to read raw data binary (Laue pattern) image file recorder on 2D detector.
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
if verbose > 1:
print("CCDLabel in readCCDimage", CCDLabel)
print('FABIO_EXISTS',FABIO_EXISTS)
print('LIBTIFF_EXISTS',LIBTIFF_EXISTS)
print('PIL_EXISTS',PIL_EXISTS)
# 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","IMSTAR_bin2","IMSTAR_bin1",
"sCMOS", "sCMOS_fliplr", "sCMOS_fliplr_16M", "sCMOS_16M",
"Rayonix MX170-HS", 'psl_weiwei', 'ImageStar_dia_2021','ImageStar_dia_2021_2x2'):
if verbose > 1:
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)
if verbose > 0: print("opening hdf5 stacked data table")
alldata = hdf5file.root.entry.data.data
if verbose > 0: print("alldata.shape", alldata.shape)
dataimage = alldata[stackimageindex]
framedim = dataimage.shape
elif LIBTIFF_EXISTS:
if verbose > 1:
print("----> Using libtiff...")
if CCDLabel in ("sCMOS", "MARCCD165", "TIFF Format", "FRELONID15_corrected", "VHR_PSI",
"VHR_DLS", "MARCCD225", "Andrea", "pnCCD_Tuba", "sCMOS_16M"):
# 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:
if verbose > 1:
print("using PIL's module Image")
if CCDLabel in ("sCMOS", "MARCCD165", "sCMOS_16M"):
if verbose > 1: print('PIL is too slow. Better install libtiff or fabio. Meanwhile I will use PIL...')
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=getfilesize(dirname, filename)
offsetheader = 4096 #filesize - 2048*2048 * 2
# offset header varying
elif CCDLabel.startswith("ImageStar_raw"):
filesize=getfilesize(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 == "ImageStar_dia_2021":
filesize=getfilesize(dirname, filename)
bytes_per_pixels = 2
nbpixels = 3056
offsetheader = filesize - nbpixels * nbpixels * bytes_per_pixels
elif CCDLabel in ("sCMOS",):
if verbose > 0: print("for sCMOS not using libtiff, raw method ...")
# offsetheader may change ...
filesize = getfilesize(dirname, filename)
offsetheader = filesize - 2016*2018 * 2
dataimage = readoneimage(filename,
framedim=framedim,
dirname=dirname,
offset=offsetheader,
formatdata=formatdata)
print("dataimage", dataimage)
if CCDLabel in ("FRELONID15_corrected",):
dataimage = dataimage.byteswap()
if CCDLabel in ("EIGER_4Munstacked",):
dataimage = np.ma.masked_where(dataimage > 4000000, dataimage)
if verbose > 0:
print("framedim", framedim)
print("offsetheader", offsetheader)
print("formatdata", formatdata)
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:
if verbose:
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)
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 == "Imagestar_dia_2021": # starting Feb july 2021 close to diamond monochromator crystal
dataimage = np.rot90(dataimage, k=1)
dataimage = np.fliplr(dataimage)
elif fliprot in ("frelon2", "flipud"):
dataimage = np.flipud(dataimage)
return dataimage, framedim, fliprot
def getfilesize(dirname,filename):
if dirname is not None:
filesize = os.path.getsize(os.path.join(dirname, filename))
else:
filesize = os.path.getsize(filename)
return filesize
[docs]def readoneimage(filename, framedim=(2048, 2048), dirname=None, offset=4096, formatdata="uint16"):
r""" crude way to open binary image. it 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, verbose=0):
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]
if verbose > 0:
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=0):
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 > 0:
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 > 0:
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 > 0:
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 > 0:
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]))
rectangle2D = band2D[:, xpixmin : xpixmax + 1]
if verbose > 0:
print("band2D.shape", band2D.shape)
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,
verbose=0):
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 = []
if verbose > 0:
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, verbose=0):
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()
if verbose > 0: print("image written in ", outputname)
[docs]def write_rawbinary(outputname, data, dataformat=np.uint16, verbose=0):
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()
if verbose > 0: 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