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)