1
2
3 """
4 Authors: Jérôme Kieffer, ESRF
5 email:jerome.kieffer@esrf.fr
6
7 XSDimge are XML files containing numpy arrays
8 """
9 __author__ = "Jérôme Kieffer"
10 __contact__ = "jerome.kieffer@esrf.eu"
11 __license__ = "GPLv3+"
12 __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
13
14 import os, logging, struct
15 import numpy as np
16 from fabioimage import fabioimage
17 import base64, hashlib
18 from lxml import etree
19
21 """
22 Read the XSDataImage XML File data format
23 """
24 - def __init__(self, data=None, header=None, fname=None):
25 """
26 Constructor of the class XSDataImage.
27
28 @param _strFilename: the name of the file to open
29 @type _strFilename: string
30 """
31 fabioimage.__init__(self, data=data, header=header)
32 self.dims = []
33 self.coding = None
34 if fname is not None:
35 self.filename = fname
36 self.read(fname)
37
38 - def read(self, fname):
39 """
40 """
41 self.header = {}
42 self.resetvals()
43 self.filename = fname
44 infile = self._open(fname, "rb")
45 self._readheader(infile)
46
47 try:
48 self.dim1, self.dim2 = self.dims[:2]
49 except:
50 raise IOError("XSD file %s is corrupt, no dimensions in it" % fname)
51 try:
52 self.bytecode = np.dtype(self.dtype).type
53 self.bpp = len(np.array(0, self.bytecode).tostring())
54 except TypeError:
55 self.bytecode = np.int32
56 self.bpp = 32
57 logging.warning("Defaulting type to int32")
58
59 exp_size = 1
60 for i in self.dims:
61 exp_size *= i
62 assert exp_size == self.size
63
64 decData = None
65 if self.coding == "base64":
66 decData = base64.b64decode(self.rawData)
67 elif self.coding == "base32":
68 decData = base64.b32decode(self.rawData)
69 elif self.coding == "base16":
70 decData = base64.b16decode(self.rawData)
71 else:
72 logging.warning("Unable to recognize the encoding of the data !!! got %s, expected base64, base32 or base16, I assume it is base64 " % self.coding)
73 decData = base64.b64decode(self.rawData)
74 if self.md5:
75 assert hashlib.md5(decData).hexdigest() == self.md5
76
77
78 self.data = np.fromstring(decData, dtype=self.bytecode).reshape(tuple(self.dims))
79 if not np.little_endian:
80 self.data.byteswap(inplace=True)
81 self.resetvals()
82
83 self.pilimage = None
84 return self
85
87 """
88 Read all headers in a file and populate self.header
89 data is not yet populated
90 @type infile: file object open in read mode
91 """
92 xml = etree.parse(infile)
93 self.dims = []
94 for i in xml.xpath("//shape"):
95 try:
96 self.dims.append(int(i.text))
97 except ValueError:
98 logging.warning("Shape: Unable to convert %s to integer in %s" % (i.text, i))
99 for i in xml.xpath("//size"):
100 try:
101 self.size = int(i.text)
102 except:
103 logging.warning("Size: Unable to convert %s to integer in %s" % (i.text, i))
104 self.dtype = None
105 for i in xml.xpath("//dtype"):
106 self.dtype = i.text
107 self.coding = None
108 for i in xml.xpath("//coding"):
109 for j in i.xpath("//value"):
110 self.coding = j.text
111 self.rawData = None
112 for i in xml.xpath("//data"):
113 self.rawData = i.text
114 self.md5 = None
115 for i in xml.xpath("//md5sum"):
116 for j in i.xpath("//value"):
117 self.md5 = j.text
118