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
RevLine 
[4bdd4fdb]1"""
2    Unit tests for the new recursive cansas reader
3"""
[b699768]4import sas.sascalc.dataloader.readers.cansas_reader as cansas
5from sas.sascalc.dataloader.loader import Loader
[132db16]6from sas.sascalc.dataloader.data_info import Data1D, Data2D
[b699768]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
[4bdd4fdb]10
11import os
12import sys
[eda8972]13import urllib2
14import StringIO
[ac5b69d]15import pylint as pylint
16import unittest
17import numpy
[132db16]18import logging
19import warnings
[4bdd4fdb]20
21from lxml import etree
[ea67541]22from xml.dom import minidom
[132db16]23
24warnings.simplefilter("ignore")
25
[ac5b69d]26CANSAS_FORMAT = CansasConstants.CANSAS_FORMAT
27CANSAS_NS = CansasConstants.CANSAS_NS
[132db16]28
29class cansas_reader_xml(unittest.TestCase):
30
[4bdd4fdb]31    def setUp(self):
32        self.loader = Loader()
[eda8972]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"
[76cd1ae]42        self.isis_1_1_doubletrans = "ISIS_1_1_doubletrans.xml"
[eda8972]43        self.schema_1_0 = "cansas1d_v1_0.xsd"
44        self.schema_1_1 = "cansas1d_v1_1.xsd"
[132db16]45
46
[eda8972]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
[132db16]54
55
[3241dd2]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)
[132db16]62
[eda8972]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))
[132db16]80
81
[eda8972]82    def test_real_xml(self):
83        reader = XMLreader(self.xml_valid, self.schema_1_0)
[ac5b69d]84        valid = reader.validate_xml()
[eda8972]85        if valid:
86            self.assertTrue(valid)
87        else:
88            self.assertFalse(valid)
[132db16]89
90
[76cd1ae]91    def _check_data(self, data):
92        self.assertTrue(data.title == "TK49 c10_SANS")
93        self.assertTrue(data.x.size == 138)
[ea67541]94        self.assertTrue(len(data.meta_data) == 3)
[76cd1ae]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")
[2e3b055]102        self.assertTrue(data.meta_data["xmlpreprocess"] != None)
[132db16]103
104
[c6ca23d]105    def _check_data_1_1(self, data):
106        spectrum = data.trans_spectrum[0]
107        self.assertTrue(len(spectrum.wavelength) == 138)
[132db16]108
109
[eda8972]110    def test_cansas_xml(self):
[75eeb425]111        filename = "isis_1_1_write_test.xml"
[eda8972]112        xmlreader = XMLreader(self.isis_1_1, self.schema_1_1)
[ac5b69d]113        valid = xmlreader.validate_xml()
114        xmlreader.set_processing_instructions()
[eda8972]115        self.assertTrue(valid)
[2e3b055]116        fo = open(self.isis_1_1)
117        str = fo.read()
[76cd1ae]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])
[c6ca23d]124            self._check_data_1_1(dataloader[i])
[76cd1ae]125            self._check_data(cansasreader[i])
[c6ca23d]126            self._check_data_1_1(cansasreader[i])
[76cd1ae]127            reader_generic.save(filename, dataloader[i], None)
[2e3b055]128            fo = open(filename)
129            str = fo.read()
130            reader2 = Loader()
131            return_data = reader2.load(filename)
[76cd1ae]132            written_data = return_data[0]
133            self._check_data(written_data)
[132db16]134
135
[76cd1ae]136    def test_double_trans_spectra(self):
137        xmlreader = XMLreader(self.isis_1_1_doubletrans, self.schema_1_1)
[ac5b69d]138        self.assertTrue(xmlreader.validate_xml())
[76cd1ae]139        reader = Loader()
140        data = reader.load(self.isis_1_1_doubletrans)
141        for item in data:
142            self._check_data(item)
[132db16]143
144
[eda8972]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)
[132db16]153
154
[eda8972]155    def test_load_cansas_file(self):
156        valid = []
157        reader1 = XMLreader(self.xml_valid, self.schema_1_0)
[ac5b69d]158        self.assertTrue(reader1.validate_xml())
[eda8972]159        reader2 = XMLreader(self.xml_invalid, self.schema_1_0)
[ac5b69d]160        self.assertFalse(reader2.validate_xml())
[eda8972]161        reader3 = XMLreader(self.xml_valid, self.schema_1_1)
[ac5b69d]162        self.assertFalse(reader3.validate_xml())
[eda8972]163        reader4 = XMLreader(self.xml_invalid, self.schema_1_1)
[ac5b69d]164        self.assertFalse(reader4.validate_xml())
[eda8972]165        reader5 = XMLreader(self.isis_1_0, self.schema_1_0)
[ac5b69d]166        self.assertTrue(reader5.validate_xml())
[eda8972]167        reader6 = XMLreader(self.isis_1_1, self.schema_1_1)
[ac5b69d]168        self.assertTrue(reader6.validate_xml())
[eda8972]169        reader7 = XMLreader(self.isis_1_1, self.schema_1_0)
[ac5b69d]170        self.assertFalse(reader7.validate_xml())
[132db16]171
172
[eda8972]173    def test_old_cansas_files(self):
174        reader1 = XMLreader(self.cansas1d, self.schema_1_0)
[ac5b69d]175        self.assertTrue(reader1.validate_xml())
[ea67541]176        file_loader = Loader()
177        file1 = file_loader.load(self.cansas1d)
[eda8972]178        reader2 = XMLreader(self.cansas1d_units, self.schema_1_0)
[ac5b69d]179        self.assertTrue(reader2.validate_xml())
[eda8972]180        reader3 = XMLreader(self.cansas1d_badunits, self.schema_1_0)
[ac5b69d]181        self.assertTrue(reader3.validate_xml())
[eda8972]182        reader4 = XMLreader(self.cansas1d_slit, self.schema_1_0)
[ac5b69d]183        self.assertTrue(reader4.validate_xml())
[132db16]184
185
[c6ca23d]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)
[ac5b69d]189        valid = xmlreader.validate_xml()
[c6ca23d]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]
[2e3b055]202            xmlwrite = XMLreader(filename, self.schema_1_0)
[ac5b69d]203            valid = xmlreader.validate_xml()
[2e3b055]204            self.assertTrue(valid)
[c6ca23d]205            self._check_data(written_data)
[132db16]206
207
[ea67541]208    def test_processing_instructions(self):
209        reader = XMLreader(self.isis_1_1, self.schema_1_1)
[ac5b69d]210        valid = reader.validate_xml()
[ea67541]211        if valid:
212            ## find the processing instructions and make into a dictionary
[ac5b69d]213            dic = self.get_processing_instructions(reader)
[3241dd2]214            self.assertTrue(dic == {'xml-stylesheet': \
215                                    'type="text/xsl" href="cansas1d.xsl" '})
[132db16]216
[ea67541]217            xml = "<test><a><b><c></c></b></a></test>"
218            xmldoc = minidom.parseString(xml)
[132db16]219
[ea67541]220            ## take the processing instructions and put them back in
[ac5b69d]221            xmldoc = self.set_processing_instructions(xmldoc, dic)
[ea67541]222            xml_output = xmldoc.toprettyxml()
[132db16]223
224
[ac5b69d]225    def set_processing_instructions(self, minidom_object, dic):
226        xmlroot = minidom_object.firstChild
[ea67541]227        for item in dic:
[ac5b69d]228            pi = minidom_object.createProcessingInstruction(item, dic[item])
229            minidom_object.insertBefore(pi, xmlroot)
230        return minidom_object
[132db16]231
232
[ac5b69d]233    def get_processing_instructions(self, xml_reader_object):
[ea67541]234        dict = {}
[ac5b69d]235        pi = xml_reader_object.xmlroot.getprevious()
[ea67541]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
[132db16]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
[2e3b055]309
[4bdd4fdb]310if __name__ == '__main__':
[eda8972]311    unittest.main()   
Note: See TracBrowser for help on using the repository browser.