source: sasview/test/sasdataloader/test/utest_cansas.py @ 2ca5d57b

magnetic_scattrelease-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249unittest-saveload
Last change on this file since 2ca5d57b was 2ca5d57b, checked in by krzywon, 19 months ago

Code cleanup and additional unit tests.

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