Changeset ccf58fb in sasview for src/sas/sasgui


Ignore:
Timestamp:
Sep 11, 2017 6:08:09 AM (7 years ago)
Author:
lewis
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, magnetic_scatt, release-4.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
0794ce3
Parents:
a309667 (diff), f9ba422 (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 branch 'master' into corfunc3d

Location:
src/sas/sasgui
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • src/sas/sasgui/guiframe/local_perspectives/data_loader/data_loader.py

    r235f514 rdcb91cf  
    1111 
    1212from sas.sascalc.dataloader.loader import Loader 
     13from sas.sascalc.dataloader.loader_exceptions import NoKnownLoaderException 
    1314from sas.sasgui.guiframe.plugin_base import PluginBase 
    1415from sas.sasgui.guiframe.events import StatusEvent 
     
    4142APPLICATION_WLIST = config.APPLICATION_WLIST 
    4243 
     44 
    4345class Plugin(PluginBase): 
    4446 
     
    5658        """ 
    5759        # menu for data files 
    58         menu_list = [] 
    5960        data_file_hint = "load one or more data in the application" 
    6061        menu_list = [('&Load Data File(s)', data_file_hint, self.load_data)] 
    6162        gui_style = self.parent.get_style() 
    6263        style = gui_style & GUIFRAME.MULTIPLE_APPLICATIONS 
    63         style1 = gui_style & GUIFRAME.DATALOADER_ON 
    6464        if style == GUIFRAME.MULTIPLE_APPLICATIONS: 
    6565            # menu for data from folder 
     
    102102        self.get_data(file_list) 
    103103 
    104  
    105104    def can_load_data(self): 
    106105        """ 
     
    108107        """ 
    109108        return True 
    110  
    111109 
    112110    def _load_folder(self, event): 
     
    140138        """ 
    141139        if error is not None or str(error).strip() != "": 
    142             dial = wx.MessageDialog(self.parent, str(error), 'Error Loading File', 
     140            dial = wx.MessageDialog(self.parent, str(error), 
     141                                    'Error Loading File', 
    143142                                    wx.OK | wx.ICON_EXCLAMATION) 
    144143            dial.ShowModal() 
     
    149148        """ 
    150149        if os.path.isdir(path): 
    151             return [os.path.join(os.path.abspath(path), filename) for filename in os.listdir(path)] 
     150            return [os.path.join(os.path.abspath(path), filename) for filename 
     151                    in os.listdir(path)] 
    152152 
    153153    def _process_data_and_errors(self, item, p_file, output, message): 
     
    178178        for p_file in path: 
    179179            basename = os.path.basename(p_file) 
     180            # Skip files that start with a period 
     181            if basename.startswith("."): 
     182                msg = "The folder included a potential hidden file - %s." \ 
     183                      % basename 
     184                msg += " Do you wish to load this file as data?" 
     185                msg_box = wx.MessageDialog(None, msg, 'Warning', 
     186                                           wx.OK | wx.CANCEL) 
     187                if msg_box.ShowModal() == wx.ID_CANCEL: 
     188                    continue 
    180189            _, extension = os.path.splitext(basename) 
    181190            if extension.lower() in EXTENSIONS: 
     
    213222                info="info") 
    214223 
    215             except: 
    216                 logger.error(sys.exc_value) 
    217  
    218                 error_message = "The Data file you selected could not be loaded.\n" 
    219                 error_message += "Make sure the content of your file" 
    220                 error_message += " is properly formatted.\n" 
    221                 error_message += "When contacting the SasView team, mention the" 
    222                 error_message += " following:\n" 
    223                 error_message += "Error: " + str(sys.exc_info()[1]) 
    224                 file_errors[basename] = [error_message] 
    225                 self.load_update(output=output, message=error_message, info="warning") 
     224            except NoKnownLoaderException as e: 
     225                exception_occurred = True 
     226                logger.error(e.message) 
     227 
     228                error_message = "Loading data failed!\n" + e.message 
     229                self.load_update(output=None, message=e.message, info="warning") 
     230 
     231            except Exception as e: 
     232                exception_occurred = True 
     233                logger.error(e.message) 
     234 
     235                file_err = "The Data file you selected could not be " 
     236                file_err += "loaded.\nMake sure the content of your file" 
     237                file_err += " is properly formatted.\n" 
     238                file_err += "When contacting the SasView team, mention the" 
     239                file_err += " following:\n" 
     240                file_err += e.message 
     241                file_errors[basename] = [file_err] 
    226242 
    227243        if len(file_errors) > 0: 
     
    233249                    error_message += message + "\n" 
    234250                error_message += "\n" 
    235             self.load_update(output=output, message=error_message, info="error") 
    236  
    237         self.load_complete(output=output, message="Loading data complete!", 
    238             info="info") 
     251            if not exception_occurred: # Some data loaded but with errors 
     252                self.load_update(output=output, message=error_message, info="error") 
     253 
     254        if not exception_occurred: # Everything loaded as expected 
     255            self.load_complete(output=output, message="Loading data complete!", 
     256                               info="info") 
     257        else: 
     258            self.load_complete(output=None, message=error_message, info="error") 
     259 
    239260 
    240261    def load_update(self, output=None, message="", info="warning"): 
     
    245266            wx.PostEvent(self.parent, StatusEvent(status=message, info=info, 
    246267                                                  type="progress")) 
    247     def load_complete(self, output, message="", error_message="", path=None, 
    248                       info="warning"): 
    249         """ 
    250          post message to  status bar and return list of data 
    251         """ 
    252         wx.PostEvent(self.parent, StatusEvent(status=message, 
    253                                               info=info, 
     268 
     269    def load_complete(self, output, message="", info="warning"): 
     270        """ 
     271         post message to status bar and return list of data 
     272        """ 
     273        wx.PostEvent(self.parent, StatusEvent(status=message, info=info, 
    254274                                              type="stop")) 
    255         # if error_message != "": 
    256         #    self.load_error(error_message) 
    257         self.parent.add_data(data_list=output) 
     275        if output is not None: 
     276            self.parent.add_data(data_list=output) 
  • src/sas/sasgui/perspectives/calculator/model_editor.py

    ra1b8fee r07ec714  
    643643        self.name_hsizer = None 
    644644        self.name_tcl = None 
     645        self.overwrite_cb = None 
    645646        self.desc_sizer = None 
    646647        self.desc_tcl = None 
     
    657658        self.warning = "" 
    658659        #This does not seem to be used anywhere so commenting out for now 
    659         #    -- PDB 2/26/17  
     660        #    -- PDB 2/26/17 
    660661        #self._description = "New Plugin Model" 
    661662        self.function_tcl = None 
     
    689690        #title name [string] 
    690691        name_txt = wx.StaticText(self, -1, 'Function Name : ') 
    691         overwrite_cb = wx.CheckBox(self, -1, "Overwrite existing plugin model of this name?", (10, 10)) 
    692         overwrite_cb.SetValue(False) 
    693         overwrite_cb.SetToolTipString("Overwrite it if already exists?") 
    694         wx.EVT_CHECKBOX(self, overwrite_cb.GetId(), self.on_over_cb) 
     692        self.overwrite_cb = wx.CheckBox(self, -1, "Overwrite existing plugin model of this name?", (10, 10)) 
     693        self.overwrite_cb.SetValue(False) 
     694        self.overwrite_cb.SetToolTipString("Overwrite it if already exists?") 
     695        wx.EVT_CHECKBOX(self, self.overwrite_cb.GetId(), self.on_over_cb) 
    695696        self.name_tcl = wx.TextCtrl(self, -1, size=(PANEL_WIDTH * 3 / 5, -1)) 
    696697        self.name_tcl.Bind(wx.EVT_TEXT_ENTER, self.on_change_name) 
     
    700701        self.name_tcl.SetToolTipString(hint_name) 
    701702        self.name_hsizer.AddMany([(self.name_tcl, 0, wx.LEFT | wx.TOP, 0), 
    702                                   (overwrite_cb, 0, wx.LEFT, 20)]) 
     703                                  (self.overwrite_cb, 0, wx.LEFT, 20)]) 
    703704        self.name_sizer.AddMany([(name_txt, 0, wx.LEFT | wx.TOP, 10), 
    704705                                 (self.name_hsizer, 0, 
     
    740741        self.param_sizer.AddMany([(param_txt, 0, wx.LEFT, 10), 
    741742                                  (self.param_tcl, 1, wx.EXPAND | wx.ALL, 10)]) 
    742          
     743 
    743744        # Parameters with polydispersity 
    744745        pd_param_txt = wx.StaticText(self, -1, 'Fit Parameters requiring ' + \ 
     
    755756        self.pd_param_tcl.setDisplayLineNumbers(True) 
    756757        self.pd_param_tcl.SetToolTipString(pd_param_tip) 
    757          
     758 
    758759        self.param_sizer.AddMany([(pd_param_txt, 0, wx.LEFT, 10), 
    759760                                  (self.pd_param_tcl, 1, wx.EXPAND | wx.ALL, 10)]) 
     
    995996            info = 'Error' 
    996997            color = 'red' 
     998            self.overwrite_cb.SetValue(True) 
     999            self.overwrite_name = True 
    9971000        else: 
    9981001            self._notes = result 
     
    10301033        if has_scipy: 
    10311034            lines.insert(0, 'import scipy') 
    1032          
    1033         # Think about 2D later         
     1035 
     1036        # Think about 2D later 
    10341037        #self.is_2d = func_str.count("#self.ndim = 2") 
    10351038        #line_2d = '' 
    10361039        #if self.is_2d: 
    10371040        #    line_2d = CUSTOM_2D_TEMP.split('\n') 
    1038          
    1039         # Also think about test later         
     1041 
     1042        # Also think about test later 
    10401043        #line_test = TEST_TEMPLATE.split('\n') 
    10411044        #local_params = '' 
     
    10431046        spaces4  = ' '*4 
    10441047        spaces13 = ' '*13 
    1045         spaces16 = ' '*16      
     1048        spaces16 = ' '*16 
    10461049        param_names = []    # to store parameter names 
    10471050        has_scipy = func_str.count("scipy.") 
     
    10551058            out_f.write(line + '\n') 
    10561059            if line.count('#name'): 
    1057                 out_f.write('name = "%s" \n' % name)                
     1060                out_f.write('name = "%s" \n' % name) 
    10581061            elif line.count('#title'): 
    1059                 out_f.write('title = "User model for %s"\n' % name)                
     1062                out_f.write('title = "User model for %s"\n' % name) 
    10601063            elif line.count('#description'): 
    1061                 out_f.write('description = "%s"\n' % desc_str)                
     1064                out_f.write('description = "%s"\n' % desc_str) 
    10621065            elif line.count('#parameters'): 
    10631066                out_f.write('parameters = [ \n') 
     
    10651068                    p_line = param_line.lstrip().rstrip() 
    10661069                    if p_line: 
    1067                         pname, pvalue = self.get_param_helper(p_line) 
     1070                        pname, pvalue, desc = self.get_param_helper(p_line) 
    10681071                        param_names.append(pname) 
    1069                         out_f.write("%s['%s', '', %s, [-numpy.inf, numpy.inf], '', ''],\n" % (spaces16, pname, pvalue)) 
     1072                        out_f.write("%s['%s', '', %s, [-numpy.inf, numpy.inf], '', '%s'],\n" % (spaces16, pname, pvalue, desc)) 
    10701073                for param_line in pd_param_str.split('\n'): 
    10711074                    p_line = param_line.lstrip().rstrip() 
    10721075                    if p_line: 
    1073                         pname, pvalue = self.get_param_helper(p_line) 
     1076                        pname, pvalue, desc = self.get_param_helper(p_line) 
    10741077                        param_names.append(pname) 
    1075                         out_f.write("%s['%s', '', %s, [-numpy.inf, numpy.inf], 'volume', ''],\n" % (spaces16, pname, pvalue)) 
     1078                        out_f.write("%s['%s', '', %s, [-numpy.inf, numpy.inf], 'volume', '%s'],\n" % (spaces16, pname, pvalue, desc)) 
    10761079                out_f.write('%s]\n' % spaces13) 
    1077              
     1080 
    10781081        # No form_volume or ER available in simple model editor 
    10791082        out_f.write('def form_volume(*arg): \n') 
     
    10821085        out_f.write('def ER(*arg): \n') 
    10831086        out_f.write('    return 1.0 \n') 
    1084          
     1087 
    10851088        # function to compute 
    10861089        out_f.write('\n') 
     
    10911094        for func_line in func_str.split('\n'): 
    10921095            out_f.write('%s%s\n' % (spaces4, func_line)) 
    1093          
     1096 
    10941097        Iqxy_string = 'return Iq(numpy.sqrt(x**2+y**2) ' 
    1095              
     1098 
    10961099        out_f.write('\n') 
    10971100        out_f.write('def Iqxy(x, y ') 
     
    11131116        items = line.split(";") 
    11141117        for item in items: 
    1115             name = item.split("=")[0].lstrip().rstrip() 
     1118            name = item.split("=")[0].strip() 
     1119            description = "" 
    11161120            try: 
    1117                 value = item.split("=")[1].lstrip().rstrip() 
     1121                value = item.split("=")[1].strip() 
     1122                if value.count("#"): 
     1123                    # If line ends in a comment, remove it before parsing float 
     1124                    index = value.index("#") 
     1125                    description = value[(index + 1):].strip() 
     1126                    value = value[:value.index("#")].strip() 
    11181127                float(value) 
    1119             except: 
     1128            except ValueError: 
    11201129                value = 1.0 # default 
    11211130 
    1122         return name, value 
     1131        return name, value, description 
    11231132 
    11241133    def set_function_helper(self, line): 
     
    12041213import numpy 
    12051214 
    1206 #name  
     1215#name 
    12071216 
    12081217#title 
     
    12101219#description 
    12111220 
    1212 #parameters  
     1221#parameters 
    12131222 
    12141223""" 
  • src/sas/sasgui/perspectives/calculator/pyconsole.py

    r7432acb r4627657  
    3737    Iqxy = model.evalDistribution([qx, qy]) 
    3838 
    39     result = """ 
    40     Iq(%s) = %s 
    41     Iqxy(%s, %s) = %s 
    42     """%(q, Iq, qx, qy, Iqxy) 
     39    # check the model's unit tests run 
     40    from sasmodels.model_test import run_one 
     41    result = run_one(path) 
    4342 
    4443    return result 
     
    8988        ok = wx.Button(self, wx.ID_OK, "OK") 
    9089 
    91         # Mysterious constraint layouts from  
     90        # Mysterious constraint layouts from 
    9291        # https://www.wxpython.org/docs/api/wx.lib.layoutf.Layoutf-class.html 
    9392        lc = layoutf.Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self,ok)) 
  • src/sas/sasgui/perspectives/file_converter/converter_panel.py

    red9f872 r19296dc  
    2424from sas.sascalc.file_converter.otoko_loader import OTOKOLoader 
    2525from sas.sascalc.file_converter.bsl_loader import BSLLoader 
     26from sas.sascalc.file_converter.ascii2d_loader import ASCII2DLoader 
    2627from sas.sascalc.file_converter.nxcansas_writer import NXcanSASWriter 
    2728from sas.sascalc.dataloader.data_info import Detector 
     
    3536    _STATICBOX_WIDTH = 410 
    3637    _BOX_WIDTH = 200 
    37     PANEL_SIZE = 480 
     38    PANEL_SIZE = 520 
    3839    FONT_VARIANT = 0 
    3940else: 
     
    4142    _STATICBOX_WIDTH = 430 
    4243    _BOX_WIDTH = 200 
    43     PANEL_SIZE = 500 
     44    PANEL_SIZE = 540 
    4445    FONT_VARIANT = 1 
    4546 
     
    352353            w.write(frame_data, output_path) 
    353354 
     355    def convert_2d_data(self, dataset): 
     356        metadata = self.get_metadata() 
     357        for key, value in metadata.iteritems(): 
     358            setattr(dataset[0], key, value) 
     359 
     360        w = NXcanSASWriter() 
     361        w.write(dataset, self.output.GetPath()) 
     362 
    354363    def on_convert(self, event): 
    355364        """Called when the Convert button is clicked""" 
     
    367376                qdata, iqdata = self.extract_otoko_data(self.q_input.GetPath()) 
    368377                self.convert_1d_data(qdata, iqdata) 
     378            elif self.data_type == 'ascii2d': 
     379                loader = ASCII2DLoader(self.iq_input.GetPath()) 
     380                data = loader.load() 
     381                dataset = [data] # ASCII 2D only ever contains 1 frame 
     382                self.convert_2d_data(dataset) 
    369383            else: # self.data_type == 'bsl' 
    370384                dataset = self.extract_bsl_data(self.iq_input.GetPath()) 
     
    372386                    # Cancelled by user 
    373387                    return 
    374  
    375                 metadata = self.get_metadata() 
    376                 for key, value in metadata.iteritems(): 
    377                     setattr(dataset[0], key, value) 
    378  
    379                 w = NXcanSASWriter() 
    380                 w.write(dataset, self.output.GetPath()) 
     388                self.convert_2d_data(dataset) 
     389 
    381390        except Exception as ex: 
    382391            msg = str(ex) 
     
    399408    def validate_inputs(self): 
    400409        msg = "You must select a" 
    401         if self.q_input.GetPath() == '' and self.data_type != 'bsl': 
     410        if self.q_input.GetPath() == '' and self.data_type != 'bsl' \ 
     411            and self.data_type != 'ascii2d': 
    402412            msg += " Q Axis input file." 
    403413        elif self.iq_input.GetPath() == '': 
     
    472482        dtype = event.GetEventObject().GetName() 
    473483        self.data_type = dtype 
    474         if dtype == 'bsl': 
     484        if dtype == 'bsl' or dtype == 'ascii2d': 
    475485            self.q_input.SetPath("") 
    476486            self.q_input.Disable() 
     
    500510 
    501511        instructions = ( 
    502         "Select linked single column 1D ASCII files containing the Q-axis and " 
    503         "Intensity-axis data, or 1D BSL/OTOKO files, or a 2D BSL/OTOKO file, " 
    504         "then choose where to save the converted file, and click Convert.\n" 
    505         "1D ASCII and BSL/OTOKO files can be converted to CanSAS (XML) or " 
    506         "NXcanSAS (HDF5) formats. 2D BSL/OTOKO files can only be converted to " 
    507         "the NXcanSAS format.\n" 
    508         "Metadata can be optionally added for the CanSAS XML format." 
     512        "If converting a 1D dataset, select linked single-column ASCII files " 
     513        "containing the Q-axis and intensity-axis data, or a 1D BSL/OTOKO file." 
     514        " If converting 2D data, select an ASCII file in the ISIS 2D file " 
     515        "format, or a 2D BSL/OTOKO file. Choose where to save the converted " 
     516        "file and click convert.\n" 
     517        "One dimensional ASCII and BSL/OTOKO files can be converted to CanSAS " 
     518        "(XML) or NXcanSAS (HDF5) formats. Two dimensional datasets can only be" 
     519        " converted to the NXcanSAS format.\n" 
     520        "Metadata can also be optionally added to the output file." 
    509521        ) 
    510522 
     
    526538            wx.ALIGN_CENTER_VERTICAL, 5) 
    527539        radio_sizer = wx.BoxSizer(wx.HORIZONTAL) 
    528         ascii_btn = wx.RadioButton(self, -1, "ASCII", name="ascii", 
     540        ascii_btn = wx.RadioButton(self, -1, "ASCII 1D", name="ascii", 
    529541            style=wx.RB_GROUP) 
    530542        ascii_btn.Bind(wx.EVT_RADIOBUTTON, self.datatype_changed) 
    531543        radio_sizer.Add(ascii_btn) 
     544        ascii2d_btn = wx.RadioButton(self, -1, "ASCII 2D", name="ascii2d") 
     545        ascii2d_btn.Bind(wx.EVT_RADIOBUTTON, self.datatype_changed) 
     546        radio_sizer.Add(ascii2d_btn) 
    532547        otoko_btn = wx.RadioButton(self, -1, "BSL 1D", name="otoko") 
    533548        otoko_btn.Bind(wx.EVT_RADIOBUTTON, self.datatype_changed) 
    534549        radio_sizer.Add(otoko_btn) 
    535         input_grid.Add(radio_sizer, (y,1), (1,1), wx.ALL, 5) 
    536550        bsl_btn = wx.RadioButton(self, -1, "BSL 2D", name="bsl") 
    537551        bsl_btn.Bind(wx.EVT_RADIOBUTTON, self.datatype_changed) 
    538552        radio_sizer.Add(bsl_btn) 
     553        input_grid.Add(radio_sizer, (y,1), (1,1), wx.ALL, 5) 
    539554        y += 1 
    540555 
     
    549564        y += 1 
    550565 
    551         iq_label = wx.StaticText(self, -1, "Intensity-Axis Data: ") 
     566        iq_label = wx.StaticText(self, -1, "Intensity Data: ") 
    552567        input_grid.Add(iq_label, (y,0), (1,1), wx.ALIGN_CENTER_VERTICAL, 5) 
    553568 
     
    647662 
    648663    def __init__(self, parent=None, title='File Converter', base=None, 
    649         manager=None, size=(PANEL_SIZE * 1.05, PANEL_SIZE / 1.1), 
     664        manager=None, size=(PANEL_SIZE * 0.96, PANEL_SIZE * 0.9), 
    650665        *args, **kwargs): 
    651666        kwargs['title'] = title 
  • src/sas/sasgui/perspectives/file_converter/file_converter.py

    r463e7ffc r94e3572  
    2525        Returns a set of menu entries 
    2626        """ 
    27         help_txt = "Convert single column ASCII data to CanSAS format" 
     27        help_txt = "Convert ASCII or BSL/OTOKO data to CanSAS or NXcanSAS formats" 
    2828        return [("File Converter", help_txt, self.on_file_converter)] 
    2929 
  • src/sas/sasgui/perspectives/file_converter/media/file_converter_help.rst

    rd73998c r59decb81  
    1818*   Single-column ASCII data, with lines that end without any delimiter, 
    1919    or with a comma or semi-colon delimiter 
     20*   2D `ISIS ASCII formatted 
     21    <http://www.isis.stfc.ac.uk/instruments/loq/software/ 
     22    colette-ascii-file-format-descriptions9808.pdf>`_ data 
    2023*   `1D BSL/OTOKO format 
    2124    <http://www.diamond.ac.uk/Beamlines/Soft-Condensed-Matter/small-angle/ 
     
    3639 
    37401) Select the files containing your Q-axis and Intensity-axis data 
    38 2) Choose whether the files are in ASCII, 1D BSL/OTOKO or 2D BSL/OTOKO format 
     412) Choose whether the files are in ASCII 1D, ASCII 2D, 1D BSL/OTOKO or 2D BSL/OTOKO format 
    39423) Choose where you would like to save the converted file 
    40434) Optionally, input some metadata such as sample size, detector name, etc 
     
    4750file, a dialog will appear asking which frames you would like converted. You 
    4851may enter a start frame, end frame & increment, and all frames in that subset 
    49 will be converted. For example, entering 0, 50 and 10 will convert frames 0,  
     52will be converted. For example, entering 0, 50 and 10 will convert frames 0, 
    505310, 20, 30, 40 & 50. 
    5154 
     
    5659single file, so there is an option in the *Select Frame* dialog to output each 
    5760frame to its own file. The single file option will produce one file with 
    58 multiple `<SASdata>` elements. The multiple file option will output a separate  
    59 file with one `<SASdata>` element for each frame. The frame number will also be  
     61multiple `<SASdata>` elements. The multiple file option will output a separate 
     62file with one `<SASdata>` element for each frame. The frame number will also be 
    6063appended to the file name. 
    6164 
    62 The multiple file option is not available when exporting to NXcanSAS because  
     65The multiple file option is not available when exporting to NXcanSAS because 
    6366the HDF5 format is more efficient at handling large amounts of data. 
    6467 
  • src/sas/sasgui/perspectives/fitting/fitting.py

    ra534432 r489f53a  
    257257        toks = os.path.splitext(label) 
    258258        path = os.path.join(models.find_plugins_dir(), toks[0]) 
     259        message = "Are you sure you want to delete the file {}?".format(path) 
     260        dlg = wx.MessageDialog(self.frame, message, '', wx.YES_NO | wx.ICON_QUESTION) 
     261        if not dlg.ShowModal() == wx.ID_YES: 
     262            return 
    259263        try: 
    260264            for ext in ['.py', '.pyc']: 
    261265                p_path = path + ext 
     266                if ext == '.pyc' and not os.path.isfile(path + ext): 
     267                    # If model is invalid, .pyc file may not exist as model has 
     268                    # never been compiled. Don't try and delete it 
     269                    continue 
    262270                os.remove(p_path) 
    263271            self.update_custom_combo() 
     
    361369                                   'Add a new model function') 
    362370        wx.EVT_MENU(owner, wx_id, self.make_new_model) 
    363          
     371 
    364372        wx_id = wx.NewId() 
    365373        self.edit_model_menu.Append(wx_id, 'Sum|Multi(p1, p2)', 
     
    383391          '(Re)Load all models present in user plugin_models folder') 
    384392        wx.EVT_MENU(owner, wx_id, self.load_plugin_models) 
    385                  
     393 
    386394    def set_edit_menu_helper(self, owner=None, menu=None): 
    387395        """ 
     
    17341742            @param unsmeared_error: data error, rescaled to unsmeared model 
    17351743        """ 
    1736              
    1737         number_finite = np.count_nonzero(np.isfinite(y))  
     1744 
     1745        number_finite = np.count_nonzero(np.isfinite(y)) 
    17381746        np.nan_to_num(y) 
    17391747        new_plot = self.create_theory_1D(x, y, page_id, model, data, state, 
     
    17941802            msg = "Computing Error: Model did not return any finite value." 
    17951803            wx.PostEvent(self.parent, StatusEvent(status = msg, info="error")) 
    1796         else:                  
     1804        else: 
    17971805            msg = "Computation  completed!" 
    17981806            if number_finite != y.size: 
     
    18241832        that can be plot. 
    18251833        """ 
    1826         number_finite = np.count_nonzero(np.isfinite(image))  
     1834        number_finite = np.count_nonzero(np.isfinite(image)) 
    18271835        np.nan_to_num(image) 
    18281836        new_plot = Data2D(image=image, err_image=data.err_data) 
     
    19271935                ## and may be the cause of other noted instabilities 
    19281936                ## 
    1929                 ##    -PDB August 12, 2014  
     1937                ##    -PDB August 12, 2014 
    19301938                while self.calc_2D.isrunning(): 
    19311939                    time.sleep(0.1) 
     
    19691977            if (self.calc_1D is not None) and self.calc_1D.isrunning(): 
    19701978                self.calc_1D.stop() 
    1971                 ## stop just raises the flag -- the thread is supposed to  
     1979                ## stop just raises the flag -- the thread is supposed to 
    19721980                ## then kill itself but cannot.  Paul Kienzle came up with 
    19731981                ## this fix to prevent threads from stepping on each other 
     
    19811989                ## a request to stop the computation. 
    19821990                ## It seems thus that the whole thread approach used here 
    1983                 ## May need rethinking   
     1991                ## May need rethinking 
    19841992                ## 
    19851993                ##    -PDB August 12, 2014 
     
    21462154            residuals.dxw = None 
    21472155            residuals.ytransform = 'y' 
    2148             # For latter scale changes  
     2156            # For latter scale changes 
    21492157            residuals.xaxis('\\rm{Q} ', 'A^{-1}') 
    21502158            residuals.yaxis('\\rm{Residuals} ', 'normalized') 
  • src/sas/sasgui/perspectives/fitting/models.py

    r8cec26b rb1c2011  
    186186            try: 
    187187                model = load_custom_model(path) 
    188                 model.name = PLUGIN_NAME_BASE + model.name 
     188                if not model.name.count(PLUGIN_NAME_BASE): 
     189                    model.name = PLUGIN_NAME_BASE + model.name 
    189190                plugins[model.name] = model 
    190191            except Exception: 
     
    297298        for name, plug in self.stored_plugins.iteritems(): 
    298299            self.model_dictionary[name] = plug 
    299          
     300 
    300301        self._get_multifunc_models() 
    301302 
  • src/sas/sasgui/perspectives/pr/inversion_panel.py

    r7432acb rcb62bd5  
    7070        self.rg_ctl = None 
    7171        self.iq0_ctl = None 
    72         self.bck_chk = None 
     72        self.bck_value = None 
     73        self.bck_est_ctl = None 
     74        self.bck_man_ctl = None 
     75        self.est_bck = True 
     76        self.bck_input = None 
    7377        self.bck_ctl = None 
    7478 
     
    312316        # Read the panel's parameters 
    313317        flag, alpha, dmax, nfunc, qmin, \ 
    314         qmax, height, width = self._read_pars() 
     318        qmax, height, width, bck = self._read_pars() 
    315319 
    316320        state.nfunc = nfunc 
     
    326330 
    327331        # Background evaluation checkbox 
    328         state.estimate_bck = self.bck_chk.IsChecked() 
     332        state.estimate_bck = self.est_bck 
     333        state.bck_value = bck 
    329334 
    330335        # Estimates 
     
    371376        self.plot_data.SetValue(str(state.file)) 
    372377 
    373         # Background evaluation checkbox 
    374         self.bck_chk.SetValue(state.estimate_bck) 
     378        # Background value 
     379        self.bck_est_ctl.SetValue(state.estimate_bck) 
     380        self.bck_man_ctl.SetValue(not state.estimate_bck) 
     381        if not state.estimate_bck: 
     382            self.bck_input.Enable() 
     383            self.bck_input.SetValue(str(state.bck_value)) 
     384        self.est_bck = state.estimate_bck 
     385        self.bck_value = state.bck_value 
    375386 
    376387        # Estimates 
     
    431442                       wx.EXPAND | wx.LEFT | wx.RIGHT | wx.ADJUST_MINSIZE, 15) 
    432443 
    433         self.bck_chk = wx.CheckBox(self, -1, "Estimate background level") 
    434         hint_msg = "Check box to let the fit estimate " 
    435         hint_msg += "the constant background level." 
    436         self.bck_chk.SetToolTipString(hint_msg) 
    437         self.bck_chk.Bind(wx.EVT_CHECKBOX, self._on_pars_changed) 
     444        radio_sizer = wx.GridBagSizer(5, 5) 
     445 
     446        self.bck_est_ctl = wx.RadioButton(self, -1, "Estimate background level", 
     447            name="estimate_bck", style=wx.RB_GROUP) 
     448        self.bck_man_ctl = wx.RadioButton(self, -1, "Input manual background level", 
     449            name="manual_bck") 
     450 
     451        self.bck_est_ctl.Bind(wx.EVT_RADIOBUTTON, self._on_bck_changed) 
     452        self.bck_man_ctl.Bind(wx.EVT_RADIOBUTTON, self._on_bck_changed) 
     453 
     454        radio_sizer.Add(self.bck_est_ctl, (0,0), (1,1), wx.LEFT | wx.EXPAND) 
     455        radio_sizer.Add(self.bck_man_ctl, (0,1), (1,1), wx.RIGHT | wx.EXPAND) 
     456 
    438457        iy += 1 
    439         pars_sizer.Add(self.bck_chk, (iy, 0), (1, 2), 
     458        pars_sizer.Add(radio_sizer, (iy, 0), (1, 2), 
    440459                       wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 
     460 
     461        background_label = wx.StaticText(self, -1, "Background: ") 
     462        self.bck_input = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER, 
     463            size=(60, 20), value="0.0") 
     464        self.bck_input.Disable() 
     465        self.bck_input.Bind(wx.EVT_TEXT, self._read_pars) 
     466        background_units = wx.StaticText(self, -1, "[A^(-1)]", size=(55, 20)) 
     467        iy += 1 
     468 
     469        background_sizer = wx.GridBagSizer(5, 5) 
     470 
     471        background_sizer.Add(background_label, (0, 0), (1,1), 
     472            wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 23) 
     473        background_sizer.Add(self.bck_input, (0, 1), (1,1), 
     474            wx.LEFT | wx.ADJUST_MINSIZE, 5) 
     475        background_sizer.Add(background_units, (0, 2), (1,1), 
     476            wx.LEFT | wx.ADJUST_MINSIZE, 5) 
     477        pars_sizer.Add(background_sizer, (iy, 0), (1, 2), 
     478            wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 
     479 
    441480        boxsizer1.Add(pars_sizer, 0, wx.EXPAND) 
    442481        vbox.Add(boxsizer1, (iy_vb, 0), (1, 1), 
     
    764803        self._on_pars_changed() 
    765804 
     805    def _on_bck_changed(self, evt=None): 
     806        self.est_bck = self.bck_est_ctl.GetValue() 
     807        if self.est_bck: 
     808            self.bck_input.Disable() 
     809        else: 
     810            self.bck_input.Enable() 
     811 
    766812    def _on_pars_changed(self, evt=None): 
    767813        """ 
     
    770816        scenes. 
    771817        """ 
    772         flag, alpha, dmax, nfunc, qmin, qmax, height, width = self._read_pars() 
    773         has_bck = self.bck_chk.IsChecked() 
     818        flag, alpha, dmax, nfunc, qmin, qmax, height, width, bck = self._read_pars() 
    774819 
    775820        # If the pars are valid, estimate alpha 
     
    783828                                                      d_max=dmax, 
    784829                                                      q_min=qmin, q_max=qmax, 
    785                                                       bck=has_bck, 
     830                                                      est_bck=self.est_bck, 
     831                                                      bck_val=bck, 
    786832                                                      height=height, 
    787833                                                      width=width) 
     
    797843        height = 0 
    798844        width = 0 
     845        background = 0 
    799846        flag = True 
    800847        # Read slit height 
     
    890937            self.qmax_ctl.Refresh() 
    891938 
    892         return flag, alpha, dmax, nfunc, qmin, qmax, height, width 
     939        # Read background 
     940        if not self.est_bck: 
     941            try: 
     942                bck_str = self.bck_input.GetValue() 
     943                if len(bck_str.strip()) == 0: 
     944                    background = 0.0 
     945                else: 
     946                    background = float(bck_str) 
     947                    self.bck_input.SetBackgroundColour(wx.WHITE) 
     948            except ValueError: 
     949                background = 0.0 
     950                self.bck_input.SetBackgroundColour("pink") 
     951            self.bck_input.Refresh() 
     952 
     953        return flag, alpha, dmax, nfunc, qmin, qmax, height, width, background 
    893954 
    894955    def _on_explore(self, evt): 
     
    915976        # Push it to the manager 
    916977 
    917         flag, alpha, dmax, nfunc, qmin, qmax, height, width = self._read_pars() 
    918         has_bck = self.bck_chk.IsChecked() 
     978        flag, alpha, dmax, nfunc, qmin, qmax, height, width, bck = self._read_pars() 
    919979 
    920980        if flag: 
     
    928988                                                   d_max=dmax, 
    929989                                                   q_min=qmin, q_max=qmax, 
    930                                                    bck=has_bck, 
     990                                                   est_bck=self.est_bck, 
     991                                                   bck_val = bck, 
    931992                                                   height=height, 
    932993                                                   width=width) 
  • src/sas/sasgui/perspectives/pr/inversion_state.py

    r7432acb ra0e6b1b  
    3636           ["qmin", "qmin"], 
    3737           ["qmax", "qmax"], 
    38            ["estimate_bck", "estimate_bck"]] 
     38           ["estimate_bck", "estimate_bck"], 
     39           ["bck_value", "bck_value"]] 
    3940 
    4041## List of P(r) inversion outputs 
     
    6263        self.estimate_bck = False 
    6364        self.timestamp = time.time() 
     65        self.bck_value = 0.0 
    6466 
    6567        # Inversion parameters 
     
    109111        state += "Timestamp:    %s\n" % self.timestamp 
    110112        state += "Estimate bck: %s\n" % str(self.estimate_bck) 
     113        state += "Bck Value:    %s\n" % str(self.bck_value) 
    111114        state += "No. terms:    %s\n" % str(self.nfunc) 
    112115        state += "D_max:        %s\n" % str(self.d_max) 
     
    296299                            self.coefficients.append(float(c)) 
    297300                        except: 
    298                             # Bad data, skip. We will count the number of  
    299                             # coefficients at the very end and deal with  
     301                            # Bad data, skip. We will count the number of 
     302                            # coefficients at the very end and deal with 
    300303                            # inconsistencies then. 
    301304                            pass 
     
    329332                                cov_row.append(float(c)) 
    330333                            except: 
    331                                 # Bad data, skip. We will count the number of  
    332                                 # coefficients at the very end and deal with  
     334                                # Bad data, skip. We will count the number of 
     335                                # coefficients at the very end and deal with 
    333336                                # inconsistencies then. 
    334337                                pass 
     
    461464                tree = etree.parse(path, parser=etree.ETCompatXMLParser()) 
    462465                # Check the format version number 
    463                 # Specifying the namespace will take care of the file  
    464                 #format version  
     466                # Specifying the namespace will take care of the file 
     467                #format version 
    465468                root = tree.getroot() 
    466469 
  • src/sas/sasgui/perspectives/pr/media/pr_help.rst

    r1221196 r1abd19c  
    4949P(r) inversion requires that the background be perfectly subtracted.  This is 
    5050often difficult to do well and thus many data sets will include a background. 
    51 For those cases, the user should check the "estimate background" box and the 
    52 module will do its best to estimate it. 
     51For those cases, the user should check the "Estimate background level" option 
     52and the module will do its best to estimate it. If you know the background value 
     53for your data, select the "Input manual background level" option. Note that 
     54this value will be treated as having 0 error. 
    5355 
    5456The P(r) module is constantly computing in the background what the optimum 
  • src/sas/sasgui/perspectives/pr/pr.py

    ra1b8fee rcb62bd5  
    6868        self.q_min = None 
    6969        self.q_max = None 
    70         self.has_bck = False 
     70        self.est_bck = False 
     71        self.bck_val = 0 
    7172        self.slit_height = 0 
    7273        self.slit_width = 0 
     
    828829        self.control_panel.iq0 = pr.iq0(out) 
    829830        self.control_panel.bck = pr.background 
     831        self.control_panel.bck_input.SetValue("{:.2g}".format(pr.background)) 
    830832 
    831833        # Show I(q) fit 
     
    907909 
    908910    def setup_plot_inversion(self, alpha, nfunc, d_max, q_min=None, q_max=None, 
    909                              bck=False, height=0, width=0): 
     911                             est_bck=False, bck_val=0, height=0, width=0): 
    910912        """ 
    911913            Set up inversion from plotted data 
     
    916918        self.q_min = q_min 
    917919        self.q_max = q_max 
    918         self.has_bck = bck 
     920        self.est_bck = est_bck 
     921        self.bck_val = bck_val 
    919922        self.slit_height = height 
    920923        self.slit_width = width 
     
    930933    def estimate_plot_inversion(self, alpha, nfunc, d_max, 
    931934                                q_min=None, q_max=None, 
    932                                 bck=False, height=0, width=0): 
     935                                est_bck=False, bck_val=0, height=0, width=0): 
    933936        """ 
    934937            Estimate parameters from plotted data 
     
    939942        self.q_min = q_min 
    940943        self.q_max = q_max 
    941         self.has_bck = bck 
     944        self.est_bck = est_bck 
     945        self.bck_val = bck_val 
    942946        self.slit_height = height 
    943947        self.slit_width = width 
     
    973977        pr.x = self.current_plottable.x 
    974978        pr.y = self.current_plottable.y 
    975         pr.has_bck = self.has_bck 
     979        pr.est_bck = self.est_bck 
    976980        pr.slit_height = self.slit_height 
    977981        pr.slit_width = self.slit_width 
     982        pr.background = self.bck_val 
    978983 
    979984        # Keep track of the plot window title to ensure that 
     
    10191024        self.q_min = q_min 
    10201025        self.q_max = q_max 
    1021         self.has_bck = bck 
     1026        self.est_bck = bck 
    10221027        self.slit_height = height 
    10231028        self.slit_width = width 
     
    10421047        self.q_min = q_min 
    10431048        self.q_max = q_max 
    1044         self.has_bck = bck 
     1049        self.est_bck = bck 
    10451050        self.slit_height = height 
    10461051        self.slit_width = width 
     
    11151120            pr.y = y 
    11161121            pr.err = err 
    1117             pr.has_bck = self.has_bck 
     1122            pr.est_bck = self.est_bck 
    11181123            pr.slit_height = self.slit_height 
    11191124            pr.slit_width = self.slit_width 
  • src/sas/sasgui/perspectives/corfunc/corfunc.py

    r463e7ffc r9b90bf8  
    189189            # Show the transformation as a curve instead of points 
    190190            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM 
     191        elif label == IDF_LABEL: 
     192            new_plot.xaxis("{x}", 'A') 
     193            new_plot.yaxis("{g_1}", '') 
     194            # Linear scale 
     195            new_plot.xtransform = 'x' 
     196            new_plot.ytransform = 'y' 
     197            group_id = GROUP_ID_IDF 
     198            # Show IDF as a curve instead of points 
     199            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM 
    191200        new_plot.id = label 
    192201        new_plot.name = label 
  • src/sas/sasgui/perspectives/corfunc/corfunc_panel.py

    r7432acb r9b90bf8  
    5555        self._data = data # The data to be analysed (corrected fr background) 
    5656        self._extrapolated_data = None # The extrapolated data set 
     57        # Callable object of class CorfuncCalculator._Interpolator representing 
     58        # the extrapolated and interpolated data 
     59        self._extrapolated_fn = None 
    5760        self._transformed_data = None # Fourier trans. of the extrapolated data 
    5861        self._calculator = CorfuncCalculator() 
     
    218221 
    219222        try: 
    220             params, self._extrapolated_data = self._calculator.compute_extrapolation() 
     223            params, self._extrapolated_data, self._extrapolated_fn = \ 
     224                self._calculator.compute_extrapolation() 
    221225        except Exception as e: 
    222226            msg = "Error extrapolating data:\n" 
     
    257261            StatusEvent(status=msg)) 
    258262 
    259     def transform_complete(self, transform=None): 
     263    def transform_complete(self, transforms=None): 
    260264        """ 
    261265        Called from FourierThread when calculation has completed 
    262266        """ 
    263267        self._transform_btn.SetLabel("Transform") 
    264         if transform is None: 
     268        if transforms is None: 
    265269            msg = "Error calculating Transform." 
    266270            if self.transform_type == 'hilbert': 
     
    270274            self._extract_btn.Disable() 
    271275            return 
    272         self._transformed_data = transform 
    273         import numpy as np 
    274         plot_x = transform.x[np.where(transform.x <= 200)] 
    275         plot_y = transform.y[np.where(transform.x <= 200)] 
     276 
     277        self._transformed_data = transforms 
     278        (transform1, transform3, idf) = transforms 
     279        plot_x = transform1.x[transform1.x <= 200] 
     280        plot_y = transform1.y[transform1.x <= 200] 
    276281        self._manager.show_data(Data1D(plot_x, plot_y), TRANSFORM_LABEL1) 
     282        # No need to shorten gamma3 as it's only calculated up to x=200 
     283        self._manager.show_data(transform3, TRANSFORM_LABEL3) 
     284 
     285        plot_x = idf.x[idf.x <= 200] 
     286        plot_y = idf.y[idf.x <= 200] 
     287        self._manager.show_data(Data1D(plot_x, plot_y), IDF_LABEL) 
     288 
    277289        # Only enable extract params button if a fourier trans. has been done 
    278290        if self.transform_type == 'fourier': 
     
    286298        """ 
    287299        try: 
    288             params = self._calculator.extract_parameters(self._transformed_data) 
     300            params = self._calculator.extract_parameters(self._transformed_data[0]) 
    289301        except: 
    290302            params = None 
  • src/sas/sasgui/perspectives/corfunc/corfunc_state.py

    r7432acb r457f735  
    5959        self.q = None 
    6060        self.iq = None 
    61         # TODO: Add extrapolated data and transformed data (when implemented) 
    6261 
    6362    def __str__(self): 
  • src/sas/sasgui/perspectives/corfunc/media/corfunc_help.rst

    r1404cce rd78b5cb  
    1010 
    1111This performs a correlation function analysis of one-dimensional 
    12 SAXS/SANS data, or generates a model-independent volume fraction  
     12SAXS/SANS data, or generates a model-independent volume fraction 
    1313profile from the SANS from an adsorbed polymer/surfactant layer. 
    1414 
    15 A correlation function may be interpreted in terms of an imaginary rod moving  
    16 through the structure of the material. Γ\ :sub:`1D`\ (R) is the probability that  
    17 a rod of length R moving through the material has equal electron/neutron scattering  
    18 length density at either end. Hence a frequently occurring spacing within a structure  
     15A correlation function may be interpreted in terms of an imaginary rod moving 
     16through the structure of the material. Γ\ :sub:`1D`\ (R) is the probability that 
     17a rod of length R moving through the material has equal electron/neutron scattering 
     18length density at either end. Hence a frequently occurring spacing within a structure 
    1919manifests itself as a peak. 
    2020 
     
    3030*  Fourier / Hilbert Transform of the smoothed data to give the correlation 
    3131   function / volume fraction profile, respectively 
    32 *  (Optional) Interpretation of the 1D correlation function based on an ideal  
     32*  (Optional) Interpretation of the 1D correlation function based on an ideal 
    3333   lamellar morphology 
    3434 
     
    7474   :align: center 
    7575 
    76     
     76 
    7777Smoothing 
    7878--------- 
    7979 
    80 The extrapolated data set consists of the Guinier back-extrapolation from Q~0  
     80The extrapolated data set consists of the Guinier back-extrapolation from Q~0 
    8181up to the lowest Q value in the original data, then the original scattering data, and the Porod tail-fit beyond this. The joins between the original data and the Guinier/Porod fits are smoothed using the algorithm below to avoid the formation of ripples in the transformed data. 
    8282 
     
    9393    h_i = \frac{1}{1 + \frac{(x_i-b)^2}{(x_i-a)^2}} 
    9494 
    95          
     95 
    9696Transform 
    9797--------- 
     
    102102If "Fourier" is selected for the transform type, the analysis will perform a 
    103103discrete cosine transform on the extrapolated data in order to calculate the 
    104 correlation function 
     1041D correlation function: 
    105105 
    106106.. math:: 
     
    115115    \left(n + \frac{1}{2} \right) k \right] } \text{ for } k = 0, 1, \ldots, 
    116116    N-1, N 
     117 
     118The 3D correlation function is also calculated: 
     119 
     120.. math:: 
     121    \Gamma _{3D}(R) = \frac{1}{Q^{*}} \int_{0}^{\infty}I(q) q^{2} 
     122    \frac{sin(qR)}{qR} dq 
    117123 
    118124Hilbert 
     
    165171.. figure:: profile1.png 
    166172   :align: center 
    167   
     173 
    168174.. figure:: profile2.png 
    169175   :align: center 
    170     
     176 
    171177 
    172178References 
     
    191197----- 
    192198Upon sending data for correlation function analysis, it will be plotted (minus 
    193 the background value), along with a *red* bar indicating the *upper end of the  
     199the background value), along with a *red* bar indicating the *upper end of the 
    194200low-Q range* (used for back-extrapolation), and 2 *purple* bars indicating the range to be used for forward-extrapolation. These bars may be moved my clicking and 
    195201dragging, or by entering appropriate values in the Q range input boxes. 
     
    221227    :align: center 
    222228 
    223          
     229 
    224230.. note:: 
    225231    This help document was last changed by Steve King, 08Oct2016 
  • src/sas/sasgui/perspectives/corfunc/plot_labels.py

    r1dc8ec9 r7dda833  
    44 
    55GROUP_ID_TRANSFORM = r"$\Gamma(x)$" 
    6 TRANSFORM_LABEL1 = r"$\Gamma1(x)$" 
    7 TRANSFORM_LABEL3 = r"$\Gamma3(x)$" 
     6TRANSFORM_LABEL1 = r"$\Gamma_1(x)$" 
     7TRANSFORM_LABEL3 = r"$\Gamma_3(x)$" 
     8 
     9GROUP_ID_IDF = r"$g_1(x)$" 
     10IDF_LABEL = r"$g_1(x)$" 
Note: See TracChangeset for help on using the changeset viewer.