source: sasview/test/sasdataloader/test/utest_cansas.py @ 132db16

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since 132db16 was 132db16, checked in by Piotr Rozyczko <rozyczko@…>, 8 years ago

Refactored Cansas HDF5 reader to allow multiple instances of SASdata of any dimensionality in a single SASentry and multiple instances of SASentry in a single file. Added unit tests to test all types of data (1 entry | 1 data, 1 entry | many data, many entry | 1 data each, many entr |, many data).

  • Property mode set to 100644
File size: 12.0 KB
Line 
1"""
2    Unit tests for the new recursive cansas reader
3"""
4import sas.sascalc.dataloader.readers.cansas_reader as cansas
5from sas.sascalc.dataloader.loader import Loader
6from sas.sascalc.dataloader.data_info import Data1D, Data2D
7from sas.sascalc.dataloader.readers.xml_reader import XMLreader
8from sas.sascalc.dataloader.readers.cansas_reader import Reader
9from sas.sascalc.dataloader.readers.cansas_constants import CansasConstants
10
11import os
12import sys
13import urllib2
14import StringIO
15import pylint as pylint
16import unittest
17import numpy
18import logging
19import warnings
20
21from lxml import etree
22from xml.dom import minidom
23
24warnings.simplefilter("ignore")
25
26CANSAS_FORMAT = CansasConstants.CANSAS_FORMAT
27CANSAS_NS = CansasConstants.CANSAS_NS
28
29class cansas_reader_xml(unittest.TestCase):
30
31    def setUp(self):
32        self.loader = Loader()
33        self.xml_valid = "cansas_test_modified.xml"
34        self.xml_invalid = "cansas_test.xml"
35        self.cansas1d_badunits = "cansas1d_badunits.xml"
36        self.cansas1d = "cansas1d.xml"
37        self.cansas1d_slit = "cansas1d_slit.xml"
38        self.cansas1d_units = "cansas1d_units.xml"
39        self.isis_1_0 = "ISIS_1_0.xml"
40        self.isis_1_1 = "ISIS_1_1.xml"
41        self.isis_1_1_notrans = "ISIS_1_1_notrans.xml"
42        self.isis_1_1_doubletrans = "ISIS_1_1_doubletrans.xml"
43        self.schema_1_0 = "cansas1d_v1_0.xsd"
44        self.schema_1_1 = "cansas1d_v1_1.xsd"
45
46
47    def get_number_of_entries(self, dictionary, name, i):
48        if dictionary.get(name) is not None:
49            i += 1
50            name = name.split("_")[0]
51            name += "_{0}".format(i)
52            name = self.get_number_of_entries(dictionary, name, i)
53        return name
54
55
56    def test_invalid_xml(self):
57        """
58        Should fail gracefully and send a message to logging.info()
59        """
60        invalid = StringIO.StringIO('<a><c></b></a>')
61        reader = XMLreader(invalid)
62
63
64    def test_xml_validate(self):
65        string = "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n"
66        string += "\t<xsd:element name=\"a\" type=\"AType\"/>\n"
67        string += "\t<xsd:complexType name=\"AType\">\n"
68        string += "\t\t<xsd:sequence>\n"
69        string += "\t\t\t<xsd:element name=\"b\" type=\"xsd:string\" />\n"
70        string += "\t\t</xsd:sequence>\n"
71        string += "\t</xsd:complexType>\n"
72        string += "</xsd:schema>"
73        f = StringIO.StringIO(string)
74        xmlschema_doc = etree.parse(f)
75        xmlschema = etree.XMLSchema(xmlschema_doc)
76        valid = etree.parse(StringIO.StringIO('<a><b></b></a>'))
77        invalid = etree.parse(StringIO.StringIO('<a><c></c></a>'))
78        self.assertTrue(xmlschema.validate(valid))
79        self.assertFalse(xmlschema.validate(invalid))
80
81
82    def test_real_xml(self):
83        reader = XMLreader(self.xml_valid, self.schema_1_0)
84        valid = reader.validate_xml()
85        if valid:
86            self.assertTrue(valid)
87        else:
88            self.assertFalse(valid)
89
90
91    def _check_data(self, data):
92        self.assertTrue(data.title == "TK49 c10_SANS")
93        self.assertTrue(data.x.size == 138)
94        self.assertTrue(len(data.meta_data) == 3)
95        self.assertTrue(data.detector[0].distance_unit == "mm")
96        self.assertTrue(data.detector[1].distance_unit == "mm")
97        self.assertTrue(data.detector[0].name == "HAB")
98        self.assertTrue(data.detector[1].name == "main-detector-bank")
99        self.assertTrue(data.detector[0].distance == 575.0)
100        self.assertTrue(data.detector[1].distance == 4145.02)
101        self.assertTrue(data.process[0].name == "Mantid generated CanSAS1D XML")
102        self.assertTrue(data.meta_data["xmlpreprocess"] != None)
103
104
105    def _check_data_1_1(self, data):
106        spectrum = data.trans_spectrum[0]
107        self.assertTrue(len(spectrum.wavelength) == 138)
108
109
110    def test_cansas_xml(self):
111        filename = "isis_1_1_write_test.xml"
112        xmlreader = XMLreader(self.isis_1_1, self.schema_1_1)
113        valid = xmlreader.validate_xml()
114        xmlreader.set_processing_instructions()
115        self.assertTrue(valid)
116        fo = open(self.isis_1_1)
117        str = fo.read()
118        reader_generic = Loader()
119        dataloader = reader_generic.load(self.isis_1_1)
120        reader_cansas = Reader()
121        cansasreader = reader_cansas.read(self.isis_1_1)
122        for i in range(len(dataloader)):
123            self._check_data(dataloader[i])
124            self._check_data_1_1(dataloader[i])
125            self._check_data(cansasreader[i])
126            self._check_data_1_1(cansasreader[i])
127            reader_generic.save(filename, dataloader[i], None)
128            fo = open(filename)
129            str = fo.read()
130            reader2 = Loader()
131            return_data = reader2.load(filename)
132            written_data = return_data[0]
133            self._check_data(written_data)
134
135
136    def test_double_trans_spectra(self):
137        xmlreader = XMLreader(self.isis_1_1_doubletrans, self.schema_1_1)
138        self.assertTrue(xmlreader.validate_xml())
139        reader = Loader()
140        data = reader.load(self.isis_1_1_doubletrans)
141        for item in data:
142            self._check_data(item)
143
144
145    def test_entry_name_recurse(self):
146        test_values = [1,2,3,4,5,6]
147        base_key = "key"
148        d = {}
149        for value in test_values:
150            new_key = self.get_number_of_entries(d, base_key, i = 0)
151            d[new_key] = value
152        self.assertTrue(len(d) == 6)
153
154
155    def test_load_cansas_file(self):
156        valid = []
157        reader1 = XMLreader(self.xml_valid, self.schema_1_0)
158        self.assertTrue(reader1.validate_xml())
159        reader2 = XMLreader(self.xml_invalid, self.schema_1_0)
160        self.assertFalse(reader2.validate_xml())
161        reader3 = XMLreader(self.xml_valid, self.schema_1_1)
162        self.assertFalse(reader3.validate_xml())
163        reader4 = XMLreader(self.xml_invalid, self.schema_1_1)
164        self.assertFalse(reader4.validate_xml())
165        reader5 = XMLreader(self.isis_1_0, self.schema_1_0)
166        self.assertTrue(reader5.validate_xml())
167        reader6 = XMLreader(self.isis_1_1, self.schema_1_1)
168        self.assertTrue(reader6.validate_xml())
169        reader7 = XMLreader(self.isis_1_1, self.schema_1_0)
170        self.assertFalse(reader7.validate_xml())
171
172
173    def test_old_cansas_files(self):
174        reader1 = XMLreader(self.cansas1d, self.schema_1_0)
175        self.assertTrue(reader1.validate_xml())
176        file_loader = Loader()
177        file1 = file_loader.load(self.cansas1d)
178        reader2 = XMLreader(self.cansas1d_units, self.schema_1_0)
179        self.assertTrue(reader2.validate_xml())
180        reader3 = XMLreader(self.cansas1d_badunits, self.schema_1_0)
181        self.assertTrue(reader3.validate_xml())
182        reader4 = XMLreader(self.cansas1d_slit, self.schema_1_0)
183        self.assertTrue(reader4.validate_xml())
184
185
186    def test_save_cansas_v1_0(self):
187        filename = "isis_1_0_write_test.xml"
188        xmlreader = XMLreader(self.isis_1_0, self.schema_1_0)
189        valid = xmlreader.validate_xml()
190        self.assertTrue(valid)
191        reader_generic = Loader()
192        dataloader = reader_generic.load(self.isis_1_0)
193        reader_cansas = Reader()
194        cansasreader = reader_cansas.read(self.isis_1_0)
195        for i in range(len(dataloader)):
196            self._check_data(dataloader[i])
197            self._check_data(cansasreader[i])
198            reader_generic.save(filename, dataloader[i], None)
199            reader2 = Reader()
200            return_data = reader2.read(filename)
201            written_data = return_data[0]
202            xmlwrite = XMLreader(filename, self.schema_1_0)
203            valid = xmlreader.validate_xml()
204            self.assertTrue(valid)
205            self._check_data(written_data)
206
207
208    def test_processing_instructions(self):
209        reader = XMLreader(self.isis_1_1, self.schema_1_1)
210        valid = reader.validate_xml()
211        if valid:
212            ## find the processing instructions and make into a dictionary
213            dic = self.get_processing_instructions(reader)
214            self.assertTrue(dic == {'xml-stylesheet': \
215                                    'type="text/xsl" href="cansas1d.xsl" '})
216
217            xml = "<test><a><b><c></c></b></a></test>"
218            xmldoc = minidom.parseString(xml)
219
220            ## take the processing instructions and put them back in
221            xmldoc = self.set_processing_instructions(xmldoc, dic)
222            xml_output = xmldoc.toprettyxml()
223
224
225    def set_processing_instructions(self, minidom_object, dic):
226        xmlroot = minidom_object.firstChild
227        for item in dic:
228            pi = minidom_object.createProcessingInstruction(item, dic[item])
229            minidom_object.insertBefore(pi, xmlroot)
230        return minidom_object
231
232
233    def get_processing_instructions(self, xml_reader_object):
234        dict = {}
235        pi = xml_reader_object.xmlroot.getprevious()
236        i = 0
237        while pi is not None:
238            attr = {}
239            pi_name = ""
240            pi_string = etree.tostring(pi)
241            if isinstance(pi_string, str):
242                pi_string = pi_string.replace("<?", "").replace("?>", "")
243                split = pi_string.split(" ", 1)
244                pi_name = split[0]
245                attr = split[1]
246            dict[pi_name] = attr
247            pi = pi.getprevious()
248        return dict
249
250
251class cansas_reader_hdf5(unittest.TestCase):
252
253    def setUp(self):
254        self.loader = Loader()
255        self.datafile_basic = "simpleexamplefile.h5"
256        self.datafile_multiplesasentry = "cansas_1Dand2D_samedatafile.h5"
257        self.datafile_multiplesasdata = "cansas_1Dand2D_samesasentry.h5"
258        self.datafile_multiplesasdata_multiplesasentry = "cansas_1Dand2D_multiplesasentry_multiplesasdata.h5"
259
260    def test_real_data(self):
261        self.data = self.loader.load(self.datafile_basic)
262        self._check_example_data(self.data[0])
263
264    def test_multiple_sasentries(self):
265        self.data = self.loader.load(self.datafile_multiplesasentry)
266        self.assertTrue(len(self.data) == 2)
267        self._check_multiple_data(self.data[0])
268        self._check_multiple_data(self.data[1])
269        self._check_1d_data(self.data[0])
270
271    def _check_multiple_data(self, data):
272        self.assertTrue(data.title == "MH4_5deg_16T_SLOW")
273        self.assertTrue(data.run[0] == '33837')
274        self.assertTrue(len(data.run) == 1)
275        self.assertTrue(data.instrument == "SANS2D")
276        self.assertTrue(data.source.radiation == "Spallation Neutron Source")
277        self.assertTrue(len(data.detector) == 1)
278        self.assertTrue(data.detector[0].name == "rear-detector")
279        self.assertTrue(data.detector[0].distance == 4.385281)
280        self.assertTrue(data.detector[0].distance_unit == 'm')
281        self.assertTrue(len(data.trans_spectrum) == 1)
282
283    def _check_1d_data(self, data):
284        self.assertTrue(isinstance(data, Data1D))
285        self.assertTrue(len(data.x) == 66)
286        self.assertTrue(len(data.x) == len(data.y))
287        self.assertTrue(data.dy[10] == 0.20721350111248701)
288        self.assertTrue(data.y[10] == 24.193889608153476)
289        self.assertTrue(data.x[10] == 0.008981127988654792)
290
291    def _check_2d_data(self, data):
292        self.assertTrue(isinstance(data, Data2D))
293        self.assertTrue(len(data.x) == 66)
294        self.assertTrue(len(data.x) == len(data.y))
295        self.assertTrue(data.dy[10] == 0.20721350111248701)
296        self.assertTrue(data.y[10] == 24.193889608153476)
297        self.assertTrue(data.x[10] == 0.008981127988654792)
298
299    def _check_example_data(self, data):
300        self.assertTrue(data.title == "")
301        self.assertTrue(data.x.size == 100)
302        self.assertTrue(data._xunit == "A^{-1}")
303        self.assertTrue(data._yunit == "cm^{-1}")
304        self.assertTrue(data.y.size == 100)
305        self.assertAlmostEqual(data.y[9], 0.952749011516985)
306        self.assertAlmostEqual(data.x[9], 0.3834415188257777)
307        self.assertAlmostEqual(len(data.meta_data), 0)
308
309
310if __name__ == '__main__':
311    unittest.main()   
Note: See TracBrowser for help on using the repository browser.