Source code for fabio.kcdimage

#!/usr/bin/env python
"""
Authors: Jerome Kieffer, ESRF 
         email:jerome.kieffer@esrf.fr

kcd images are 2D images written by the old KappaCCD diffractometer built by Nonius in the 1990's
Based on the edfimage.py parser.
"""
# Get ready for python3:
from __future__ import with_statement, print_function

import numpy, logging
import os, string
from .fabioimage import fabioimage
logger = logging.getLogger("kcdimage")

DATA_TYPES = {"u16"  :  numpy.uint16 }

MINIMUM_KEYS = [
                'ByteOrder',
                'Data type',
                'X dimension',
                'Y dimension',
                'Number of readouts']

DEFAULT_VALUES = { "Data type": "u16" }




[docs]class kcdimage(fabioimage): """ Read the Nonius kcd data format """ def _readheader(self, infile): """ Read in a header in some KCD format from an already open file @ """ oneLine = infile.readline() alphanum = string.digits + string.letters + ". " asciiHeader = True for oneChar in oneLine.strip(): if not oneChar in alphanum: asciiHeader = False if asciiHeader is False: # This does not look like an edf file logger.warning("First line of %s does not seam to be ascii text!" % infile.name) endOfHeaders = False while not endOfHeaders: oneLine = infile.readline() if len(oneLine) > 100: endOfHeaders = True break if oneLine.strip() == "Binned mode": oneLine = "Mode = Binned" try: key, val = oneLine.split('=' , 1) except: endOfHeaders = True break key = key.strip() self.header_keys.append(key) self.header[key] = val.strip() missing = [] for item in MINIMUM_KEYS: if item not in self.header_keys: missing.append(item) if len(missing) > 0: logger.debug("KCD file misses the keys " + " ".join(missing))
[docs] def read(self, fname, frame=None): """ Read in header into self.header and the data into self.data """ self.header = {} self.resetvals() infile = self._open(fname, "rb") self._readheader(infile) # Compute image size try: self.dim1 = int(self.header['X dimension']) self.dim2 = int(self.header['Y dimension']) except: raise Exception("KCD file %s is corrupt, cannot read it" % fname) try: bytecode = DATA_TYPES[self.header['Data type']] self.bpp = len(numpy.array(0, bytecode).tostring()) except KeyError: bytecode = numpy.uint16 self.bpp = 2 logger.warning("Defaulting type to uint16") try: nbReadOut = int(self.header['Number of readouts']) except KeyError: logger.warning("Defaulting number of ReadOut to 1") nbReadOut = 1 fileSize = os.stat(fname)[6] expected_size = self.dim1 * self.dim2 * self.bpp * nbReadOut infile.seek(fileSize - expected_size) block = infile.read() assert len(block) == expected_size infile.close() #now read the data into the array self.data = numpy.zeros((self.dim2, self.dim1)) try: for i in range(nbReadOut): self.data += numpy.reshape(numpy.fromstring( block[i * expected_size / nbReadOut:(i + 1) * expected_size / nbReadOut], bytecode), [self.dim2, self.dim1]) except: print(len(block), bytecode, self.bpp, self.dim2, self.dim1) raise IOError( 'Size spec in kcd-header does not match size of image data field') self.bytecode = self.data.dtype.type self.resetvals() # ensure the PIL image is reset self.pilimage = None return self
@staticmethod
[docs] def checkData(data=None): if data is None: return None else: return data.astype(int)