Changeset 786685e in sasview for src


Ignore:
Timestamp:
May 15, 2014 7:08:38 PM (10 years ago)
Author:
pkienzle
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:
4a0dc427
Parents:
4e9f227 (diff), bb1b892 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merge from trunk

Location:
src/sans
Files:
3 added
22 edited

Legend:

Unmodified
Added
Removed
  • src/sans/dataloader/readers/cansas_constants.py

    r9e2bc6c rac5b69d  
    33the cansas_reader.py file to read in any version of the cansas format. 
    44""" 
    5 class cansasConstants: 
    6      
    7     ns = '' 
     5class CansasConstants: 
     6    """ 
     7    The base class to define where all of the data is to be saved by 
     8    cansas_reader.py. 
     9    """ 
     10     
     11    names = '' 
    812    format = '' 
    913     
    1014     
    1115    def __init__(self): 
    12         self.ns = self.CANSAS_NS 
     16        self.names = self.CANSAS_NS 
    1317        self.format = self.CANSAS_FORMAT 
    1418     
    1519     
    16     def _iterate_namespace(self, namespace): 
     20    def iterate_namespace(self, namespace): 
    1721        """ 
    1822        Method to iterate through a cansas constants tree based on a list of 
     
    2327        """ 
    2428        # The current level to look through in cansas_constants. 
    25         return_me = currentLevel() 
     29        return_me = CurrentLevel() 
    2630        return_me.current_level = self.CANSAS_FORMAT.get("SASentry") 
    2731        # Defaults for variable and datatype 
     
    3034        return_me.ns_optional = True 
    3135        for name in namespace: 
    32             if name != "SASentry": 
    33                 return_me.current_level = \ 
    34                         return_me.current_level.get("children").get(name, "") 
    35                 if return_me.current_level == "": 
     36            try: 
     37                if name != "SASentry": 
    3638                    return_me.current_level = \ 
    37                             return_me.current_level.get("<any>", "") 
    38                 cl_variable = return_me.current_level.get("variable", "") 
    39                 cl_datatype = return_me.current_level.get("storeas", "") 
    40                 cl_units_optional = \ 
    41                             return_me.current_level.get("units_required", "") 
    42                 # Where are how to store the variable for the given namespace 
    43                 # CANSAS_CONSTANTS tree is hierarchical, so is no value, inherit 
    44                 return_me.ns_variable = cl_variable if cl_variable != "" else \ 
    45                                     return_me.ns_variable 
    46                 return_me.ns_datatype = cl_datatype if cl_datatype != "" else \ 
    47                                     return_me.ns_datatype 
    48                 return_me.ns_optional = cl_units_optional if \ 
    49                                     cl_units_optional != return_me.ns_optional \ 
    50                                     else return_me.ns_optional 
     39                            return_me.current_level.get("children").get(name, "") 
     40                    if return_me.current_level == "": 
     41                        return_me.current_level = \ 
     42                                return_me.current_level.get("<any>", "") 
     43                    cl_variable = return_me.current_level.get("variable", "") 
     44                    cl_datatype = return_me.current_level.get("storeas", "") 
     45                    cl_units_optional = \ 
     46                                return_me.current_level.get("units_required", "") 
     47                    # Where are how to store the variable for the given namespace 
     48                    # CANSAS_CONSTANTS tree is hierarchical, so is no value, inherit 
     49                    return_me.ns_variable = cl_variable if cl_variable != "" else \ 
     50                                        return_me.ns_variable 
     51                    return_me.ns_datatype = cl_datatype if cl_datatype != "" else \ 
     52                                        return_me.ns_datatype 
     53                    return_me.ns_optional = cl_units_optional if \ 
     54                                        cl_units_optional != return_me.ns_optional \ 
     55                                        else return_me.ns_optional 
     56            except AttributeError: 
     57                return_me.ns_variable = "{0}.meta_data[\"{2}\"] = \"{1}\"" 
     58                return_me.ns_datatype = "content" 
     59                return_me.ns_optional = True 
    5160        return return_me     
    5261     
     
    454463                           } 
    455464    SASINSTR_SRC = { 
    456                     "attributes" : {"name" : {"variable" : "{0}.source.name = \"{1}\""}}, 
     465                    "attributes" : {"name" : {"variable" : \ 
     466                                              "{0}.source.name = \"{1}\""}}, 
    457467                    "variable" : None, 
    458468                    "children" : { 
    459                                   "radiation" : {"variable" : "{0}.source.radiation = \"{1}\""}, 
     469                                  "radiation" : {"variable" : \ 
     470                                            "{0}.source.radiation = \"{1}\""}, 
    460471                                  "beam_size" : SASINSTR_SRC_BEAMSIZE, 
    461472                                  "beam_shape" : {"variable" : \ 
     
    647658                        "unit" : "pixel_size_unit", 
    648659                        "attributes" : { 
    649                                         "unit" : "{0}.pixel_size_unit = \"{1}\"", 
     660                                        "unit" : \ 
     661                                            "{0}.pixel_size_unit = \"{1}\"", 
    650662                                        "storeas" : "content" 
    651663                                        } 
     
    655667                        "unit" : "pixel_size_unit", 
    656668                        "attributes" : { 
    657                                         "unit" : "{0}.pixel_size_unit = \"{1}\"", 
     669                                        "unit" : \ 
     670                                            "{0}.pixel_size_unit = \"{1}\"", 
    658671                                        "storeas" : "content" 
    659672                                        } 
     
    663676                        "unit" : "pixel_size_unit", 
    664677                        "attributes" : { 
    665                                         "unit" : "{0}.pixel_size_unit = \"{1}\"", 
     678                                        "unit" : \ 
     679                                            "{0}.pixel_size_unit = \"{1}\"", 
    666680                                        "storeas" : "content" 
    667681                                        } 
     
    740754                     } 
    741755    
    742 class currentLevel: 
     756class CurrentLevel: 
     757    """ 
     758    A helper class to hold information on where you are in the constants tree 
     759    """ 
    743760      
    744761    current_level = '' 
     
    748765      
    749766    def __init__(self): 
    750         self.current_level = '' 
     767        self.current_level = {} 
    751768        self.ns_variable = '' 
    752769        self.ns_datatype = "content" 
  • src/sans/dataloader/readers/cansas_reader.py

    r2e3b055 rbb1b892  
    1818import sys 
    1919import datetime 
     20import inspect 
     21# For saving individual sections of data 
    2022from sans.dataloader.data_info import Data1D 
    2123from sans.dataloader.data_info import Collimation 
     
    2426from sans.dataloader.data_info import Process 
    2527from sans.dataloader.data_info import Aperture 
     28# Both imports used. Do not remove either. 
     29from xml.dom.minidom import parseString 
    2630import sans.dataloader.readers.xml_reader as xml_reader 
    27 from sans.dataloader.readers.cansas_constants import cansasConstants 
     31from sans.dataloader.readers.xml_reader import XMLreader 
     32from sans.dataloader.readers.cansas_constants import CansasConstants 
    2833 
    2934_ZERO = 1e-16 
     
    3641    HAS_CONVERTER = False 
    3742 
    38 constants = cansasConstants()     
    39 CANSAS_FORMAT = constants.format 
    40 CANSAS_NS = constants.ns 
     43CONSTANTS = CansasConstants()     
     44CANSAS_FORMAT = CONSTANTS.format 
     45CANSAS_NS = CONSTANTS.names 
    4146ALLOW_ALL = True 
    4247 
    4348 
     49# minidom used in functions called by outside classes 
     50import xml.dom.minidom 
     51# DO NOT REMOVE 
     52# Called by outside packages: 
     53#    sans.perspectives.invariant.invariant_state 
     54#    sans.perspectives.fitting.pagestate 
    4455def get_content(location, node): 
    4556    """ 
     
    5162    :return: Element, or None 
    5263    """ 
    53     nodes = node.xpath(location, namespaces={'ns': CANSAS_NS}) 
     64    nodes = node.xpath(location,  
     65                       namespaces={'ns': CANSAS_NS.get("1.0").get("ns")}) 
    5466     
    5567    if len(nodes) > 0: 
     
    5971 
    6072 
    61 def get_float(location, node): 
    62     """ 
    63     Get the content of a node as a float 
    64      
    65     :param location: xpath location 
    66     :param node: node to start at 
    67     """ 
    68     nodes = node.xpath(location, namespaces={'ns': CANSAS_NS}) 
    69      
    70     value = None 
    71     attr = {} 
    72     if len(nodes) > 0: 
    73         try: 
    74             value = float(nodes[0].text) 
    75         except: 
    76             # Could not pass, skip and return None 
    77             msg = "cansas_reader.get_float: could not " 
    78             msg += " convert '%s' to float" % nodes[0].text 
    79             logging.error(msg) 
    80         if nodes[0].get('unit') is not None: 
    81             attr['unit'] = nodes[0].get('unit') 
    82     return value, attr 
    83  
    84  
    85 # This is called by sans.perspectives.fitting.pagestate.py 
    86 # Do not remove 
     73# DO NOT REMOVE 
     74# Called by outside packages: 
     75#    sans.perspectives.fitting.pagestate 
    8776def write_node(doc, parent, name, value, attr={}): 
    8877    """ 
     
    10594                 
    10695 
    107 class Reader(): 
     96class Reader(XMLreader): 
    10897    """ 
    10998    Class to load cansas 1D XML files 
     
    114103    ##CanSAS version - defaults to version 1.0 
    115104    cansas_version = "1.0" 
    116     ##Data reader 
    117     # TODO: make the reader extend the XMLreader class? 
    118     reader = xml_reader.XMLreader() 
     105     
     106    logging = [] 
    119107    errors = [] 
    120108     
    121109    type_name = "canSAS" 
    122      
    123110    ## Wildcards 
    124     type = ["XML files (*.xml)|*.xml"] 
     111    type = ["XML files (*.xml)|*.xml", "SasView Save Files (*.svs)|*.svs"] 
    125112    ## List of allowed extensions 
    126     ext = ['.xml', '.XML'] 
     113    ext = ['.xml', '.XML', '.svs', '.SVS'] 
    127114     
    128115    ## Flag to bypass extension check 
     
    133120        self.errors = [] 
    134121         
    135     def is_cansas(self): 
     122    def is_cansas(self, ext="xml"): 
    136123        """ 
    137124        Checks to see if the xml file is a CanSAS file 
    138125        """ 
    139         if self.reader.validateXML(): 
     126        if self.validate_xml(): 
    140127            name = "{http://www.w3.org/2001/XMLSchema-instance}schemaLocation" 
    141             value = self.reader.xmlroot.get(name) 
    142             if (CANSAS_NS.get(self.cansas_version).get("ns") == \ 
    143                     value.rsplit(" ")[0]): 
     128            value = self.xmlroot.get(name) 
     129            if CANSAS_NS.get(self.cansas_version).get("ns") == \ 
     130                    value.rsplit(" ")[0]: 
    144131                return True 
     132        if ext == "svs": 
     133            return True 
    145134        return False 
    146135     
     
    152141        """ 
    153142        # X - Q value; Y - Intensity (Abs) 
    154         x = numpy.empty(0) 
    155         y = numpy.empty(0) 
    156         dx = numpy.empty(0) 
    157         dy = numpy.empty(0) 
     143        x_vals = numpy.empty(0) 
     144        y_vals = numpy.empty(0) 
     145        dx_vals = numpy.empty(0) 
     146        dy_vals = numpy.empty(0) 
    158147        dxl = numpy.empty(0) 
    159148        dxw = numpy.empty(0) 
     
    162151        output = [] 
    163152        # ns - Namespace hierarchy for current xml object 
    164         ns = [] 
     153        ns_list = [] 
    165154         
    166155        # Check that the file exists 
     
    168157            basename = os.path.basename(xml) 
    169158            _, extension = os.path.splitext(basename) 
    170             # If the fiel type is not allowed, return nothing 
     159            # If the file type is not allowed, return nothing 
    171160            if extension in self.ext or self.allow_all: 
     161                # Get the file location of  
    172162                base_name = xml_reader.__file__ 
    173163                base_name = base_name.replace("\\","/") 
     
    175165                 
    176166                # Load in xml file and get the cansas version from the header 
    177                 self.reader.setXMLFile(xml) 
    178                 root = self.reader.xmlroot 
     167                self.set_xml_file(xml) 
     168                root = self.xmlroot 
    179169                if root is None: 
    180170                    root = {} 
     
    187177                 
    188178                # Link a schema to the XML file. 
    189                 self.reader.setSchema(schema_path) 
     179                self.set_schema(schema_path) 
    190180                 
    191181                # Try to load the file, but raise an error if unable to. 
    192182                # Check the file matches the XML schema 
    193183                try: 
    194                     if self.is_cansas(): 
     184                    if self.is_cansas(extension): 
    195185                        # Get each SASentry from XML file and add it to a list. 
    196186                        entry_list = root.xpath('/ns:SASroot/ns:SASentry', 
    197187                                namespaces={'ns': cansas_defaults.get("ns")}) 
    198                         ns.append("SASentry") 
     188                        ns_list.append("SASentry") 
    199189                         
    200190                        # If multiple files, modify the name for each is unique 
     
    204194                        # Parse each SASentry item 
    205195                        for entry in entry_list: 
    206                             # Define a new Data1D object with zeroes for x and y 
    207                             data1d = Data1D(x,y,dx,dy) 
     196                            # Define a new Data1D object with zeroes for  
     197                            # x_vals and y_vals 
     198                            data1d = Data1D(x_vals, y_vals, dx_vals, dy_vals) 
    208199                            data1d.dxl = dxl 
    209200                            data1d.dxw = dxw 
     
    220211                             
    221212                            # Get all preprocessing events and encoding 
    222                             self.reader.setProcessingInstructions() 
     213                            self.set_processing_instructions() 
    223214                            data1d.meta_data[PREPROCESS] = \ 
    224                                     self.reader.processingInstructions 
     215                                    self.processing_instructions 
    225216                             
    226217                            # Parse the XML file 
    227218                            return_value, extras = \ 
    228                                 self._parse_entry(entry, ns, data1d) 
     219                                self._parse_entry(entry, ns_list, data1d) 
    229220                            del extras[:] 
    230221                             
     
    251242                            output.append(return_value) 
    252243                    else: 
    253                         value = self.reader.findInvalidXML() 
     244                        value = self.find_invalid_xml() 
    254245                        output.append("Invalid XML at: {0}".format(value)) 
    255246                except: 
    256247                    # If the file does not match the schema, raise this error 
    257                     raise RuntimeError, "%s cannot be read \increment" % xml 
     248                    raise RuntimeError, "%s cannot be read" % xml 
    258249                return output 
    259250        # Return a list of parsed entries that dataloader can manage 
    260251        return None 
    261252     
    262     def _create_unique_key(self, dictionary, name, i = 0): 
     253    def _create_unique_key(self, dictionary, name, numb = 0): 
    263254        """ 
    264255        Create a unique key value for any dictionary to prevent overwriting 
     
    267258        :param dictionary: A dictionary with any number of entries 
    268259        :param name: The index of the item to be added to dictionary 
    269         :param i: The number to be appended to the name, starts at 0 
     260        :param numb: The number to be appended to the name, starts at 0 
    270261        """ 
    271262        if dictionary.get(name) is not None: 
    272             i += 1 
     263            numb += 1 
    273264            name = name.split("_")[0] 
    274             name += "_{0}".format(i) 
    275             name = self._create_unique_key(dictionary, name, i) 
     265            name += "_{0}".format(numb) 
     266            name = self._create_unique_key(dictionary, name, numb) 
    276267        return name 
    277268     
     
    284275         
    285276        :param new_current_level: cansas_constants level as returned by  
    286             _iterate_namespace 
     277            iterate_namespace 
    287278        :param attr: The attributes of the node 
    288279        :param data1d: Where the values will be saved 
     
    318309                            return 
    319310                        except: 
    320                             err_msg = "CanSAS reader: could not convert the units" 
     311                            err_msg = \ 
     312                                "CanSAS reader: could not convert the units" 
    321313                            self.errors.append(err_msg) 
    322314                            return 
     
    343335        return node_value, value_unit 
    344336     
    345     def _parse_entry(self, dom, ns, data1d, extras = []): 
     337    def _parse_entry(self, dom, names=["SASentry"], data1d=None, extras=[]): 
    346338        """ 
    347339        Parse a SASEntry - new recursive method for parsing the dom of 
     
    349341            and extra nodes to be read in simultaneously. 
    350342         
    351         :param dom: dom object with a namespace base of ns 
    352         :param ns: A list of element names that lead up to the dom object 
     343        :param dom: dom object with a namespace base of names 
     344        :param names: A list of element names that lead up to the dom object 
    353345        :param data1d: The data1d object that will be modified 
    354346        :param extras: Any values that should go into meta_data when data1d 
    355347            is not a Data1D object 
    356348        """ 
    357           
     349         
    358350        # A portion of every namespace entry 
     351        if data1d == None: 
     352            x_vals = numpy.empty(0) 
     353            y_vals = numpy.empty(0) 
     354            dx_vals = numpy.empty(0) 
     355            dy_vals = numpy.empty(0) 
     356            dxl = numpy.empty(0) 
     357            dxw = numpy.empty(0) 
     358            data1d = Data1D(x_vals, y_vals, dx_vals, dy_vals) 
     359            data1d.dxl = dxl 
     360            data1d.dxw = dxw 
     361                             
    359362        base_ns = "{0}{1}{2}".format("{", \ 
    360363                            CANSAS_NS.get(self.cansas_version).get("ns"), "}") 
     
    366369        for node in dom: 
    367370            try: 
    368                 # Get the element name and set the current ns level 
     371                # Get the element name and set the current names level 
    369372                tagname = node.tag.replace(base_ns, "") 
    370373                tagname_original = tagname 
    371                 ns.append(tagname) 
     374                if tagname == "fitting_plug_in" or tagname == "pr_inversion" or\ 
     375                    tagname == "invariant": 
     376                    continue 
     377                names.append(tagname) 
    372378                attr = node.attrib 
    373379                children = node.getchildren() 
     380                if len(children) == 0: 
     381                    children = None 
    374382                save_data1d = data1d 
    375383                 
     
    410418                                 
    411419                # Get where to store content 
    412                 cs_values = constants._iterate_namespace(ns) 
     420                cs_values = CONSTANTS.iterate_namespace(names) 
    413421                # If the element is a child element, recurse 
    414422                if children is not None: 
    415423                    # Returned value is new Data1D object with all previous and  
    416424                    # new values in it. 
    417                     data1d, extras = self._parse_entry(node, ns, data1d, extras) 
     425                    data1d, extras = self._parse_entry(node,  
     426                                                       names, data1d, extras) 
    418427                     
    419428                #Get the information from the node 
     
    488497                            pass 
    489498             
    490             except TypeError: 
     499            except TypeError as e: 
    491500                pass 
    492501            except Exception as e: 
     
    509518                else: 
    510519                    save_data1d = data1d 
    511                 data1d = save_data1d 
    512                 # Remove tagname from ns to restore original base 
    513                 ns.remove(tagname_original) 
    514          
     520                if tagname_original == "fitting_plug_in" or \ 
     521                    tagname_original == "invariant" or \ 
     522                    tagname_original == "pr_inversion": 
     523                    pass 
     524                else: 
     525                    data1d = save_data1d 
     526                    # Remove tagname from names to restore original base 
     527                    names.remove(tagname_original) 
    515528        return data1d, extras 
    516529         
     530     
    517531    def _to_xml_doc(self, datainfo): 
    518532        """ 
     
    521535        :param datainfo: Data1D object 
    522536        """ 
    523          
    524537        if not issubclass(datainfo.__class__, Data1D): 
    525538            raise RuntimeError, "The cansas writer expects a Data1D instance" 
    526539         
    527540        # Get PIs and create root element 
    528         pis = self.reader.return_processing_instructions() 
    529         doc = self.reader.create_tree(pis[0]) 
    530         i = 1 
    531         for i in range(1,len(pis) - 1): 
    532             doc = self.reader.append(pis[i], doc) 
     541        pis = self.return_processing_instructions() 
     542        if len(pis) > 0: 
     543            pi_tree = self.create_tree(pis[0]) 
     544            i = 1 
     545            for i in range(1,len(pis) - 1): 
     546                pi_tree = self.append(pis[i], pi_tree) 
     547            pi_string = self.to_string(pi_tree) 
     548        else: 
     549            pi_string = "" 
    533550         
    534551        # Define namespaces and create SASroot object 
     
    540557        else: 
    541558            url = "http://svn.smallangles.net/svn/canSAS/1dwg/trunk/" 
    542         schemaLocation = "{0} {1}cansas1d.xsd".format(ns, url) 
    543         attrib = {"{" + xsi + "}schemaLocation" : schemaLocation, 
     559        schema_location = "{0} {1}cansas1d.xsd".format(ns, url) 
     560        attrib = {"{" + xsi + "}schemaLocation" : schema_location, 
    544561                  "version" : version} 
    545562        nsmap = {'xsi' : xsi, None: ns} 
    546563         
    547         main_node = self.reader.create_element("{" + ns + "}SASroot", \ 
     564        main_node = self.create_element("{" + ns + "}SASroot", \ 
    548565                                               attrib = attrib, \ 
    549566                                               nsmap = nsmap) 
    550567         
    551568        # Create ElementTree, append SASroot and apply processing instructions 
    552         base_string = self.reader.toString(doc) + \ 
    553                     self.reader.toString(main_node) 
    554         base_element = self.reader.create_element_from_string(base_string) 
    555         doc = self.reader.create_tree(base_element) 
     569        base_string = pi_string + self.to_string(main_node) 
     570        base_element = self.create_element_from_string(base_string) 
     571        doc = self.create_tree(base_element) 
    556572         
    557573        # Create SASentry Element 
    558         entry_node = self.reader.create_element("SASentry") 
     574        entry_node = self.create_element("SASentry") 
    559575        root = doc.getroot() 
    560576        root.append(entry_node) 
     
    576592         
    577593        # Data info 
    578         node = self.reader.create_element("SASdata") 
    579         self.reader.append(node, entry_node) 
     594        node = self.create_element("SASdata") 
     595        self.append(node, entry_node) 
    580596         
    581597        for i in range(len(datainfo.x)): 
    582             pt = self.reader.create_element("Idata") 
     598            pt = self.create_element("Idata") 
    583599            node.append(pt) 
    584600            self.write_node(pt, "Q", datainfo.x[i], {'unit': datainfo.x_unit}) 
     
    598614                self.write_node(pt, "dQl", datainfo.dxl[i], 
    599615                            {'unit': datainfo.x_unit}) 
    600  
     616         
    601617        # Transmission Spectrum Info 
    602618        for i in range(len(datainfo.trans_spectrum)): 
    603619            spectrum = datainfo.trans_spectrum[i] 
    604             node = self.reader.create_element("SAStransmission_spectrum", 
     620            node = self.create_element("SAStransmission_spectrum", 
    605621                                              {"name" : spectrum.name}) 
    606             self.reader.append(node, entry_node) 
     622            self.append(node, entry_node) 
    607623            if isinstance(spectrum.timestamp, datetime.datetime): 
    608624                node.setAttribute("timestamp", spectrum.timestamp) 
    609625            for i in range(len(spectrum.wavelength)): 
    610                 pt = self.reader.create_element("Tdata") 
     626                pt = self.create_element("Tdata") 
    611627                node.append(pt) 
    612628                self.write_node(pt, "Lambda", spectrum.wavelength[i],  
     
    621637 
    622638        # Sample info 
    623         sample = self.reader.create_element("SASsample") 
     639        sample = self.create_element("SASsample") 
    624640        if datainfo.sample.name is not None: 
    625             self.reader.write_attribute(sample,  
     641            self.write_attribute(sample,  
    626642                                        "name",  
    627643                                        str(datainfo.sample.name)) 
    628         self.reader.append(sample, entry_node) 
     644        self.append(sample, entry_node) 
    629645        self.write_node(sample, "ID", str(datainfo.sample.ID)) 
    630646        self.write_node(sample, "thickness", datainfo.sample.thickness, 
     
    634650                   {"unit": datainfo.sample.temperature_unit}) 
    635651         
    636         pos = self.reader.create_element("position") 
     652        pos = self.create_element("position") 
    637653        written = self.write_node(pos,  
    638654                                  "x",  
     
    648664                                       {"unit": datainfo.sample.position_unit}) 
    649665        if written == True: 
    650             self.reader.append(pos, sample) 
    651          
    652         ori = self.reader.create_element("orientation") 
     666            self.append(pos, sample) 
     667         
     668        ori = self.create_element("orientation") 
    653669        written = self.write_node(ori, "roll", 
    654670                                  datainfo.sample.orientation.x, 
     
    661677                                    {"unit": datainfo.sample.orientation_unit}) 
    662678        if written == True: 
    663             self.reader.append(ori, sample) 
     679            self.append(ori, sample) 
    664680         
    665681        for item in datainfo.sample.details: 
     
    667683         
    668684        # Instrument info 
    669         instr = self.reader.create_element("SASinstrument") 
    670         self.reader.append(instr, entry_node) 
     685        instr = self.create_element("SASinstrument") 
     686        self.append(instr, entry_node) 
    671687         
    672688        self.write_node(instr, "name", datainfo.instrument) 
    673689         
    674690        #   Source 
    675         source = self.reader.create_element("SASsource") 
     691        source = self.create_element("SASsource") 
    676692        if datainfo.source.name is not None: 
    677             self.reader.write_attribute(source, 
     693            self.write_attribute(source, 
    678694                                        "name", 
    679695                                        str(datainfo.source.name)) 
    680         self.reader.append(source, instr) 
     696        self.append(source, instr) 
    681697        if datainfo.source.radiation == None or datainfo.source.radiation == '': 
    682698            datainfo.source.radiation = "neutron" 
    683699        self.write_node(source, "radiation", datainfo.source.radiation) 
    684700         
    685         size = self.reader.create_element("beam_size") 
     701        size = self.create_element("beam_size") 
    686702        if datainfo.source.beam_size_name is not None: 
    687             self.reader.write_attribute(size, 
     703            self.write_attribute(size, 
    688704                                        "name", 
    689705                                        str(datainfo.source.beam_size_name)) 
     
    697713                                       {"unit": datainfo.source.beam_size_unit}) 
    698714        if written == True: 
    699             self.reader.append(size, source) 
     715            self.append(size, source) 
    700716             
    701717        self.write_node(source, "beam_shape", datainfo.source.beam_shape) 
     
    718734            datainfo.collimation.append(coll) 
    719735        for item in datainfo.collimation: 
    720             coll = self.reader.create_element("SAScollimation") 
     736            coll = self.create_element("SAScollimation") 
    721737            if item.name is not None: 
    722                 self.reader.write_attribute(coll, "name", str(item.name)) 
    723             self.reader.append(coll, instr) 
     738                self.write_attribute(coll, "name", str(item.name)) 
     739            self.append(coll, instr) 
    724740             
    725741            self.write_node(coll, "length", item.length, 
     
    727743             
    728744            for apert in item.aperture: 
    729                 ap = self.reader.create_element("aperture") 
     745                ap = self.create_element("aperture") 
    730746                if apert.name is not None: 
    731                     self.reader.write_attribute(ap, "name", str(apert.name)) 
     747                    self.write_attribute(ap, "name", str(apert.name)) 
    732748                if apert.type is not None: 
    733                     self.reader.write_attribute(ap, "type", str(apert.type)) 
    734                 self.reader.append(ap, coll) 
    735                  
    736                 size = self.reader.create_element("size") 
     749                    self.write_attribute(ap, "type", str(apert.type)) 
     750                self.append(ap, coll) 
     751                 
     752                size = self.create_element("size") 
    737753                if apert.size_name is not None: 
    738                     self.reader.write_attribute(size,  
     754                    self.write_attribute(size,  
    739755                                                "name",  
    740756                                                str(apert.size_name)) 
     
    746762                                               {"unit": apert.size_unit}) 
    747763                if written == True: 
    748                     self.reader.append(size, ap) 
     764                    self.append(size, ap) 
    749765                 
    750766                self.write_node(ap, "distance", apert.distance, 
     
    758774                 
    759775        for item in datainfo.detector: 
    760             det = self.reader.create_element("SASdetector") 
     776            det = self.create_element("SASdetector") 
    761777            written = self.write_node(det, "name", item.name) 
    762778            written = written | self.write_node(det, "SDD", item.distance, 
    763779                                           {"unit": item.distance_unit}) 
    764780            if written == True: 
    765                 self.reader.append(det, instr) 
     781                self.append(det, instr) 
    766782             
    767             off = self.reader.create_element("offset") 
     783            off = self.create_element("offset") 
    768784            written = self.write_node(off, "x", item.offset.x, 
    769785                                 {"unit": item.offset_unit}) 
     
    773789                                           {"unit": item.offset_unit}) 
    774790            if written == True: 
    775                 self.reader.append(off, det) 
    776                  
    777             ori = self.reader.create_element("orientation") 
     791                self.append(off, det) 
     792                 
     793            ori = self.create_element("orientation") 
    778794            written = self.write_node(ori, "roll", item.orientation.x, 
    779795                                 {"unit": item.orientation_unit}) 
     
    785801                                           {"unit": item.orientation_unit}) 
    786802            if written == True: 
    787                 self.reader.append(ori, det) 
     803                self.append(ori, det) 
    788804             
    789             center = self.reader.create_element("beam_center") 
     805            center = self.create_element("beam_center") 
    790806            written = self.write_node(center, "x", item.beam_center.x, 
    791807                                 {"unit": item.beam_center_unit}) 
     
    797813                                           {"unit": item.beam_center_unit}) 
    798814            if written == True: 
    799                 self.reader.append(center, det) 
    800                  
    801             pix = self.reader.create_element("pixel_size") 
     815                self.append(center, det) 
     816                 
     817            pix = self.create_element("pixel_size") 
    802818            written = self.write_node(pix, "x", item.pixel_size.x, 
    803819                                 {"unit": item.pixel_size_unit}) 
     
    810826                                           {"unit": item.slit_length_unit}) 
    811827            if written == True: 
    812                 self.reader.append(pix, det) 
     828                self.append(pix, det) 
    813829             
    814830        # Processes info 
    815831        for item in datainfo.process: 
    816             node = self.reader.create_element("SASprocess") 
    817             self.reader.append(node, entry_node) 
     832            node = self.create_element("SASprocess") 
     833            self.append(node, entry_node) 
    818834 
    819835            self.write_node(node, "name", item.name) 
     
    831847        # Note info 
    832848        if len(datainfo.notes) == 0: 
    833             node = self.reader.create_element("SASnote") 
    834             self.reader.append(node, entry_node) 
     849            node = self.create_element("SASnote") 
     850            self.append(node, entry_node) 
    835851        else: 
    836852            for item in datainfo.notes: 
    837                 node = self.reader.create_element("SASnote") 
    838                 self.reader.write_text(node, item) 
    839                 self.reader.append(node, entry_node) 
     853                node = self.create_element("SASnote") 
     854                self.write_text(node, item) 
     855                self.append(node, entry_node) 
    840856                 
    841857         
    842858        # Return the document, and the SASentry node associated with 
    843         # the data we just wrote 
     859        #      the data we just wrote 
     860        # If the calling function was not the cansas reader, return a minidom 
     861        #      object rather than an lxml object.         
     862         
     863        frm = inspect.stack()[1] 
     864        mod_name = frm[1].replace("\\", "/").replace(".pyc", "") 
     865        mod_name = mod_name.replace(".py", "") 
     866        mod = mod_name.split("/readers/") 
     867        mod_name = mod[1] 
     868        if mod_name != "cansas_reader": 
     869            string = self.to_string(doc, pp=False) 
     870            doc = parseString(string) 
     871            node_name = entry_node.tag 
     872            node_list = doc.getElementsByTagName(node_name) 
     873            entry_node = node_list.item(0) 
     874             
    844875        return doc, entry_node 
    845876     
    846877     
    847     def write_node(self, parent, name, value, attr={}): 
     878    def write_node(self, parent, name, value, attr=None): 
    848879        """ 
    849880        :param doc: document DOM 
     
    856887        """ 
    857888        if value is not None: 
    858             parent = self.reader.ebuilder(parent, name, value, attr) 
     889            parent = self.ebuilder(parent, name, value, attr) 
    859890            return True 
    860891        return False 
     
    872903        # Write the file 
    873904        fd = open(filename, 'w') 
    874         if self.reader.encoding == None: 
    875             self.reader.encoding = "UTF-8" 
    876         doc.write(fd, encoding=self.reader.encoding, 
     905        if self.encoding == None: 
     906            self.encoding = "UTF-8" 
     907        doc.write(fd, encoding=self.encoding, 
    877908                  pretty_print=True, xml_declaration=True) 
    878909        fd.close() 
    879910     
     911     
     912    # DO NOT REMOVE - used in saving and loading panel states. 
     913    def _store_float(self, location, node, variable, storage, optional=True): 
     914        """ 
     915        Get the content of a xpath location and store 
     916        the result. Check that the units are compatible 
     917        with the destination. The value is expected to 
     918        be a float. 
     919         
     920        The xpath location might or might not exist. 
     921        If it does not exist, nothing is done 
     922        
     923        :param location: xpath location to fetch 
     924        :param node: node to read the data from 
     925        :param variable: name of the data member to store it in [string] 
     926        :param storage: data object that has the 'variable' data member 
     927        :param optional: if True, no exception will be raised 
     928            if unit conversion can't be done 
     929 
     930        :raise ValueError: raised when the units are not recognized 
     931        """ 
     932        entry = get_content(location, node) 
     933        try: 
     934            value = float(entry.text) 
     935        except: 
     936            value = None 
     937             
     938        if value is not None: 
     939            # If the entry has units, check to see that they are 
     940            # compatible with what we currently have in the data object 
     941            units = entry.get('unit') 
     942            if units is not None: 
     943                toks = variable.split('.') 
     944                local_unit = None 
     945                exec "local_unit = storage.%s_unit" % toks[0] 
     946                if local_unit != None and units.lower() != local_unit.lower(): 
     947                    if HAS_CONVERTER == True: 
     948                        try: 
     949                            conv = Converter(units) 
     950                            exec "storage.%s = %g" % (variable, 
     951                                           conv(value, units=local_unit)) 
     952                        except: 
     953                            exc_type, exc_value, exc_traceback = sys.exc_info() 
     954                            err_mess = "CanSAS reader: could not convert" 
     955                            err_mess += " %s unit [%s]; expecting [%s]\n  %s" \ 
     956                                % (variable, units, local_unit, exc_value) 
     957                            self.errors.append(err_mess) 
     958                            if optional: 
     959                                logging.info(err_mess) 
     960                            else: 
     961                                raise ValueError, err_mess 
     962                    else: 
     963                        err_mess = "CanSAS reader: unrecognized %s unit [%s];"\ 
     964                        % (variable, units) 
     965                        err_mess += " expecting [%s]" % local_unit 
     966                        self.errors.append(err_mess) 
     967                        if optional: 
     968                            logging.info(err_mess) 
     969                        else: 
     970                            raise ValueError, err_mess 
     971                else: 
     972                    exec "storage.%s = value" % variable 
     973            else: 
     974                exec "storage.%s = value" % variable 
     975                 
     976     
     977    # DO NOT REMOVE - used in saving and loading panel states. 
     978    def _store_content(self, location, node, variable, storage): 
     979        """ 
     980        Get the content of a xpath location and store 
     981        the result. The value is treated as a string. 
     982         
     983        The xpath location might or might not exist. 
     984        If it does not exist, nothing is done 
     985         
     986        :param location: xpath location to fetch 
     987        :param node: node to read the data from 
     988        :param variable: name of the data member to store it in [string] 
     989        :param storage: data object that has the 'variable' data member 
     990         
     991        :return: return a list of errors 
     992        """ 
     993        entry = get_content(location, node) 
     994        if entry is not None and entry.text is not None: 
     995            exec "storage.%s = entry.text.strip()" % variable 
  • src/sans/dataloader/readers/xml_reader.py

    r2e3b055 rac5b69d  
    1717from lxml import etree 
    1818from lxml.builder import E 
    19 parser = etree.ETCompatXMLParser(remove_comments=True, remove_pis=False) 
     19 
     20PARSER = etree.ETCompatXMLParser(remove_comments=True, remove_pis=False) 
    2021 
    2122class XMLreader(): 
     23    """ 
     24    Generic XML read and write class. Mostly helper functions. 
     25    Makes reading/writing XML a bit easier than calling lxml libraries directly. 
     26     
     27    :Dependencies: 
     28        This class requires lxml 2.3 or higher. 
     29    """ 
    2230     
    2331    xml = None 
     
    2735    schemadoc = None 
    2836    encoding = None 
    29     processingInstructions = None 
     37    processing_instructions = None 
    3038     
    3139    def __init__(self, xml = None, schema = None, root = None): 
    3240        self.xml = xml 
    3341        self.schema = schema 
    34         self.processingInstructions = {} 
     42        self.processing_instructions = {} 
    3543        if xml is not None: 
    36             self.setXMLFile(xml, root) 
     44            self.set_xml_file(xml, root) 
    3745        else: 
    3846            self.xmldoc = None 
    3947            self.xmlroot = None 
    4048        if schema is not None: 
    41             self.setSchema(schema) 
     49            self.set_schema(schema) 
    4250        else: 
    4351            self.schemadoc = None 
     
    4755        Read in an XML file into memory and return an lxml dictionary 
    4856        """ 
    49         if self.validateXML(): 
    50             self.xmldoc = etree.parse(self.xml, parser = parser) 
     57        if self.validate_xml(): 
     58            self.xmldoc = etree.parse(self.xml, parser = PARSER) 
    5159        else: 
    52             raise etree.ValidationError(self, self.findInvalidXML()) 
     60            raise etree.XMLSchemaValidateError(self, self.find_invalid_xml()) 
    5361        return self.xmldoc 
    5462     
    55     def setXMLFile(self, xml, root = None): 
     63    def set_xml_file(self, xml, root = None): 
    5664        """ 
    5765        Set the XML file and parse 
     
    5967        try: 
    6068            self.xml = xml 
    61             self.xmldoc = etree.parse(self.xml, parser = parser) 
     69            self.xmldoc = etree.parse(self.xml, parser = PARSER) 
    6270            self.xmlroot = self.xmldoc.getroot() 
    6371        except Exception: 
     
    6674            self.xmlroot = None 
    6775     
    68     def setSchema(self, schema): 
     76    def set_schema(self, schema): 
    6977        """ 
    7078        Set the schema file and parse 
     
    7280        try: 
    7381            self.schema = schema 
    74             self.schemadoc = etree.parse(self.schema, parser = parser) 
     82            self.schemadoc = etree.parse(self.schema, parser = PARSER) 
    7583        except Exception: 
    7684            self.schema = None 
    7785            self.schemadoc = None 
    7886     
    79     def validateXML(self): 
     87    def validate_xml(self): 
    8088        """ 
    8189        Checks to see if the XML file meets the schema 
     
    8391        valid = True 
    8492        if self.schema is not None: 
    85             self.parseSchemaAndDoc() 
    86             schemaCheck = etree.XMLSchema(self.schemadoc) 
    87             valid = schemaCheck.validate(self.xmldoc) 
     93            self.parse_schema_and_doc() 
     94            schema_check = etree.XMLSchema(self.schemadoc) 
     95            valid = schema_check.validate(self.xmldoc) 
    8896        return valid 
    8997     
    90     def findInvalidXML(self): 
     98    def find_invalid_xml(self): 
    9199        """ 
    92100        Finds the first offending element that should not be present in XML file 
    93101        """ 
    94         firstError = "" 
    95         self.parseSchemaAndDoc() 
     102        first_error = "" 
     103        self.parse_schema_and_doc() 
    96104        schema = etree.XMLSchema(self.schemadoc) 
    97105        try: 
    98             firstError = schema.assertValid(self.xmldoc) 
     106            first_error = schema.assertValid(self.xmldoc) 
    99107        except etree.DocumentInvalid as e: 
    100             firstError = str(e) 
    101         return firstError 
    102      
    103     def parseSchemaAndDoc(self): 
     108            first_error = str(e) 
     109        return first_error 
     110     
     111    def parse_schema_and_doc(self): 
    104112        """ 
    105113        Creates a dictionary of the parsed schema and xml files. 
    106114        """ 
    107         self.setXMLFile(self.xml) 
    108         self.setSchema(self.schema) 
    109          
    110     def toString(self, elem, pp=False, encoding=None): 
     115        self.set_xml_file(self.xml) 
     116        self.set_schema(self.schema) 
     117         
     118    def to_string(self, elem, pp=False, encoding=None): 
    111119        """ 
    112120        Converts an etree element into a string 
     
    129137        return dic 
    130138     
    131     def setProcessingInstructions(self): 
     139    def set_processing_instructions(self): 
    132140        """ 
    133141        Take out all processing instructions and create a dictionary from them 
     
    135143        """ 
    136144        dic = {} 
    137         pi = self.xmlroot.getprevious() 
    138         while pi is not None: 
    139             pi_string = self.toString(pi) 
     145        proc_instr = self.xmlroot.getprevious() 
     146        while proc_instr is not None: 
     147            pi_string = self.to_string(proc_instr) 
    140148            if "?>\n<?" in pi_string: 
    141149                pi_string = pi_string.split("?>\n<?") 
     
    145153                for item in pi_string: 
    146154                    dic = self.break_processing_instructions(item, dic) 
    147             pi = pi.getprevious() 
     155            proc_instr = proc_instr.getprevious() 
    148156        if 'xml' in dic: 
    149             self.setEncoding(dic['xml']) 
     157            self.set_encoding(dic['xml']) 
    150158            del dic['xml'] 
    151         self.processingInstructions = dic 
    152          
    153     def setEncoding(self, attr_str): 
     159        self.processing_instructions = dic 
     160         
     161    def set_encoding(self, attr_str): 
    154162        """ 
    155163        Find the encoding in the xml declaration and save it as a string 
     
    169177        self.encoding = None 
    170178         
    171     def _create_unique_key(self, dictionary, name, i = 0): 
     179    def _create_unique_key(self, dictionary, name, numb = 0): 
    172180        """ 
    173181        Create a unique key value for any dictionary to prevent overwriting 
     
    176184        :param dictionary: A dictionary with any number of entries 
    177185        :param name: The index of the item to be added to dictionary 
    178         :param i: The number to be appended to the name, starts at 0 
     186        :param numb: The number to be appended to the name, starts at 0 
    179187        """ 
    180188        if dictionary.get(name) is not None: 
    181             i += 1 
     189            numb += 1 
    182190            name = name.split("_")[0] 
    183             name += "_{0}".format(i) 
    184             name = self._create_unique_key(dictionary, name, i) 
     191            name += "_{0}".format(numb) 
     192            name = self._create_unique_key(dictionary, name, numb) 
    185193        return name 
    186194     
     
    193201        return etree.ElementTree(root) 
    194202     
    195     def create_element_from_string(self, s): 
     203    def create_element_from_string(self, xml_string): 
    196204        """ 
    197205        Create an element from an XML string 
    198206         
    199         :param s: A string of xml 
    200         """ 
    201         return etree.fromstring(s) 
    202      
    203     def create_element(self, name, attrib={}, nsmap=None): 
     207        :param xml_string: A string of xml 
     208        """ 
     209        return etree.fromstring(xml_string) 
     210     
     211    def create_element(self, name, attrib=None, nsmap=None): 
    204212        """ 
    205213        Create an XML element for writing to file 
     
    207215        :param name: The name of the element to be created 
    208216        """ 
     217        if attrib == None: 
     218            attrib = {} 
    209219        return etree.Element(name, attrib, nsmap) 
    210220     
     
    237247        """ 
    238248        pi_list = [] 
    239         for key in self.processingInstructions: 
    240             value = self.processingInstructions.get(key) 
    241             pi = etree.ProcessingInstruction(key, value) 
    242             pi_list.append(pi) 
     249        if self.processing_instructions is not None: 
     250            for key in self.processing_instructions: 
     251                value = self.processing_instructions.get(key) 
     252                pi_item = etree.ProcessingInstruction(key, value) 
     253                pi_list.append(pi_item) 
    243254        return pi_list 
    244255     
     
    253264        return tree 
    254265     
    255     def ebuilder(self, parent, elementname, text=None, attrib={}): 
     266    def ebuilder(self, parent, elementname, text=None, attrib=None): 
     267        """ 
     268        Use lxml E builder class with arbitrary inputs. 
     269         
     270        :param parnet: The parent element to append a child to 
     271        :param elementname: The name of the child in string form 
     272        :param text: The element text 
     273        :param attrib: A dictionary of attribute names to attribute values 
     274        """ 
    256275        text = str(text) 
     276        if attrib == None: 
     277            attrib = {} 
    257278        elem = E(elementname, attrib, text) 
    258279        parent = parent.append(elem) 
  • src/sans/guiframe/gui_manager.py

    r98816c43 ra3b635b  
    776776        # Append item from plugin under menu file if necessary 
    777777        self._populate_file_menu() 
     778 
     779 
    778780        if not wx.VERSION_STRING >= '3.0.0.0': 
    779781            self.SetMenuBar(self._menubar) 
     
    13491351        if config._do_aboutbox: 
    13501352            self._help_menu.AppendSeparator() 
    1351             id = wx.NewId() 
    1352             self._help_menu.Append(id, '&About', 'Software information') 
    1353             wx.EVT_MENU(self, id, self._onAbout) 
     1353            self._help_menu.Append(wx.ID_ABOUT, '&About', 'Software information') 
     1354            wx.EVT_MENU(self, wx.ID_ABOUT, self._onAbout) 
    13541355         
    13551356        # Checking for updates 
     
    14911492                self._file_menu.AppendSeparator() 
    14921493                 
    1493     def _add_menu_file(self): 
    1494         """ 
    1495         add menu file 
    1496         """ 
    1497          
    1498         # File menu 
    1499         self._file_menu = wx.Menu() 
    15001494        style1 = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS 
    15011495        if OPEN_SAVE_MENU: 
     
    15261520                        'Save state of the current active analysis panel') 
    15271521            wx.EVT_MENU(self, id, self._on_save_application) 
     1522        if not sys.platform =='darwin': 
    15281523            self._file_menu.AppendSeparator() 
    1529         
    1530         id = wx.NewId() 
    1531         self._file_menu.Append(id, '&Quit', 'Exit')  
    1532         wx.EVT_MENU(self, id, self.Close) 
     1524            id = wx.NewId() 
     1525            self._file_menu.Append(id, '&Quit', 'Exit')  
     1526            wx.EVT_MENU(self, id, self.Close) 
     1527         
     1528    def _add_menu_file(self): 
     1529        """ 
     1530        add menu file 
     1531        """ 
     1532        # File menu 
     1533        self._file_menu = wx.Menu() 
    15331534        # Add sub menus 
    15341535        self._menubar.Append(self._file_menu, '&File') 
     
    19471948                if temp is not None: 
    19481949                    doc = temp 
    1949                
     1950             
    19501951            # Write the XML document 
    19511952            extens = APPLICATION_STATE_EXTENSION 
     
    19611962        except: 
    19621963            msg = "Error occurred while saving: " 
    1963             msg += "To save, at leat one application panel " 
     1964            msg += "To save, at least one application panel " 
    19641965            msg += "should have a data set.." 
    19651966            wx.PostEvent(self, StatusEvent(status=msg))     
  • src/sans/perspectives/fitting/pagestate.py

    reddb6ec rac5b69d  
    2020 
    2121import xml.dom.minidom 
     22from xml.dom.minidom import parseString 
    2223from lxml import etree 
    2324 
     
    672673            # We are appending to an existing document 
    673674            newdoc = doc 
    674             top_element = newdoc.createElement(FITTING_NODE_NAME) 
     675            try: 
     676                top_element = newdoc.createElement(FITTING_NODE_NAME) 
     677            except: 
     678                string = etree.tostring(doc, pretty_print=True) 
     679                newdoc = parseString(string) 
     680                top_element = newdoc.createElement(FITTING_NODE_NAME) 
    675681            if entry_node is None: 
    676682                newdoc.documentElement.appendChild(top_element) 
    677683            else: 
    678                 entry_node.appendChild(top_element) 
    679              
     684                try: 
     685                    entry_node.appendChild(top_element) 
     686                except: 
     687                    node_name = entry_node.tag 
     688                    node_list = newdoc.getElementsByTagName(node_name) 
     689                    entry_node = node_list.item(0) 
     690                    entry_node.appendChild(top_element) 
     691                     
    680692        attr = newdoc.createAttribute("version") 
    681693        attr.nodeValue = '1.0' 
     
    750762        for item in list_of_state_parameters: 
    751763            element = newdoc.createElement(item[0]) 
    752             com = "self._toXML_helper(list=self.%s," 
     764            com = "self._toXML_helper(thelist=self.%s," 
    753765            com += " element=element, newdoc=newdoc)" 
    754766            exec com % item[1] 
     
    762774            return None 
    763775        else: 
    764             return newdoc.toprettyxml() 
     776            return newdoc 
    765777         
    766778    def _fromXML_helper(self, node, list): 
     
    12521264                state = PageState() 
    12531265                state.fromXML(node=nodes[0]) 
     1266                 
    12541267        except: 
    12551268            logging.info("XML document does not contain fitting information.\n %s" % sys.exc_value) 
     
    12571270        return state 
    12581271       
    1259     def _parse_entry(self, dom): 
     1272    def _parse_save_state_entry(self, dom): 
    12601273        """ 
    12611274        Parse a SASentry 
     
    12681281        node = dom.xpath('ns:data_class', namespaces={'ns': CANSAS_NS}) 
    12691282        if not node or node[0].text.lstrip().rstrip() != "Data2D": 
    1270             return CansasReader._parse_entry(self, dom) 
     1283            return_value, _ = self._parse_entry(dom) 
     1284            numpy.trim_zeros(return_value.x) 
     1285            numpy.trim_zeros(return_value.y) 
     1286            numpy.trim_zeros(return_value.dy) 
     1287            size_dx = return_value.dx.size 
     1288            size_dxl = return_value.dxl.size 
     1289            size_dxw = return_value.dxw.size 
     1290            if size_dxl == 0 and size_dxw == 0: 
     1291                return_value.dxl = None 
     1292                return_value.dxw = None 
     1293                numpy.trim_zeros(return_value.dx) 
     1294            elif size_dx == 0: 
     1295                return_value.dx = None 
     1296                size_dx = size_dxl 
     1297                numpy.trim_zeros(return_value.dxl) 
     1298                numpy.trim_zeros(return_value.dxw) 
     1299                             
     1300            return return_value, _ 
    12711301         
    12721302        #Parse 2D 
     
    15391569                    for entry in entry_list: 
    15401570                        try: 
    1541                             sas_entry = self._parse_entry(entry) 
     1571                            sas_entry, _ = self._parse_save_state_entry(entry) 
    15421572                        except: 
    15431573                            raise 
     
    16081638        # Sanity check 
    16091639        if self.cansas == True: 
    1610              
    16111640            # Add fitting information to the XML document 
    16121641            doc = self.write_toXML(datainfo, fitstate) 
    16131642            # Write the XML document 
    1614             fd = open(filename, 'w') 
    1615             fd.write(doc.toprettyxml()) 
    1616             fd.close() 
    16171643        else: 
    1618             fitstate.toXML(file=filename) 
     1644            doc = fitstate.toXML(file=filename) 
     1645         
     1646        # Save the document no matter the type 
     1647        fd = open(filename, 'w') 
     1648        fd.write(doc.toprettyxml()) 
     1649        fd.close() 
    16191650         
    16201651    def write_toXML(self, datainfo=None, state=None): 
     
    16381669                state.data.run = [str(state.data.name)] 
    16391670                state.data.run_name[0] = state.data.name 
    1640     
     1671             
    16411672            if issubclass(state.data.__class__, 
    16421673                          sans.dataloader.data_info.Data1D): 
     
    16481679             
    16491680        if state is not None: 
    1650             state.toXML(doc=doc, file=data.filename, entry_node=sasentry) 
    1651              
     1681            doc = state.toXML(doc=doc, file=data.filename, entry_node=sasentry) 
     1682         
    16521683        return doc 
    16531684     
  • src/sans/perspectives/invariant/invariant_panel.py

    r5777106 r92a2ecd  
    218218            if new_doc is not None: 
    219219                if doc is not None and hasattr(doc, "firstChild"): 
    220                     child = new_doc.firstChild.firstChild 
    221                     doc.firstChild.appendChild(child)   
     220                    child = new_doc.getElementsByTagName("SASentry") 
     221                    for item in child: 
     222                        doc.firstChild.appendChild(item) 
    222223                else: 
    223224                    doc = new_doc 
  • src/sans/perspectives/invariant/invariant_state.py

    r51f14603 r92a2ecd  
    254254        : param entry_node: XML node within the XML document at which we will append the data [optional] 
    255255        """ 
     256        # TODO: Get this to work 
    256257        from xml.dom.minidom import getDOMImplementation 
    257258        import time 
     
    273274            else: 
    274275                entry_node.appendChild(top_element) 
    275              
     276                 
    276277        attr = newdoc.createAttribute("version") 
    277278        attr.nodeValue = '1.0' 
     
    352353            return None 
    353354        else: 
    354             return newdoc.toprettyxml() 
     355            return newdoc 
    355356         
    356357    def fromXML(self, file=None, node=None): 
     
    742743                for entry in entry_list: 
    743744                     
    744                     sas_entry = self._parse_entry(entry) 
     745                    sas_entry, _ = self._parse_entry(entry) 
    745746                    invstate = self._parse_state(entry) 
    746747                     
     
    809810        # Add the invariant information to the XML document 
    810811        if state is not None: 
    811             state.toXML(datainfo.name,doc=doc, entry_node=sasentry) 
     812            doc = state.toXML(datainfo.name,doc=doc, entry_node=sasentry) 
    812813        return doc 
    813814 
  • src/sans/perspectives/pr/inversion_panel.py

    r5777106 r92a2ecd  
    255255            if new_doc is not None: 
    256256                if doc is not None and hasattr(doc, "firstChild"): 
    257                     child = new_doc.firstChild.firstChild 
    258                     doc.firstChild.appendChild(child)   
     257                    child = new_doc.getElementsByTagName("SASentry") 
     258                    for item in child: 
     259                        doc.firstChild.appendChild(item) 
    259260                else: 
    260261                    doc = new_doc 
  • src/sans/perspectives/pr/inversion_state.py

    r5777106 r92a2ecd  
    148148         
    149149        """ 
     150        #TODO: Get this to work 
    150151        from xml.dom.minidom import getDOMImplementation 
    151152 
     
    221222            return None 
    222223        else: 
    223             return newdoc.toprettyxml() 
     224            return newdoc 
    224225 
    225226    def fromXML(self, file=None, node=None): 
     
    470471 
    471472                for entry in entry_list: 
    472                     sas_entry = self._parse_entry(entry) 
     473                    sas_entry, _ = self._parse_entry(entry) 
    473474                    prstate = self._parse_prstate(entry) 
    474475                    #prstate could be None when .svs file is loaded 
     
    504505        # Sanity check 
    505506        if self.cansas == True: 
    506             doc =self.write_toXML(datainfo, prstate)         
     507            doc = self.write_toXML(datainfo, prstate)         
    507508            # Write the XML document 
    508509            fd = open(filename, 'w') 
     
    527528        # Create basic XML document 
    528529        doc, sasentry = self._to_xml_doc(datainfo) 
    529      
     530         
    530531        # Add the invariant information to the XML document 
    531532        if state is not None: 
    532             state.toXML(doc=doc, entry_node=sasentry) 
     533            doc = state.toXML(doc=doc, entry_node=sasentry) 
    533534             
    534535        return doc  
  • src/sans/fit/AbstractFitEngine.py

    r6c00702 r8d074d9  
    33#import logging 
    44import sys 
     5import math 
    56import numpy 
    6 import math 
    7 import park 
     7 
    88from sans.dataloader.data_info import Data1D 
    99from sans.dataloader.data_info import Data2D 
    10 _SMALLVALUE = 1.0e-10     
    11      
    12 class SansParameter(park.Parameter): 
    13     """ 
    14     SANS model parameters for use in the PARK fitting service. 
    15     The parameter attribute value is redirected to the underlying 
    16     parameter value in the SANS model. 
    17     """ 
    18     def __init__(self, name, model, data): 
    19         """ 
    20             :param name: the name of the model parameter 
    21             :param model: the sans model to wrap as a park model 
    22         """ 
    23         park.Parameter.__init__(self, name) 
    24         self._model, self._name = model, name 
    25         self.data = data 
    26         self.model = model 
    27         #set the value for the parameter of the given name 
    28         self.set(model.getParam(name)) 
    29           
    30     def _getvalue(self): 
    31         """ 
    32         override the _getvalue of park parameter 
    33          
    34         :return value the parameter associates with self.name 
    35          
    36         """ 
    37         return self._model.getParam(self.name) 
    38      
    39     def _setvalue(self, value): 
    40         """ 
    41         override the _setvalue pf park parameter 
    42          
    43         :param value: the value to set on a given parameter 
    44          
    45         """ 
    46         self._model.setParam(self.name, value) 
    47          
    48     value = property(_getvalue, _setvalue) 
    49      
    50     def _getrange(self): 
    51         """ 
    52         Override _getrange of park parameter 
    53         return the range of parameter 
    54         """ 
    55         #if not  self.name in self._model.getDispParamList(): 
    56         lo, hi = self._model.details[self.name][1:3] 
    57         if lo is None: lo = -numpy.inf 
    58         if hi is None: hi = numpy.inf 
    59         if lo > hi: 
    60             raise ValueError, "wrong fit range for parameters" 
    61          
    62         return lo, hi 
    63      
    64     def get_name(self): 
    65         """ 
    66         """ 
    67         return self._getname() 
    68      
    69     def _setrange(self, r): 
    70         """ 
    71         override _setrange of park parameter 
    72          
    73         :param r: the value of the range to set 
    74          
    75         """ 
    76         self._model.details[self.name][1:3] = r 
    77     range = property(_getrange, _setrange) 
    78      
    79      
    80 class Model(park.Model): 
    81     """ 
    82     PARK wrapper for SANS models. 
     10_SMALLVALUE = 1.0e-10 
     11 
     12# Note: duplicated from park 
     13class FitHandler(object): 
     14    """ 
     15    Abstract interface for fit thread handler. 
     16 
     17    The methods in this class are called by the optimizer as the fit 
     18    progresses. 
     19 
     20    Note that it is up to the optimizer to call the fit handler correctly, 
     21    reporting all status changes and maintaining the 'done' flag. 
     22    """ 
     23    done = False 
     24    """True when the fit job is complete""" 
     25    result = None 
     26    """The current best result of the fit""" 
     27 
     28    def improvement(self): 
     29        """ 
     30        Called when a result is observed which is better than previous 
     31        results from the fit. 
     32 
     33        result is a FitResult object, with parameters, #calls and fitness. 
     34        """ 
     35    def error(self, msg): 
     36        """ 
     37        Model had an error; print traceback 
     38        """ 
     39    def progress(self, current, expected): 
     40        """ 
     41        Called each cycle of the fit, reporting the current and the 
     42        expected amount of work.   The meaning of these values is 
     43        optimizer dependent, but they can be converted into a percent 
     44        complete using (100*current)//expected. 
     45 
     46        Progress is updated each iteration of the fit, whatever that 
     47        means for the particular optimization algorithm.  It is called 
     48        after any calls to improvement for the iteration so that the 
     49        update handler can control I/O bandwidth by suppressing 
     50        intermediate improvements until the fit is complete. 
     51        """ 
     52    def finalize(self): 
     53        """ 
     54        Fit is complete; best results are reported 
     55        """ 
     56    def abort(self): 
     57        """ 
     58        Fit was aborted. 
     59        """ 
     60 
     61    # TODO: not sure how these are used, but they are needed for running the fit 
     62    def update_fit(self, last=False): pass 
     63    def set_result(self, result=None): self.result = result 
     64 
     65class Model: 
     66    """ 
     67    Fit wrapper for SANS models. 
    8368    """ 
    8469    def __init__(self, sans_model, sans_data=None, **kw): 
    8570        """ 
    8671        :param sans_model: the sans model to wrap using park interface 
    87          
    88         """ 
    89         park.Model.__init__(self, **kw) 
     72 
     73        """ 
    9074        self.model = sans_model 
    9175        self.name = sans_model.name 
    9276        self.data = sans_data 
    93         #list of parameters names 
    94         self.sansp = sans_model.getParamList() 
    95         #list of park parameter 
    96         self.parkp = [SansParameter(p, sans_model, sans_data) for p in self.sansp] 
    97         #list of parameter set 
    98         self.parameterset = park.ParameterSet(sans_model.name, pars=self.parkp) 
    99         self.pars = [] 
    100    
     77 
    10178    def get_params(self, fitparams): 
    10279        """ 
    10380        return a list of value of paramter to fit 
    104          
     81 
    10582        :param fitparams: list of paramaters name to fit 
    106          
    107         """ 
    108         list_params = [] 
    109         self.pars = [] 
    110         self.pars = fitparams 
    111         for item in fitparams: 
    112             for element in self.parkp: 
    113                 if element.name == str(item): 
    114                     list_params.append(element.value) 
    115         return list_params 
    116      
     83 
     84        """ 
     85        return [self.model.getParam(k) for k in fitparams] 
     86 
    11787    def set_params(self, paramlist, params): 
    11888        """ 
    11989        Set value for parameters to fit 
    120          
     90 
    12191        :param params: list of value for parameters to fit 
    122          
    123         """ 
    124         try: 
    125             for i in range(len(self.parkp)): 
    126                 for j in range(len(paramlist)): 
    127                     if self.parkp[i].name == paramlist[j]: 
    128                         self.parkp[i].value = params[j] 
    129                         self.model.setParam(self.parkp[i].name, params[j]) 
    130         except: 
    131             raise 
    132    
     92 
     93        """ 
     94        for k,v in zip(paramlist, params): 
     95            self.model.setParam(k,v) 
     96 
     97    def set(self, **kw): 
     98        self.set_params(*zip(*kw.items())) 
     99 
    133100    def eval(self, x): 
    134101        """ 
    135102            Override eval method of park model. 
    136          
     103 
    137104            :param x: the x value used to compute a function 
    138105        """ 
     
    141108        except: 
    142109            raise 
    143          
     110 
    144111    def eval_derivs(self, x, pars=[]): 
    145112        """ 
     
    154121        instead of calling eval. 
    155122        """ 
    156         return [] 
    157  
    158      
     123        raise NotImplementedError('no derivatives available') 
     124 
     125    def __call__(self, x): 
     126        return self.eval(x) 
     127 
    159128class FitData1D(Data1D): 
    160129    """ 
     
    185154        """ 
    186155        Data1D.__init__(self, x=x, y=y, dx=dx, dy=dy) 
     156        self.num_points = len(x) 
    187157        self.sans_data = data 
    188158        self.smearer = smearer 
     
    251221        """ 
    252222        return self.qmin, self.qmax 
    253          
     223 
     224    def size(self): 
     225        """ 
     226        Number of measurement points in data set after masking, etc. 
     227        """ 
     228        return len(self.x) 
     229 
    254230    def residuals(self, fn): 
    255231        """ 
     
    293269    def __init__(self, sans_data2d, data=None, err_data=None): 
    294270        Data2D.__init__(self, data=data, err_data=err_data) 
    295         """ 
    296             Data can be initital with a data (sans plottable) 
    297             or with vectors. 
    298         """ 
     271        # Data can be initialized with a sans plottable or with vectors. 
    299272        self.res_err_image = [] 
     273        self.num_points = 0 # will be set by set_data 
    300274        self.idx = [] 
    301275        self.qmin = None 
     
    339313        self.idx = (self.idx) & (self.mask) 
    340314        self.idx = (self.idx) & (numpy.isfinite(self.data)) 
     315        self.num_points = numpy.sum(self.idx) 
    341316 
    342317    def set_smearer(self, smearer): 
     
    372347        """ 
    373348        return self.qmin, self.qmax 
    374       
     349 
     350    def size(self): 
     351        """ 
     352        Number of measurement points in data set after masking, etc. 
     353        """ 
     354        return numpy.sum(self.idx) 
     355 
    375356    def residuals(self, fn): 
    376357        """ 
     
    409390 
    410391 
    411 class SansAssembly: 
    412     """ 
    413     Sans Assembly class a class wrapper to be call in optimizer.leastsq method 
    414     """ 
    415     def __init__(self, paramlist, model=None, data=None, fitresult=None, 
    416                  handler=None, curr_thread=None, msg_q=None): 
    417         """ 
    418         :param Model: the model wrapper fro sans -model 
    419         :param Data: the data wrapper for sans data 
    420          
    421         """ 
    422         self.model = model 
    423         self.data = data 
    424         self.paramlist = paramlist 
    425         self.msg_q = msg_q 
    426         self.curr_thread = curr_thread 
    427         self.handler = handler 
    428         self.fitresult = fitresult 
    429         self.res = [] 
    430         self.true_res = [] 
    431         self.func_name = "Functor" 
    432         self.theory = None 
    433          
    434     def chisq(self): 
    435         """ 
    436         Calculates chi^2 
    437          
    438         :param params: list of parameter values 
    439          
    440         :return: chi^2 
    441          
    442         """ 
    443         total = 0 
    444         for item in self.true_res: 
    445             total += item * item 
    446         if len(self.true_res) == 0: 
    447             return None 
    448         return total / len(self.true_res) 
    449      
    450     def __call__(self, params): 
    451         """ 
    452             Compute residuals 
    453             :param params: value of parameters to fit 
    454         """ 
    455         #import thread 
    456         self.model.set_params(self.paramlist, params) 
    457         #print "params", params 
    458         self.true_res, theory = self.data.residuals(self.model.eval) 
    459         self.theory = copy.deepcopy(theory) 
    460         # check parameters range 
    461         if self.check_param_range(): 
    462             # if the param value is outside of the bound 
    463             # just silent return res = inf 
    464             return self.res 
    465         self.res = self.true_res 
    466          
    467         if self.fitresult is not None: 
    468             self.fitresult.set_model(model=self.model) 
    469             self.fitresult.residuals = self.true_res 
    470             self.fitresult.iterations += 1 
    471             self.fitresult.theory = theory 
    472             
    473             #fitness = self.chisq(params=params) 
    474             fitness = self.chisq() 
    475             self.fitresult.pvec = params 
    476             self.fitresult.set_fitness(fitness=fitness) 
    477             if self.msg_q is not None: 
    478                 self.msg_q.put(self.fitresult) 
    479                  
    480             if self.handler is not None: 
    481                 self.handler.set_result(result=self.fitresult) 
    482                 self.handler.update_fit() 
    483  
    484             if self.curr_thread != None: 
    485                 try: 
    486                     self.curr_thread.isquit() 
    487                 except: 
    488                     #msg = "Fitting: Terminated...       Note: Forcing to stop " 
    489                     #msg += "fitting may cause a 'Functor error message' " 
    490                     #msg += "being recorded in the log file....." 
    491                     #self.handler.stop(msg) 
    492                     raise 
    493           
    494         return self.res 
    495      
    496     def check_param_range(self): 
    497         """ 
    498         Check the lower and upper bound of the parameter value 
    499         and set res to the inf if the value is outside of the 
    500         range 
    501         :limitation: the initial values must be within range. 
    502         """ 
    503  
    504         #time.sleep(0.01) 
    505         is_outofbound = False 
    506         # loop through the fit parameters 
    507         for p in self.model.parameterset: 
    508             param_name = p.get_name() 
    509             if param_name in self.paramlist: 
    510                  
    511                 # if the range was defined, check the range 
    512                 if numpy.isfinite(p.range[0]): 
    513                     if p.value == 0: 
    514                         # This value works on Scipy 
    515                         # Do not change numbers below 
    516                         value = _SMALLVALUE 
    517                     else: 
    518                         value = p.value 
    519                     # For leastsq, it needs a bit step back from the boundary 
    520                     val = p.range[0] - value * _SMALLVALUE 
    521                     if p.value < val: 
    522                         self.res *= 1e+6 
    523                          
    524                         is_outofbound = True 
    525                         break 
    526                 if numpy.isfinite(p.range[1]): 
    527                     # This value works on Scipy 
    528                     # Do not change numbers below 
    529                     if p.value == 0: 
    530                         value = _SMALLVALUE 
    531                     else: 
    532                         value = p.value 
    533                     # For leastsq, it needs a bit step back from the boundary 
    534                     val = p.range[1] + value * _SMALLVALUE 
    535                     if p.value > val: 
    536                         self.res *= 1e+6 
    537                         is_outofbound = True 
    538                         break 
    539  
    540         return is_outofbound 
    541      
    542      
     392 
    543393class FitEngine: 
    544394    def __init__(self): 
     
    571421         
    572422        """ 
    573         if model == None: 
    574             raise ValueError, "AbstractFitEngine: Need to set model to fit" 
    575          
    576         new_model = model 
     423        if not pars: 
     424            raise ValueError("no fitting parameters") 
     425 
     426        if model is None: 
     427            raise ValueError("no model to fit") 
     428 
    577429        if not issubclass(model.__class__, Model): 
    578             new_model = Model(model, data) 
    579          
    580         if len(constraints) > 0: 
    581             for constraint in constraints: 
    582                 name, value = constraint 
    583                 try: 
    584                     new_model.parameterset[str(name)].set(str(value)) 
    585                 except: 
    586                     msg = "Fit Engine: Error occurs when setting the constraint" 
    587                     msg += " %s for parameter %s " % (value, name) 
    588                     raise ValueError, msg 
    589                  
    590         if len(pars) > 0: 
    591             temp = [] 
    592             for item in pars: 
    593                 if item in new_model.model.getParamList(): 
    594                     temp.append(item) 
    595                     self.param_list.append(item) 
    596                 else: 
    597                      
    598                     msg = "wrong parameter %s used " % str(item) 
    599                     msg += "to set model %s. Choose " % str(new_model.model.name) 
    600                     msg += "parameter name within %s" % \ 
    601                                 str(new_model.model.getParamList()) 
    602                     raise ValueError, msg 
    603                
    604             #A fitArrange is already created but contains data_list only at id 
    605             if self.fit_arrange_dict.has_key(id): 
    606                 self.fit_arrange_dict[id].set_model(new_model) 
    607                 self.fit_arrange_dict[id].pars = pars 
    608             else: 
    609             #no fitArrange object has been create with this id 
    610                 fitproblem = FitArrange() 
    611                 fitproblem.set_model(new_model) 
    612                 fitproblem.pars = pars 
    613                 self.fit_arrange_dict[id] = fitproblem 
    614                 vals = [] 
    615                 for name in pars: 
    616                     vals.append(new_model.model.getParam(name)) 
    617                 self.fit_arrange_dict[id].vals = vals 
    618         else: 
    619             raise ValueError, "park_integration:missing parameters" 
    620      
     430            model = Model(model, data) 
     431 
     432        sasmodel = model.model 
     433        available_parameters = sasmodel.getParamList() 
     434        for p in pars: 
     435            if p not in available_parameters: 
     436                raise ValueError("parameter %s not available in model %s; use one of [%s] instead" 
     437                                 %(p, sasmodel.name, ", ".join(available_parameters))) 
     438 
     439        if id not in self.fit_arrange_dict: 
     440            self.fit_arrange_dict[id] = FitArrange() 
     441 
     442        self.fit_arrange_dict[id].set_model(model) 
     443        self.fit_arrange_dict[id].pars = pars 
     444        self.fit_arrange_dict[id].vals = [sasmodel.getParam(name) for name in pars] 
     445        self.fit_arrange_dict[id].constraints = constraints 
     446 
     447        self.param_list.extend(pars) 
     448 
    621449    def set_data(self, data, id, smearer=None, qmin=None, qmax=None): 
    622450        """ 
     
    700528        self.vals = [] 
    701529        self.selected = 0 
    702          
     530 
    703531    def set_model(self, model): 
    704532        """ 
     
    752580        """ 
    753581        return self.selected 
    754      
    755      
    756 IS_MAC = True 
    757 if sys.platform.count("win32") > 0: 
    758     IS_MAC = False 
    759  
    760582 
    761583class FResult(object): 
     
    765587    def __init__(self, model=None, param_list=None, data=None): 
    766588        self.calls = None 
    767         self.pars = [] 
    768589        self.fitness = None 
    769590        self.chisqr = None 
     
    776597        self.residuals = [] 
    777598        self.index = [] 
    778         self.parameters = None 
    779         self.is_mac = IS_MAC 
    780599        self.model = model 
    781600        self.data = data 
     
    803622        if self.pvec == None and self.model is None and self.param_list is None: 
    804623            return "No results" 
    805         n = len(self.model.parameterset) 
    806          
    807         result_param = zip(xrange(n), self.model.parameterset) 
    808         msg1 = ["[Iteration #: %s ]" % self.iterations] 
    809         msg3 = ["=== goodness of fit: %s ===" % (str(self.fitness))] 
    810         if not self.is_mac: 
    811             msg2 = ["P%-3d  %s......|.....%s" % \ 
    812                 (p[0], p[1], p[1].value)\ 
    813                   for p in result_param if p[1].name in self.param_list] 
    814             msg = msg1 + msg3 + msg2 
    815         else: 
    816             msg = msg1 + msg3 
    817         msg = "\n".join(msg) 
    818         return msg 
     624 
     625        sasmodel = self.model.model 
     626        pars = enumerate(sasmodel.getParamList()) 
     627        msg1 = "[Iteration #: %s ]" % self.iterations 
     628        msg3 = "=== goodness of fit: %s ===" % (str(self.fitness)) 
     629        msg2 = ["P%-3d  %s......|.....%s" % (i, v, sasmodel.getParam(v)) 
     630                for i,v in pars if v in self.param_list] 
     631        msg = [msg1, msg3] + msg2 
     632        return "\n".join(msg) 
    819633     
    820634    def print_summary(self): 
    821635        """ 
    822636        """ 
    823         print self 
     637        print str(self) 
  • src/sans/fit/Fitting.py

    r5777106 re3efa6b3  
    88from sans.fit.ScipyFitting import ScipyFit 
    99from sans.fit.ParkFitting import ParkFit 
     10from sans.fit.BumpsFitting import BumpsFit 
    1011 
     12ENGINES={ 
     13    'scipy': ScipyFit, 
     14    'park': ParkFit, 
     15    'bumps': BumpsFit, 
     16} 
    1117 
    1218class Fit(object): 
     
    2632         
    2733    """   
    28     def __init__(self, engine='scipy'): 
     34    def __init__(self, engine='scipy', *args, **kw): 
    2935        """ 
    3036        """ 
     
    3238        self._engine = None 
    3339        self.fitter_id = None 
    34         self.set_engine(engine) 
     40        self.set_engine(engine, *args, **kw) 
    3541           
    3642    def __setattr__(self, name, value): 
     
    4955            self.__dict__[name] = value 
    5056                 
    51     def set_engine(self, word): 
     57    def set_engine(self, word, *args, **kw): 
    5258        """ 
    5359        Select the type of Fit  
     
    5965              
    6066        """ 
    61         if word == "scipy": 
    62             self._engine = ScipyFit() 
    63         elif word == "park": 
    64             self._engine = ParkFit() 
    65         else: 
    66             raise ValueError, "enter the keyword scipy or park" 
     67        try: 
     68            self._engine = ENGINES[word](*args, **kw) 
     69        except KeyError, exc: 
     70            raise KeyError("fit engine should be one of scipy, park or bumps") 
    6771 
    6872    def fit(self, msg_q=None, q=None, handler=None,  
  • src/sans/fit/Loader.py

    r5777106 r6fe5100  
    88    This class is loading values from given file or value giving by the user 
    99    """ 
    10      
    1110    def __init__(self, x=None, y=None, dx=None, dy=None): 
     11        raise NotImplementedError("a code search shows that this code is not active, and you are not seeing this message") 
    1212        # variable to store loaded values 
    1313        self.x = x 
  • src/sans/fit/ParkFitting.py

    r9d6d5ba r8d074d9  
    2424from sans.fit.AbstractFitEngine import FitEngine 
    2525from sans.fit.AbstractFitEngine import FResult 
    26    
     26 
     27class SansParameter(park.Parameter): 
     28    """ 
     29    SANS model parameters for use in the PARK fitting service. 
     30    The parameter attribute value is redirected to the underlying 
     31    parameter value in the SANS model. 
     32    """ 
     33    def __init__(self, name, model, data): 
     34        """ 
     35            :param name: the name of the model parameter 
     36            :param model: the sans model to wrap as a park model 
     37        """ 
     38        park.Parameter.__init__(self, name) 
     39        #self._model, self._name = model, name 
     40        self.data = data 
     41        self.model = model 
     42        #set the value for the parameter of the given name 
     43        self.set(model.getParam(name)) 
     44 
     45        # TODO: model is missing parameter ranges for dispersion parameters 
     46        if name not in model.details: 
     47            #print "setting details for",name 
     48            model.details[name] = ["", None, None] 
     49 
     50    def _getvalue(self): 
     51        """ 
     52        override the _getvalue of park parameter 
     53 
     54        :return value the parameter associates with self.name 
     55 
     56        """ 
     57        return self.model.getParam(self.name) 
     58 
     59    def _setvalue(self, value): 
     60        """ 
     61        override the _setvalue pf park parameter 
     62 
     63        :param value: the value to set on a given parameter 
     64 
     65        """ 
     66        self.model.setParam(self.name, value) 
     67 
     68    value = property(_getvalue, _setvalue) 
     69 
     70    def _getrange(self): 
     71        """ 
     72        Override _getrange of park parameter 
     73        return the range of parameter 
     74        """ 
     75        #if not  self.name in self._model.getDispParamList(): 
     76        lo, hi = self.model.details[self.name][1:3] 
     77        if lo is None: lo = -numpy.inf 
     78        if hi is None: hi = numpy.inf 
     79        if lo > hi: 
     80            raise ValueError, "wrong fit range for parameters" 
     81 
     82        return lo, hi 
     83 
     84    def get_name(self): 
     85        """ 
     86        """ 
     87        return self._getname() 
     88 
     89    def _setrange(self, r): 
     90        """ 
     91        override _setrange of park parameter 
     92 
     93        :param r: the value of the range to set 
     94 
     95        """ 
     96        self.model.details[self.name][1:3] = r 
     97    range = property(_getrange, _setrange) 
     98 
     99 
     100class ParkModel(park.Model): 
     101    """ 
     102    PARK wrapper for SANS models. 
     103    """ 
     104    def __init__(self, sans_model, sans_data=None, **kw): 
     105        """ 
     106        :param sans_model: the sans model to wrap using park interface 
     107 
     108        """ 
     109        park.Model.__init__(self, **kw) 
     110        self.model = sans_model 
     111        self.name = sans_model.name 
     112        self.data = sans_data 
     113        #list of parameters names 
     114        self.sansp = sans_model.getParamList() 
     115        #list of park parameter 
     116        self.parkp = [SansParameter(p, sans_model, sans_data) for p in self.sansp] 
     117        #list of parameter set 
     118        self.parameterset = park.ParameterSet(sans_model.name, pars=self.parkp) 
     119        self.pars = [] 
     120 
     121    def get_params(self, fitparams): 
     122        """ 
     123        return a list of value of paramter to fit 
     124 
     125        :param fitparams: list of paramaters name to fit 
     126 
     127        """ 
     128        list_params = [] 
     129        self.pars = fitparams 
     130        for item in fitparams: 
     131            for element in self.parkp: 
     132                if element.name == str(item): 
     133                    list_params.append(element.value) 
     134        return list_params 
     135 
     136    def set_params(self, paramlist, params): 
     137        """ 
     138        Set value for parameters to fit 
     139 
     140        :param params: list of value for parameters to fit 
     141 
     142        """ 
     143        try: 
     144            for i in range(len(self.parkp)): 
     145                for j in range(len(paramlist)): 
     146                    if self.parkp[i].name == paramlist[j]: 
     147                        self.parkp[i].value = params[j] 
     148                        self.model.setParam(self.parkp[i].name, params[j]) 
     149        except: 
     150            raise 
     151 
     152    def eval(self, x): 
     153        """ 
     154            Override eval method of park model. 
     155 
     156            :param x: the x value used to compute a function 
     157        """ 
     158        try: 
     159            return self.model.evalDistribution(x) 
     160        except: 
     161            raise 
     162 
     163    def eval_derivs(self, x, pars=[]): 
     164        """ 
     165        Evaluate the model and derivatives wrt pars at x. 
     166 
     167        pars is a list of the names of the parameters for which derivatives 
     168        are desired. 
     169 
     170        This method needs to be specialized in the model to evaluate the 
     171        model function.  Alternatively, the model can implement is own 
     172        version of residuals which calculates the residuals directly 
     173        instead of calling eval. 
     174        """ 
     175        return [] 
     176 
     177 
    27178class SansFitResult(fitresult.FitResult): 
    28179    def __init__(self, *args, **kwrds): 
     
    244395        return fitpars 
    245396     
    246     def all_results(self, result): 
     397    def extend_results_with_calculated_parameters(self, result): 
    247398        """ 
    248399        Extend result from the fit with the calculated parameters. 
     
    292443                # dividing residuals by N in order to be consistent with Scipy 
    293444                m.chisq = numpy.sum(m.residuals**2/N)  
    294                 resid.append(m.weight*m.residuals/math.sqrt(N)) 
     445                resid.append(m.weight*m.residuals) 
    295446        self.residuals = numpy.hstack(resid) 
    296447        N = len(self.residuals) 
    297448        self.degrees_of_freedom = N-k if N>k else 1 
    298449        self.chisq = numpy.sum(self.residuals**2) 
    299         return self.chisq 
     450        return self.chisq/self.degrees_of_freedom 
    300451     
    301452class ParkFit(FitEngine): 
     
    354505            if fproblem.get_to_fit() == 1: 
    355506                fitproblems.append(fproblem) 
    356         if len(fitproblems) == 0:  
     507        if len(fitproblems) == 0: 
    357508            raise RuntimeError, "No Assembly scheduled for Park fitting." 
    358             return 
    359509        for item in fitproblems: 
    360             parkmodel = item.get_model() 
     510            model = item.get_model() 
     511            parkmodel = ParkModel(model.model, model.data) 
     512            parkmodel.pars = item.pars 
    361513            if reset_flag: 
    362514                # reset the initial value; useful for batch 
     
    364516                    ind = item.pars.index(name) 
    365517                    parkmodel.model.setParam(name, item.vals[ind]) 
     518 
     519            # set the constraints into the model 
     520            for p,v in item.constraints: 
     521                parkmodel.parameterset[str(p)].set(str(v)) 
    366522             
    367523            for p in parkmodel.parameterset: 
    368524                ## does not allow status change for constraint parameters 
    369525                if p.status != 'computed': 
    370                     if p.get_name()in item.pars: 
     526                    if p.get_name() in item.pars: 
    371527                        ## make parameters selected for  
    372528                        #fit will be between boundaries 
     
    383539    def fit(self, msg_q=None,  
    384540            q=None, handler=None, curr_thread=None,  
    385                                         ftol=1.49012e-8, reset_flag=False): 
     541            ftol=1.49012e-8, reset_flag=False): 
    386542        """ 
    387543        Performs fit with park.fit module.It can  perform fit with one model 
     
    407563        localfit = SansFitSimplex() 
    408564        localfit.ftol = ftol 
    409          
     565        localfit.xtol = 1e-6 
     566 
    410567        # See `park.fitresult.FitHandler` for details. 
    411568        fitter = SansFitMC(localfit=localfit, start_points=1) 
     
    416573        try: 
    417574            result = fit.fit(self.problem, fitter=fitter, handler=handler) 
    418             self.problem.all_results(result) 
     575            self.problem.extend_results_with_calculated_parameters(result) 
    419576             
    420577        except LinAlgError: 
    421578            raise ValueError, "SVD did not converge" 
     579 
     580        if result is None: 
     581            raise RuntimeError("park did not return a fit result") 
    422582     
    423583        for m in self.problem.parts: 
     
    427587            small_result.theory = theory 
    428588            small_result.residuals = residuals 
    429             small_result.pvec = [] 
    430             small_result.cov = [] 
    431             small_result.stderr = [] 
    432             small_result.param_list = [] 
    433             small_result.residuals = m.residuals 
    434             if result is not None: 
    435                 for p in result.parameters: 
    436                     if p.data.name == small_result.data.name and \ 
    437                             p.model.name == small_result.model.name: 
    438                         small_result.index = m.data.idx 
    439                         small_result.fitness = result.fitness 
    440                         small_result.pvec.append(p.value) 
    441                         small_result.stderr.append(p.stderr) 
    442                         name_split = p.name.split('.') 
    443                         name = name_split[1].strip() 
    444                         if len(name_split) > 2: 
    445                             name += '.' + name_split[2].strip() 
    446                         small_result.param_list.append(name) 
     589            small_result.index = m.data.idx 
     590            small_result.fitness = result.fitness 
     591 
     592            # Extract the parameters that are part of this model; make sure 
     593            # they match the fitted parameters for this model, and place them 
     594            # in the same order as they occur in the model. 
     595            pars = {} 
     596            for p in result.parameters: 
     597                #if p.data.name == small_result.data.name and 
     598                if p.model.name == small_result.model.name: 
     599                    model_name, par_name = p.name.split('.', 1) 
     600                    pars[par_name] = (p.value, p.stderr) 
     601            #assert len(pars.keys()) == len(m.model.pars) 
     602            v,dv = zip(*[pars[p] for p in m.model.pars]) 
     603            small_result.pvec = v 
     604            small_result.stderr = dv 
     605            small_result.param_list = m.model.pars 
     606 
     607            # normalize chisq by degrees of freedom 
     608            dof = len(small_result.residuals)-len(small_result.pvec) 
     609            small_result.fitness = numpy.sum(residuals**2)/dof 
     610 
    447611            result_list.append(small_result)     
    448612        if q != None: 
  • src/sans/fit/ScipyFitting.py

    r5777106 r8d074d9  
    1  
    2  
    31""" 
    42ScipyFitting module contains FitArrange , ScipyFit, 
     
    64simple fit with scipy optimizer. 
    75""" 
     6import sys 
     7import copy 
    88 
    99import numpy  
    10 import sys 
    11  
    1210 
    1311from sans.fit.AbstractFitEngine import FitEngine 
    14 from sans.fit.AbstractFitEngine import SansAssembly 
    15 from sans.fit.AbstractFitEngine import FitAbort 
    16 from sans.fit.AbstractFitEngine import Model 
    17 from sans.fit.AbstractFitEngine import FResult  
     12from sans.fit.AbstractFitEngine import FResult 
     13 
     14class SansAssembly: 
     15    """ 
     16    Sans Assembly class a class wrapper to be call in optimizer.leastsq method 
     17    """ 
     18    def __init__(self, paramlist, model=None, data=None, fitresult=None, 
     19                 handler=None, curr_thread=None, msg_q=None): 
     20        """ 
     21        :param Model: the model wrapper fro sans -model 
     22        :param Data: the data wrapper for sans data 
     23 
     24        """ 
     25        self.model = model 
     26        self.data = data 
     27        self.paramlist = paramlist 
     28        self.msg_q = msg_q 
     29        self.curr_thread = curr_thread 
     30        self.handler = handler 
     31        self.fitresult = fitresult 
     32        self.res = [] 
     33        self.true_res = [] 
     34        self.func_name = "Functor" 
     35        self.theory = None 
     36 
     37    def chisq(self): 
     38        """ 
     39        Calculates chi^2 
     40 
     41        :param params: list of parameter values 
     42 
     43        :return: chi^2 
     44 
     45        """ 
     46        total = 0 
     47        for item in self.true_res: 
     48            total += item * item 
     49        if len(self.true_res) == 0: 
     50            return None 
     51        return total / (len(self.true_res) - len(self.paramlist)) 
     52 
     53    def __call__(self, params): 
     54        """ 
     55            Compute residuals 
     56            :param params: value of parameters to fit 
     57        """ 
     58        #import thread 
     59        self.model.set_params(self.paramlist, params) 
     60        #print "params", params 
     61        self.true_res, theory = self.data.residuals(self.model.eval) 
     62        self.theory = copy.deepcopy(theory) 
     63        # check parameters range 
     64        if self.check_param_range(): 
     65            # if the param value is outside of the bound 
     66            # just silent return res = inf 
     67            return self.res 
     68        self.res = self.true_res 
     69 
     70        if self.fitresult is not None: 
     71            self.fitresult.set_model(model=self.model) 
     72            self.fitresult.residuals = self.true_res 
     73            self.fitresult.iterations += 1 
     74            self.fitresult.theory = theory 
     75 
     76            #fitness = self.chisq(params=params) 
     77            fitness = self.chisq() 
     78            self.fitresult.pvec = params 
     79            self.fitresult.set_fitness(fitness=fitness) 
     80            if self.msg_q is not None: 
     81                self.msg_q.put(self.fitresult) 
     82 
     83            if self.handler is not None: 
     84                self.handler.set_result(result=self.fitresult) 
     85                self.handler.update_fit() 
     86 
     87            if self.curr_thread != None: 
     88                try: 
     89                    self.curr_thread.isquit() 
     90                except: 
     91                    #msg = "Fitting: Terminated...       Note: Forcing to stop " 
     92                    #msg += "fitting may cause a 'Functor error message' " 
     93                    #msg += "being recorded in the log file....." 
     94                    #self.handler.stop(msg) 
     95                    raise 
     96 
     97        return self.res 
     98 
     99    def check_param_range(self): 
     100        """ 
     101        Check the lower and upper bound of the parameter value 
     102        and set res to the inf if the value is outside of the 
     103        range 
     104        :limitation: the initial values must be within range. 
     105        """ 
     106 
     107        #time.sleep(0.01) 
     108        is_outofbound = False 
     109        # loop through the fit parameters 
     110        model = self.model.model 
     111        for p in self.paramlist: 
     112            value = model.getParam(p) 
     113            low,high = model.details[p][1:3] 
     114            if low is not None and numpy.isfinite(low): 
     115                if p.value == 0: 
     116                    # This value works on Scipy 
     117                    # Do not change numbers below 
     118                    value = _SMALLVALUE 
     119                # For leastsq, it needs a bit step back from the boundary 
     120                val = low - value * _SMALLVALUE 
     121                if value < val: 
     122                    self.res *= 1e+6 
     123                    is_outofbound = True 
     124                    break 
     125            if high is not None and numpy.isfinite(high): 
     126                # This value works on Scipy 
     127                # Do not change numbers below 
     128                if value == 0: 
     129                    value = _SMALLVALUE 
     130                # For leastsq, it needs a bit step back from the boundary 
     131                val = high + value * _SMALLVALUE 
     132                if value > val: 
     133                    self.res *= 1e+6 
     134                    is_outofbound = True 
     135                    break 
     136 
     137        return is_outofbound 
    18138 
    19139class ScipyFit(FitEngine): 
     
    50170        """ 
    51171        FitEngine.__init__(self) 
    52         self.fit_arrange_dict = {} 
    53         self.param_list = [] 
    54172        self.curr_thread = None 
    55173    #def fit(self, *args, **kw): 
     
    68186            msg = "Scipy can't fit more than a single fit problem at a time." 
    69187            raise RuntimeError, msg 
    70             return 
    71         elif len(fitproblem) == 0 :  
     188        elif len(fitproblem) == 0 : 
    72189            raise RuntimeError, "No Assembly scheduled for Scipy fitting." 
    73             return 
    74190        model = fitproblem[0].get_model() 
    75191        if reset_flag: 
     
    87203         
    88204        # Check the initial value if it is within range 
    89         self._check_param_range(model) 
     205        _check_param_range(model.model, self.param_list) 
    90206         
    91         result = FResult(model=model, data=data, param_list=self.param_list) 
    92         result.pars = fitproblem[0].pars 
     207        result = FResult(model=model.model, data=data, param_list=self.param_list) 
    93208        result.fitter_id = self.fitter_id 
    94209        if handler is not None: 
    95210            handler.set_result(result=result) 
     211        functor = SansAssembly(paramlist=self.param_list, 
     212                               model=model, 
     213                               data=data, 
     214                               handler=handler, 
     215                               fitresult=result, 
     216                               curr_thread=curr_thread, 
     217                               msg_q=msg_q) 
    96218        try: 
    97219            # This import must be here; otherwise it will be confused when more 
     
    99221            from scipy import optimize 
    100222             
    101             functor = SansAssembly(paramlist=self.param_list,  
    102                                    model=model,  
    103                                    data=data, 
    104                                     handler=handler, 
    105                                     fitresult=result, 
    106                                      curr_thread=curr_thread, 
    107                                      msg_q=msg_q) 
    108223            out, cov_x, _, mesg, success = optimize.leastsq(functor, 
    109224                                            model.get_params(self.param_list), 
    110                                                     ftol=ftol, 
    111                                                     full_output=1) 
     225                                            ftol=ftol, 
     226                                            full_output=1) 
    112227        except: 
    113228            if hasattr(sys, 'last_type') and sys.last_type == KeyboardInterrupt: 
     
    142257 
    143258         
    144     def _check_param_range(self, model): 
    145         """ 
    146         Check parameter range and set the initial value inside  
    147         if it is out of range. 
    148          
    149         : model: park model object 
    150         """ 
    151         is_outofbound = False 
    152         # loop through parameterset 
    153         for p in model.parameterset:         
    154             param_name = p.get_name() 
    155             # proceed only if the parameter name is in the list of fitting 
    156             if param_name in self.param_list: 
    157                 # if the range was defined, check the range 
    158                 if numpy.isfinite(p.range[0]): 
    159                     if p.value <= p.range[0]:  
    160                         # 10 % backing up from the border if not zero 
    161                         # for Scipy engine to work properly. 
    162                         shift = self._get_zero_shift(p.range[0]) 
    163                         new_value = p.range[0] + shift 
    164                         p.value =  new_value 
    165                         is_outofbound = True 
    166                 if numpy.isfinite(p.range[1]): 
    167                     if p.value >= p.range[1]: 
    168                         shift = self._get_zero_shift(p.range[1]) 
    169                         # 10 % backing up from the border if not zero 
    170                         # for Scipy engine to work properly. 
    171                         new_value = p.range[1] - shift 
    172                         # Check one more time if the new value goes below 
    173                         # the low bound, If so, re-evaluate the value  
    174                         # with the mean of the range. 
    175                         if numpy.isfinite(p.range[0]): 
    176                             if new_value < p.range[0]: 
    177                                 new_value = (p.range[0] + p.range[1]) / 2.0 
    178                         # Todo:  
    179                         # Need to think about when both min and max are same. 
    180                         p.value =  new_value 
    181                         is_outofbound = True 
    182                          
    183         return is_outofbound 
    184      
    185     def _get_zero_shift(self, range): 
    186         """ 
    187         Get 10% shift of the param value = 0 based on the range value 
    188          
    189         : param range: min or max value of the bounds 
    190         """ 
    191         if range == 0: 
    192             shift = 0.1 
    193         else: 
    194             shift = 0.1 * range 
    195              
    196         return shift 
    197      
     259def _check_param_range(model, param_list): 
     260    """ 
     261    Check parameter range and set the initial value inside 
     262    if it is out of range. 
     263 
     264    : model: park model object 
     265    """ 
     266    # loop through parameterset 
     267    for p in param_list: 
     268        value = model.getParam(p) 
     269        low,high = model.details.setdefault(p,["",None,None])[1:3] 
     270        # if the range was defined, check the range 
     271        if low is not None and value <= low: 
     272            value = low + _get_zero_shift(low) 
     273        if high is not None and value > high: 
     274            value = high - _get_zero_shift(high) 
     275            # Check one more time if the new value goes below 
     276            # the low bound, If so, re-evaluate the value 
     277            # with the mean of the range. 
     278            if low is not None and value < low: 
     279                value = 0.5 * (low+high) 
     280        model.setParam(p, value) 
     281 
     282def _get_zero_shift(limit): 
     283    """ 
     284    Get 10% shift of the param value = 0 based on the range value 
     285 
     286    : param range: min or max value of the bounds 
     287    """ 
     288    return 0.1 * (limit if limit != 0.0 else 1.0) 
     289 
    198290     
    199291#def profile(fn, *args, **kw): 
  • src/sans/fit/__init__.py

    r5777106 r6fe5100  
     1from .AbstractFitEngine import FitHandler 
  • src/sans/perspectives/fitting/basepage.py

    r116e1a7 r5bf0331  
    835835            infor = "warning" 
    836836        else: 
    837             msg = "Error was occured " 
    838             msg += ": No valid parameter values to paste from the clipboard..." 
     837            msg = "Error occured: " 
     838            msg += "No valid parameter values to paste from the clipboard..." 
    839839            infor = "error" 
    840840            wx.PostEvent(self._manager.parent, 
     
    21832183                else: 
    21842184                    tcrtl.SetBackgroundColour("pink") 
    2185                     msg = "Model Error:wrong value entered: %s" % sys.exc_value 
     2185                    msg = "Model Error: wrong value entered: %s" % sys.exc_value 
    21862186                    wx.PostEvent(self.parent, StatusEvent(status=msg)) 
    21872187                    return 
    21882188            except: 
    21892189                tcrtl.SetBackgroundColour("pink") 
    2190                 msg = "Model Error:wrong value entered: %s" % sys.exc_value 
     2190                msg = "Model Error: wrong value entered: %s" % sys.exc_value 
    21912191                wx.PostEvent(self.parent, StatusEvent(status=msg)) 
    21922192                return 
     
    21992199                        #is_modified = True 
    22002200                else: 
    2201                     msg = "Cannot Plot :No npts in that Qrange!!!  " 
     2201                    msg = "Cannot plot: No points in Q range!!!  " 
    22022202                    wx.PostEvent(self.parent, StatusEvent(status=msg)) 
    22032203        else: 
    22042204            tcrtl.SetBackgroundColour("pink") 
    2205             msg = "Model Error:wrong value entered!!!" 
     2205            msg = "Model Error: wrong value entered!!!" 
    22062206            wx.PostEvent(self.parent, StatusEvent(status=msg)) 
    22072207        self.save_current_state() 
     
    22402240                else: 
    22412241                    tcrtl.SetBackgroundColour("pink") 
    2242                     msg = "Model Error:wrong value entered: %s" % sys.exc_value 
     2242                    msg = "Model Error: wrong value entered: %s" % sys.exc_value 
    22432243                    wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 
    22442244                    return 
    22452245            except: 
    22462246                tcrtl.SetBackgroundColour("pink") 
    2247                 msg = "Model Error:wrong value entered: %s" % sys.exc_value 
     2247                msg = "Model Error: wrong value entered: %s" % sys.exc_value 
    22482248                wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 
    22492249                return 
     
    22562256                        is_modified = True 
    22572257                else: 
    2258                     msg = "Cannot Plot :No npts in that Qrange!!!  " 
     2258                    msg = "Cannot Plot: No points in Q range!!!  " 
    22592259                    wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 
    22602260        else: 
    22612261            tcrtl.SetBackgroundColour("pink") 
    2262             msg = "Model Error:wrong value entered!!!" 
     2262            msg = "Model Error: wrong value entered!!!" 
    22632263            wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 
    22642264        self.save_current_state() 
     
    24312431                self.qmax.SetBackgroundColour("pink") 
    24322432                self.qmax.Refresh() 
    2433                 msg = "Npts of Data Error :" 
    2434                 msg += "No or too little npts of %s." % data.name 
     2433                msg = "Data Error: " 
     2434                msg += "Too few points in %s." % data.name 
    24352435                wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 
    24362436                self.fitrange = False 
     
    24662466                self.qmax.SetBackgroundColour("pink") 
    24672467                self.qmax.Refresh() 
    2468                 msg = "Npts of Data Error :" 
    2469                 msg += "No or too little npts of %s." % data.name 
     2468                msg = "Data Error: " 
     2469                msg += "Too few points in %s." % data.name 
    24702470                wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 
    24712471                self.fitrange = False 
     
    25182518                                            
    25192519                        except: 
    2520                             msg = "Wrong Fit parameter range entered " 
     2520                            msg = "Wrong fit parameter range entered" 
    25212521                            wx.PostEvent(self._manager.parent, 
    25222522                                         StatusEvent(status=msg)) 
  • src/sans/perspectives/fitting/console.py

    r5777106 r644ca73  
    55import time 
    66import wx 
    7 import park 
    8 from park.fitresult import FitHandler 
     7from sans.fit import FitHandler 
    98 
    109class ConsoleUpdate(FitHandler): 
     
    8887        Print result object 
    8988        """ 
    90         msg = " \n %s \n" % self.result.__str__() 
     89        msg = " \n %s \n" % str(self.result) 
    9190        wx.PostEvent(self.parent, StatusEvent(status=msg)) 
    9291                      
     
    137136        self.fit_duration += self.elapsed_time 
    138137        str_time = time.strftime("%a, %d %b %Y %H:%M:%S ", time.localtime(t1)) 
    139         UPDATE_INTERVAL = 0.5 
     138        UPDATE_INTERVAL = 5.0 
    140139        u_flag = False 
    141140        if self.fit_duration >= UPDATE_INTERVAL: 
  • src/sans/perspectives/fitting/fit_thread.py

    ra855fec re3efa6b3  
    1818     
    1919    def __init__(self,  
    20                   fn, 
    21                   page_id, 
    22                    handler, 
    23                     batch_outputs, 
    24                     batch_inputs=None,              
    25                   pars=None, 
     20                 fn, 
     21                 page_id, 
     22                 handler, 
     23                 batch_outputs, 
     24                 batch_inputs=None, 
     25                 pars=None, 
    2626                 completefn = None, 
    2727                 updatefn   = None, 
     
    3030                 ftol       = None, 
    3131                 reset_flag = False): 
    32         CalcThread.__init__(self,completefn, 
     32        CalcThread.__init__(self, 
     33                 completefn, 
    3334                 updatefn, 
    3435                 yieldtime, 
     
    8081                list_map_get_attr.append(map_getattr) 
    8182            #from multiprocessing import Pool 
    82             inputs = zip(list_map_get_attr,self.fitter, list_fit_function, 
    83                           list_q, list_q, list_handler,list_curr_thread,list_ftol, 
     83            inputs = zip(list_map_get_attr, self.fitter, list_fit_function, 
     84                         list_q, list_q, list_handler,list_curr_thread,list_ftol, 
    8485                         list_reset_flag) 
    8586            result =  map(map_apply, inputs) 
     
    8788            self.complete(result=result, 
    8889                          batch_inputs=self.batch_inputs, 
    89                            batch_outputs=self.batch_outputs, 
     90                          batch_outputs=self.batch_outputs, 
    9091                          page_id=self.page_id, 
    9192                          pars = self.pars, 
  • src/sans/perspectives/fitting/fitpage.py

    rd44648e r4e9f227  
    661661                          wx.EXPAND | wx.ADJUST_MINSIZE, 0) 
    662662         
    663         if self.engine_type == "park": 
     663        if self.engine_type in ("park","bumps"): 
    664664            self.text_disp_max.Show(True) 
    665665            self.text_disp_min.Show(True) 
     
    738738                                          wx.EXPAND | wx.ADJUST_MINSIZE, 0) 
    739739 
    740                         if self.engine_type == "park": 
     740                        if self.engine_type in ("park","bumps"): 
    741741                            ctl3.Show(True) 
    742742                            ctl4.Show(True) 
     
    10051005            return 
    10061006 
    1007         if len(self._manager.fit_thread_list) > 0 and\ 
    1008                     self._manager._fit_engine != "park" and\ 
    1009                     self._manager.sim_page != None and \ 
    1010                     self._manager.sim_page.uid == self.uid: 
     1007        if (len(self._manager.fit_thread_list) > 0 
     1008                and self._manager._fit_engine not in ("park","bumps") 
     1009                and self._manager.sim_page != None 
     1010                and self._manager.sim_page.uid == self.uid): 
    10111011            msg = "The FitEnging will be set to 'ParkMC'\n" 
    10121012            msg += " to fit with more than one data set..." 
     
    21082108        if chisqr != None and numpy.isfinite(chisqr): 
    21092109            #format chi2 
    2110             if self.engine_type == "park": 
     2110            if self.engine_type in ("park","bumps"): 
    21112111                npt_fit = float(self.get_npts2fit()) 
    21122112            chi2 = format_number(chisqr, True) 
  • src/sans/perspectives/fitting/fitproblem.py

    r5777106 r5bf0331  
    454454        return self.itervalues() 
    455455     
    456     def  set_result(self, result, fid): 
     456    def set_result(self, result, fid): 
    457457        """ 
    458458        """ 
  • src/sans/perspectives/fitting/fitting.py

    r767514a r4e9f227  
    3636from .fitproblem import FitProblemDictionary 
    3737from .fitpanel import FitPanel 
     38from .resultpanel import ResultPanel, PlotResultEvent 
     39 
    3840from .fit_thread import FitThread 
    3941from .pagestate import Reader 
     
    111113        self.scipy_id = wx.NewId() 
    112114        self.park_id = wx.NewId() 
     115        self.bumps_id = wx.NewId() 
    113116        self.menu1 = None 
    114117        self.new_model_frame = None 
     
    198201        wx.EVT_MENU(owner, self.park_id, self._onset_engine_park) 
    199202         
     203        bumps_help = "Bumps: fitting and uncertainty analysis. More in Help window...." 
     204        self.menu1.AppendCheckItem(self.bumps_id, "Bumps fit", 
     205                                   bumps_help) 
     206        wx.EVT_MENU(owner, self.bumps_id, self._onset_engine_bumps) 
     207         
    200208        self.menu1.FindItemById(self.scipy_id).Check(True) 
    201209        self.menu1.FindItemById(self.park_id).Check(False) 
     210        self.menu1.FindItemById(self.bumps_id).Check(False) 
    202211        self.menu1.AppendSeparator() 
    203212        self.id_tol = wx.NewId() 
     
    207216                                   ftol_help) 
    208217        wx.EVT_MENU(owner, self.id_tol, self.show_ftol_dialog) 
     218 
     219        self.id_bumps_options = wx.NewId() 
     220        bopts_help = "Bumps fitting options" 
     221        self.menu1.Append(self.id_bumps_options, 'Bumps &Options', bopts_help) 
     222        wx.EVT_MENU(owner, self.id_bumps_options, self.on_bumps_options) 
     223        self.bumps_options_menu = self.menu1.FindItemById(self.id_bumps_options) 
     224        self.bumps_options_menu.Enable(True) 
     225 
     226        self.id_result_panel = wx.NewId() 
     227        self.menu1.Append(self.id_result_panel, "Fit Results", "Show fit results panel") 
     228        wx.EVT_MENU(owner, self.id_result_panel, lambda ev: self.result_frame.Show()) 
    209229        self.menu1.AppendSeparator() 
    210230         
     
    511531        self.perspective = [] 
    512532        self.perspective.append(self.fit_panel.window_name) 
     533 
     534        self.result_frame = MDIFrame(self.parent, None, ResultPanel.window_caption, (220, 200)) 
     535        self.result_panel = ResultPanel(parent=self.result_frame, manager=self) 
     536        self.perspective.append(self.result_panel.window_name) 
    513537        
    514538        #index number to create random model name 
     
    525549        #Send the fitting panel to guiframe 
    526550        self.mypanels.append(self.fit_panel) 
     551        self.mypanels.append(self.result_panel) 
    527552        return self.mypanels 
    528553     
     
    818843                         StatusEvent(status=msg, info='warning')) 
    819844        dialog.Destroy() 
     845 
     846    def on_bumps_options(self, event=None): 
     847        from bumps.gui.fit_dialog import OpenFitOptions 
     848        OpenFitOptions() 
    820849 
    821850    def stop_fit(self, uid): 
     
    959988        self._gui_engine = self._return_engine_type() 
    960989        self.fitproblem_count = fitproblem_count 
    961         if self._fit_engine == "park": 
     990        if self._fit_engine in ("park","bumps"): 
    962991            engineType = "Simultaneous Fit" 
    963992        else: 
     
    970999            #simulatanous fit only one engine need to be created 
    9711000            ## if simultaneous fit change automatically the engine to park 
    972             self._on_change_engine(engine='park') 
     1001            if self._fit_engine not in ("park","bumps"): 
     1002                self._on_change_engine(engine='park') 
    9731003            sim_fitter = Fit(self._fit_engine) 
    9741004            sim_fitter.fitter_id = self.sim_page.uid 
     
    9781008             
    9791009        self.fitproblem_count = fitproblem_count 
    980         if self._fit_engine == "park": 
     1010        if self._fit_engine in ("park","bumps"): 
    9811011            engineType = "Simultaneous Fit" 
    9821012        else: 
     
    15711601        wx.PostEvent(self.parent, StatusEvent(status=msg, info="info", 
    15721602                                                      type="stop")) 
     1603        wx.PostEvent(self.result_panel, PlotResultEvent(result=result)) 
    15731604        # reset fit_engine if changed by simul_fit 
    15741605        if self._fit_engine != self._gui_engine: 
     
    16821713        self._on_change_engine('scipy') 
    16831714        
     1715    def _onset_engine_bumps(self, event): 
     1716        """  
     1717        set engine to bumps 
     1718        """ 
     1719        self._on_change_engine('bumps') 
     1720        
    16841721    def _on_slicer_event(self, event): 
    16851722        """ 
     
    17331770            self.menu1.FindItemById(self.park_id).Check(True) 
    17341771            self.menu1.FindItemById(self.scipy_id).Check(False) 
     1772            self.menu1.FindItemById(self.bumps_id).Check(False) 
     1773        elif engine == "scipy": 
     1774            self.menu1.FindItemById(self.park_id).Check(False) 
     1775            self.menu1.FindItemById(self.scipy_id).Check(True) 
     1776            self.menu1.FindItemById(self.bumps_id).Check(False) 
    17351777        else: 
    17361778            self.menu1.FindItemById(self.park_id).Check(False) 
    1737             self.menu1.FindItemById(self.scipy_id).Check(True) 
     1779            self.menu1.FindItemById(self.scipy_id).Check(False) 
     1780            self.menu1.FindItemById(self.bumps_id).Check(True) 
    17381781        ## post a message to status bar 
    17391782        msg = "Engine set to: %s" % self._fit_engine 
  • src/sans/perspectives/fitting/simfitpage.py

    r5777106 r4e9f227  
    152152        ## making sure all parameters content a constraint 
    153153        ## validity of the constraint expression is own by fit engine 
    154         if self.parent._manager._fit_engine != "park" and flag: 
     154        if self.parent._manager._fit_engine not in ("park","bumps") and flag: 
    155155            msg = "The FitEnging will be set to 'Park' fit engine\n" 
    156156            msg += " for the simultaneous fit..." 
     
    378378        box_description = wx.StaticBox(self, -1,"Easy Setup ") 
    379379        boxsizer = wx.StaticBoxSizer(box_description, wx.HORIZONTAL)      
    380         sizer_constraint = wx.BoxSizer(wx.HORIZONTAL|wx.LEFT|wx.RIGHT|wx.EXPAND) 
     380        sizer_constraint = wx.BoxSizer(wx.HORIZONTAL) 
    381381        self.model_cbox_left = wx.ComboBox(self, -1, style=wx.CB_READONLY) 
    382382        self.model_cbox_left.Clear() 
Note: See TracChangeset for help on using the changeset viewer.