source: canSAS2012/examples/xml/fakecansas.py @ 224

Last change on this file since 224 was 224, checked in by prjemian, 8 years ago

more stuff

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 9.6 KB
Line 
1#!/usr/bin/env python
2
3'''
4Generate synthetic data to demonstrate canSAS (2012) data structure in XML
5
6:see: http://www.smallangles.net/wgwiki/index.php/2012_Data_Discussion_Examples
7'''
8
9import inspect
10import string
11import time
12import sys
13import numpy as np
14from lxml import etree
15
16
17CANSAS_VERSION = '1.0'
18#FILE_TIMESTAMP = "2009-09-09T09:09:09-0000"
19FILE_TIMESTAMP = time.strftime("%Y-%m-%dT%H:%M:%S")
20FILE_TIMESTAMP += '%+03d%02d' % (-time.timezone/60/60, abs(time.timezone/60) % 60)
21FILE_PRODUCER = "canSAS"
22SVN_ID = "$Id$".strip('$').strip()
23
24
25class ExampleFile():
26    '''Support for creating and writing XML files (not reading)'''
27    rootTag = "SASroot"
28    root = None
29    filename = None
30    entry = None
31    sasdata = None
32   
33    def __init__(self, filename):
34        self.filename = filename
35
36    def createFile(self):
37        '''
38        Creates the in-memory data structure.
39        Note the actual file creation happens in closeFile().
40        '''
41        self.root = etree.Element(self.rootTag)
42        self.root.attrib['producer'] = FILE_PRODUCER
43        self.root.attrib['file_time'] = FILE_TIMESTAMP
44        self.root.attrib['file_name'] = self.filename
45        #self.root.attrib['Python_etree_version'] = etree.__version__
46        self.root.attrib['svn_id'] = SVN_ID
47
48    def closeFile(self):
49        '''write (or overwrite) the named XML file'''
50        if self.root is not None and self.filename is not None:
51            text = etree.tostring(self.root, pretty_print=True, encoding='utf-8')
52            f = open(self.filename, 'w')
53            f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
54            #if xslt != None:
55            #    f.write('<?xml-stylesheet type="text/xsl" href="%s"?>\n' % xslt)
56            f.write( text )
57            f.close()
58
59    def createEntry(self, name):
60        if self.root is None:
61            raise "No parent SASroot node created yet!"
62        self.entry = etree.SubElement(self.root, 'SASentry')
63        self.entry.attrib['name'] = name        # TODO: automatically choose this name
64        self.entry.attrib['version'] = CANSAS_VERSION
65        self.sasdata = None
66
67    def createTitle(self, title):
68        if self.root is None:
69            raise "No parent SASentry node created yet!"
70        node = etree.SubElement(self.entry, 'Title')
71        node.text = title
72   
73    def createData(self, name, qi, ii, mi=None):
74        if self.entry is None:
75            raise "No parent SASentry node created yet!"
76        self.sasdata = etree.SubElement(self.entry, 'SASdata')
77        self.sasdata.attrib['name'] = name        # TODO: automatically choose this name
78        self.sasdata.attrib['I_axes'] = ii
79        items = self._list_to_text_list(qi)
80        self.sasdata.attrib['Q_indices'] = items
81        if mi != None:
82            items = self._list_to_text_list(mi)
83            self.sasdata.attrib['Mask_indices'] = items
84
85    def createDataSet(self, name, array, attributes=None):
86        if self.sasdata is None:
87            raise "No parent SASdata node created yet!"
88        node = etree.SubElement(self.sasdata, name)
89        text = self._list_to_text_list(array.shape, delimiter='')
90        node.attrib['size'] = text.strip('(),')
91        arrText = self._list_to_text_list(array, delimiter=' ')
92        if len(array.shape)>1:      # multi-dimensional
93            # split into lines on lowest index,
94            # blank lines between rectangular blocks for higher dimensionalities
95            arrText = string.replace(arrText, ']', '\n')
96            arrText = string.replace(arrText, '[', ' ')
97            # indent all lines by the same amount
98            arrText = '\n' + '\n'.join([' '*8 + line.strip() for line in arrText.splitlines()])
99            arrText += '\n' + ' '*4
100        node.text = arrText
101        if attributes != None:
102            for key, value in attributes.items():
103                node.attrib[key] = value
104
105    def _list_to_text_list(self, data, delimiter = ','):
106        # FIXME: fails when len(data) > 1000, array is truncated
107        # TODO: return _all_ content of long np arrays (no " ... " in the middle)
108        return delimiter.join( str(data).strip('[]').split() )
109
110
111class SimpleExampleFile(ExampleFile):
112    def write(self):
113        self.createFile()
114        self.createEntry("sasentry01")
115        self.createTitle('example of simple 1D SAS data, I(Q)')
116        self.createData("sasdata01", np.array([0]), "Q")
117        n = 7
118        self.createDataSet("Q", np.random.rand(n,), {"units": "1/A"})
119        self.createDataSet("I", np.random.rand(n,), {"units": "1/cm"})
120        self.closeFile()
121
122class Simple1DTimeSeries(ExampleFile):
123    def write(self):
124        self.createFile()
125        self.createEntry("sasentry01")
126        self.createTitle('example of simple 1D SAS data in a time series, I(Q, t)')
127        self.createData("sasdata01", np.array([1]), "Time,Q")
128        n, nt = (5, 7)
129        self.createDataSet("Q", np.random.rand(n,), {"units": "1/A"})
130        self.createDataSet("I", np.random.rand(nt,n,), {"units": "1/cm"})
131        self.createDataSet("Time", np.random.rand(nt,), {"units": "s"})
132        self.closeFile()
133
134class Generic1DTimeSeries(ExampleFile):
135    def write(self):
136        self.createFile()
137        self.createEntry("sasentry01")
138        self.createTitle('example of generic 1D SAS data in a time series, I(Q(t), t)')
139        self.createData("sasdata01", np.array([0,1]), "Time,Q")
140        n, nt = (5, 7)
141        self.createDataSet("Q", np.random.rand(nt,n,), {"units": "1/A"})
142        self.createDataSet("I", np.random.rand(nt,n,), {"units": "1/cm"})
143        self.createDataSet("Time", np.random.rand(nt,), {"units": "s"})
144        self.closeFile()
145
146class Simple2DCase(ExampleFile):
147    def write(self):
148        self.createFile()
149        self.createEntry("sasentry01")
150        self.createTitle('example of simple 2D (image) SAS data, I(Q)')
151        self.createData("sasdata01", np.array([0,1]), "Q,Q")
152        nx, ny = (7, 5)
153        self.createDataSet("Qx", np.random.rand(nx,ny,), {"units": "1/A"})
154        self.createDataSet("Qy", np.random.rand(nx,ny,), {"units": "1/A"})
155        self.createDataSet("Qz", np.random.rand(nx,ny,), {"units": "1/A"})
156        self.createDataSet("I", np.random.rand(nx,ny,), {"units": "1/cm"})
157        self.closeFile()
158
159
160class Simple2DMaskedCase(ExampleFile):
161    def write(self):
162        self.createFile()
163        self.createEntry("sasentry01")
164        self.createTitle('example of a simple masked 2D (image) SAS data, I(Q)')
165        self.createData("sasdata01", np.array([0,1]), "Q,Q", np.array([0,1]))
166        nx, ny = (7, 5)
167        self.createDataSet("Qx", np.random.rand(nx,ny,), {"units": "1/A"})
168        self.createDataSet("Qy", np.random.rand(nx,ny,), {"units": "1/A"})
169        self.createDataSet("Qz", np.random.rand(nx,ny,), {"units": "1/A"})
170        self.createDataSet("I", np.random.rand(nx,ny,), {"units": "1/cm"})
171        self.createDataSet("Mask", np.array(np.random.randint(0,1,nx*ny,).reshape(nx,ny), dtype=np.dtype("int8")))
172        self.closeFile()
173
174
175class Generic2DCase(ExampleFile):
176    def write(self):
177        self.createFile()
178        self.createEntry("sasentry01")
179        self.createTitle('example of generic 2D SAS data, I(Q)')
180        self.createData("sasdata01", np.array([0]), "Q")
181        nx, ny = (7, 5)
182        self.createDataSet("Qx", np.random.rand(nx,ny,), {"units": "1/A"})
183        self.createDataSet("Qy", np.random.rand(nx,ny,), {"units": "1/A"})
184        self.createDataSet("Qz", np.random.rand(nx,ny,), {"units": "1/A"})
185        self.createDataSet("I", np.random.rand(nx*ny,), {"units": "1/cm"})
186        self.closeFile()
187
188
189class Generic2DTimeSeries(ExampleFile):
190    def write(self):
191        self.createFile()
192        self.createEntry("sasentry01")
193        self.createTitle('example of generic 2D SAS data in a time series, I(Q(t),t)')
194        self.createData("sasdata01", np.array([0,1]), "Time,Q")
195        nx, ny, nt = (7, 5, 4)
196        self.createDataSet("Qx", np.random.rand(nx,ny,), {"units": "1/A"})
197        self.createDataSet("Qy", np.random.rand(nx,ny,), {"units": "1/A"})
198        self.createDataSet("Qz", np.random.rand(nx,ny,), {"units": "1/A"})
199        self.createDataSet("I", np.random.rand(nt,nx*ny,), {"units": "1/cm"})
200        self.createDataSet("Time", np.random.rand(nt,), {"units": "ms"})
201        self.closeFile()
202
203
204class Generic2DTimeTPSeries(ExampleFile):
205    def write(self):
206        self.createFile()
207        self.createEntry("sasentry01")
208        self.createTitle('example of generic 2D SAS data (images) in a time, T, & P series, I(T,t,P,Q(t))')
209        self.createData("sasdata01", np.array([1,3,4]), "Temperature,Time,Pressure,Q,Q")
210        nx, ny, ntime, ntemperature, npressure = (5, 6, 4, 3, 2)
211        self.createDataSet("Qx", np.random.rand(ntime,nx,ny), {"units": "1/A"})
212        self.createDataSet("Qy", np.random.rand(ntime,nx,ny), {"units": "1/A"})
213        self.createDataSet("Qz", np.random.rand(ntime,nx,ny), {"units": "1/A"})
214        self.createDataSet("I", np.random.rand(ntemperature,ntime,npressure,nx,ny), {"units": "1/cm"})
215        self.createDataSet("Temperature", np.random.rand(ntemperature,), {"units": "ms"})
216        self.createDataSet("Time", np.random.rand(ntime,), {"units": "ms"})
217        self.createDataSet("Pressure", np.random.rand(npressure,), {"units": "ms"})
218        self.closeFile()
219
220
221def main():
222    subclasses = []
223    classType=ExampleFile
224    callers_module = sys._getframe(0).f_globals['__name__']
225    classes = inspect.getmembers(sys.modules[callers_module], inspect.isclass)
226    for name, obj in classes:
227        if (obj is not classType) and (classType in inspect.getmro(obj)):
228            subclasses.append((obj, name))
229    for f in subclasses:
230        filename = f[1]+".xml"
231        filename = filename.lower()
232        f[0](filename).write()
233
234
235if __name__ == "__main__":
236    main()
Note: See TracBrowser for help on using the repository browser.