Changeset 91128648 in sasview for prview/perspectives/pr


Ignore:
Timestamp:
May 30, 2009 11:24:48 AM (16 years ago)
Author:
Mathieu Doucet <doucetm@…>
Branches:
master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
a88ac04
Parents:
b3de3a45
Message:

prview: extending the module to add flexibility necessary for SansView?. Adding compatibility with CanSAS format when saving a P(r) fit result to file.

Location:
prview/perspectives/pr
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • prview/perspectives/pr/inversion_panel.py

    rd2ee6f6 r91128648  
    341341         
    342342        # Data file 
    343         state.file = self.data_file.GetValue() 
     343        if self.manager.standalone==True: 
     344            state.file = self.data_file.GetValue() 
     345        else: 
     346            #TODO: save the data 
     347            pass 
    344348         
    345349        # Background evaluation checkbox 
  • prview/perspectives/pr/inversion_state.py

    r6f1f129 r91128648  
    99""" 
    1010import time, os 
     11import logging 
     12import DataLoader 
     13from DataLoader.readers.cansas_reader import Reader as CansasReader 
     14 
     15PRNODE_NAME = 'pr_inversion' 
    1116 
    1217## List of P(r) inversion inputs  
     
    111116        return state 
    112117         
    113     def toXML(self, file="pr_state.prv"): 
     118    def toXML(self, file="pr_state.prv", doc=None, entry_node=None): 
    114119        """ 
    115120            Writes the state of the InversionControl panel to file, as XML. 
    116121             
     122            Compatible with standalone writing, or appending to an 
     123            already existing XML document. In that case, the XML document 
     124            is required. An optional entry node in the XML document may also be given. 
     125             
    117126            @param file: file to write to 
     127            @param doc: XML document object [optional] 
     128            @param entry_node: XML node within the XML document at which we will append the data [optional] 
    118129        """ 
    119130        from xml.dom.minidom import getDOMImplementation 
    120131 
    121         impl = getDOMImplementation() 
    122          
    123         doc_type = impl.createDocumentType("pr_inversion", "1.0", "1.0")      
    124          
    125         newdoc = impl.createDocument(None, "pr_inversion", doc_type) 
    126         top_element = newdoc.documentElement 
     132        # Check whether we have to write a standalone XML file 
     133        if doc is None: 
     134            impl = getDOMImplementation() 
     135         
     136            doc_type = impl.createDocumentType(PRNODE_NAME, "1.0", "1.0")      
     137         
     138            newdoc = impl.createDocument(None, PRNODE_NAME, doc_type) 
     139            top_element = newdoc.documentElement 
     140        else: 
     141            # We are appending to an existing document 
     142            newdoc = doc 
     143            top_element = newdoc.createElement(PRNODE_NAME) 
     144            if entry_node is None: 
     145                newdoc.documentElement.appendChild(top_element) 
     146            else: 
     147                entry_node.appendChild(top_element) 
     148             
    127149        attr = newdoc.createAttribute("version") 
    128150        attr.nodeValue = '1.0' 
     
    130152         
    131153        # File name 
    132         element = newdoc.createElement("filename") 
    133         element.appendChild(newdoc.createTextNode(self.file)) 
    134         top_element.appendChild(element) 
     154        if self.file is not None: 
     155            element = newdoc.createElement("filename") 
     156            element.appendChild(newdoc.createTextNode(str(self.file))) 
     157            top_element.appendChild(element) 
    135158         
    136159        element = newdoc.createElement("timestamp") 
     
    160183                     
    161184        # Save the file 
    162         fd = open(file, 'w') 
    163         fd.write(newdoc.toprettyxml()) 
    164         fd.close() 
    165  
    166     def fromXML(self, file): 
     185        if doc is None: 
     186            fd = open(file, 'w') 
     187            fd.write(newdoc.toprettyxml()) 
     188            fd.close() 
     189            return None 
     190        else: 
     191            return newdoc.toprettyxml() 
     192 
     193    def fromXML(self, file=None, node=None): 
    167194        """ 
    168195            Load a P(r) inversion state from a file 
    169196             
    170197            @param file: .prv file 
    171         """ 
    172         # Check whether the file is valid 
    173         if not os.path.isfile(file): 
    174             raise  RuntimeError, "P(r) reader: cannot open %s" % file 
    175          
    176         from xml.dom.minidom import parse 
    177         doc = parse(file) 
    178         if doc.documentElement.tagName == 'pr_inversion': 
    179             if doc.documentElement.hasAttribute('version')\ 
    180                 and doc.documentElement.getAttribute('version') == '1.0': 
     198            @param node: node of a XML document to read from 
     199        """ 
     200        if file is not None: 
     201            # Check whether the file is valid 
     202            if not os.path.isfile(file): 
     203                raise  RuntimeError, "P(r) reader: cannot open %s" % file 
     204         
     205            from xml.dom.minidom import parse 
     206            doc = parse(file) 
     207            node = doc.documentElement 
     208             
     209        if node.tagName == PRNODE_NAME: 
     210            if node.hasAttribute('version')\ 
     211                and node.getAttribute('version') == '1.0': 
    181212                 
    182                 if doc.documentElement.hasChildNodes(): 
    183                     for node in doc.documentElement.childNodes: 
     213                if node.hasChildNodes(): 
     214                    for node in node.childNodes: 
    184215                        if node.nodeName == 'filename': 
    185216                            if node.hasChildNodes(): 
     
    220251                                                exec '%s = None' % out[1] 
    221252            else: 
    222                 raise RuntimeError, "Unsupported P(r) file version: %s" % doc.documentElement.getAttribute('version') 
     253                raise RuntimeError, "Unsupported P(r) file version" 
    223254         
    224255                     
    225 class Reader: 
     256class Reader(CansasReader): 
    226257    """ 
    227258        Class to load a .prv P(r) inversion file 
     
    235266    ext=['.prv', '.PRV']   
    236267     
    237     def __init__(self, call_back): 
     268    def __init__(self, call_back, cansas=False): 
    238269        """ 
    239270            Initialize the call-back method to be called 
    240271            after we load a file 
    241272            @param call_back: call-back method 
    242         """ 
     273            @param cansas:  True = files will be written/read in CanSAS format 
     274                            False = standalone mode 
     275             
     276        """ 
     277        ## Call back method to be executed after a file is read 
    243278        self.call_back = call_back 
     279        ## CanSAS format flag 
     280        self.cansas = cansas 
    244281         
    245282    def read(self, path): 
     
    250287            @return: None 
    251288        """ 
     289        if self.cansas==True: 
     290            return self._read_cansas(path) 
     291        else: 
     292            return self._read_standalone(path) 
     293         
     294    def _read_standalone(self, path): 
     295        """  
     296            Load a new P(r) inversion state from file. 
     297            The P(r) node is assumed to be the top element. 
     298             
     299            @param path: file path 
     300            @return: None 
     301        """ 
    252302        # Read the new state from file 
    253303        state = InversionState() 
    254         state.fromXML(path) 
     304        state.fromXML(file=path) 
    255305         
    256306        # Call back to post the new state 
    257307        self.call_back(state) 
    258308        return None 
     309     
     310    def _parse_prstate(self, entry): 
     311        """ 
     312            Read a p(r) inversion result from an XML node 
     313            @param entry: XML node to read from  
     314            @return: InversionState object 
     315        """ 
     316        from xml import xpath 
     317 
     318        # Create an empty state 
     319        state = InversionState() 
     320         
     321        # Locate the P(r) node 
     322        try: 
     323            nodes = xpath.Evaluate(PRNODE_NAME, entry) 
     324            state.fromXML(node=nodes[0]) 
     325        except: 
     326            #raise RuntimeError, "%s is not a file with P(r) information." % path 
     327            logging.info("XML document does not contain P(r) information.") 
     328            import sys 
     329            print sys.exc_value 
     330             
     331        return state 
     332     
     333    def _read_cansas(self, path): 
     334        """  
     335            Load data and P(r) information from a CanSAS XML file. 
     336             
     337            @param path: file path 
     338            @return: Data1D object if a single SASentry was found,  
     339                        or a list of Data1D objects if multiple entries were found, 
     340                        or None of nothing was found 
     341            @raise RuntimeError: when the file can't be opened 
     342            @raise ValueError: when the length of the data vectors are inconsistent 
     343        """ 
     344        from xml.dom.minidom import parse 
     345        from xml import xpath 
     346        output = [] 
     347         
     348        if os.path.isfile(path): 
     349            basename  = os.path.basename(path) 
     350            root, extension = os.path.splitext(basename) 
     351            if  extension.lower() in self.ext or \ 
     352                extension.lower() == '.xml': 
     353                 
     354                dom = parse(path) 
     355                 
     356                # Format 1: check whether we have a CanSAS file 
     357                nodes = xpath.Evaluate('SASroot', dom) 
     358                # Check the format version number 
     359                if nodes[0].hasAttributes(): 
     360                    for i in range(nodes[0].attributes.length): 
     361                        if nodes[0].attributes.item(i).nodeName=='version': 
     362                            if nodes[0].attributes.item(i).nodeValue != self.version: 
     363                                raise ValueError, "cansas_reader: unrecognized version number %s" % \ 
     364                                    nodes[0].attributes.item(i).nodeValue 
     365                 
     366                entry_list = xpath.Evaluate('SASroot/SASentry', dom) 
     367                for entry in entry_list: 
     368                    sas_entry = self._parse_entry(entry) 
     369                    prstate = self._parse_prstate(entry) 
     370                    sas_entry.meta_data['prstate'] = prstate 
     371                    sas_entry.filename = basename 
     372                    output.append(sas_entry) 
     373        else: 
     374            raise RuntimeError, "%s is not a file" % path 
     375         
     376        # Return output consistent with the loader's api 
     377        if len(output)==0: 
     378            return None 
     379        elif len(output)==1: 
     380            return output[0] 
     381        else: 
     382            return output                 
     383     
     384     
     385    def write(self, filename, datainfo=None, prstate=None): 
     386        """ 
     387            Write the content of a Data1D as a CanSAS XML file 
     388             
     389            @param filename: name of the file to write 
     390            @param datainfo: Data1D object 
     391            @param prstate: InversionState object 
     392        """ 
     393 
     394        # Sanity check 
     395        if self.cansas == True: 
     396            if datainfo is None: 
     397                datainfo = DataLoader.data_info.Data1D(x=[], y=[])     
     398            elif not datainfo.__class__ == DataLoader.data_info.Data1D:  
     399                raise RuntimeError, "The cansas writer expects a Data1D instance" 
     400         
     401            # Create basic XML document 
     402            doc, sasentry = self._to_xml_doc(datainfo) 
     403         
     404            # Add the P(r) information to the XML document 
     405            if prstate is not None: 
     406                prstate.toXML(doc=doc, entry_node=sasentry) 
     407         
     408            # Write the XML document 
     409            fd = open(filename, 'w') 
     410            fd.write(doc.toprettyxml()) 
     411            fd.close() 
     412        else: 
     413            prstate.toXML(file=filename) 
     414         
    259415         
    260416if __name__ == "__main__":  
     417    #TODO: turn all this into unit tests 
     418     
    261419    state = InversionState() 
    262420    #print state.fromXML('../../test/pr_state.prv')      
    263421    print state.fromXML('../../test/test.prv')      
    264422    print state    
     423    state.toXML('test_copy.prv') 
     424     
     425    from DataLoader.loader import Loader 
     426    l = Loader() 
     427    datainfo = l.load("../../test/cansas1d.xml") 
     428     
     429    def call_back(state): 
     430        print state 
     431         
     432    reader = Reader(call_back) 
     433    reader.cansas = False 
     434    reader.write("test_copy_from_reader.prv", prstate=state) 
     435    reader.cansas = True 
     436    reader.write("testout.prv", datainfo, state) 
     437    reader.write("testout_wo_datainfo.prv", prstate=state) 
     438     
     439    # Now try to load things back 
     440    reader.cansas = False 
     441    #print reader.read("test_copy_from_reader.prv") 
     442    reader.cansas = True 
     443    #data = reader.read("testout.prv") 
     444    data = reader.read("testout_wo_datainfo.prv") 
     445    print data 
     446    print data.meta_data['prstate'] 
     447     
     448     
Note: See TracChangeset for help on using the changeset viewer.