Ignore:
Timestamp:
Sep 23, 2017 4:24:27 PM (7 years ago)
Author:
Paul Kienzle <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, magnetic_scatt, release-4.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
b963b20, fca1f50
Parents:
9706d88 (diff), dba8557 (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 'ticket-887-reorg' into ticket-853-fit-gui-to-calc

Location:
src/sas/sasgui/perspectives/calculator
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/sas/sasgui/perspectives/calculator/__init__.py

    r959eb01 r5a405bd  
    1818    path = os.path.dirname(__file__) 
    1919    #Look for maximum n_dir up of the current dir to find media 
    20     
     20 
    2121    #for i in range(n_dir): 
    2222    i = 0 
     
    3030             return media_path 
    3131        i += 1 
    32     
     32 
    3333    raise RuntimeError('Could not find calculator media files') 
    3434 
     
    3636    """ 
    3737    Return the data files associated with media calculator. 
    38      
     38 
    3939    The format is a list of (directory, [files...]) pairs which can be 
    4040    used directly in setup(...,data_files=...) for setup.py. 
     
    4242    """ 
    4343    data_files = [] 
    44     path = get_data_path(media="media") 
    45     for f in findall(path): 
    46         data_files.append(('media/calculator_media', [f])) 
     44    data_files.append(('media/calculator_media', findall(get_data_path("media")))) 
    4745    return data_files 
  • src/sas/sasgui/perspectives/calculator/model_editor.py

    r23359ccb r69363c7  
    3131import re 
    3232import logging 
     33import datetime 
     34 
    3335from wx.py.editwindow import EditWindow 
     36 
    3437from sas.sasgui.guiframe.documentation_window import DocumentationWindow 
     38 
    3539from .pyconsole import show_model_output, check_model 
    3640 
    3741logger = logging.getLogger(__name__) 
    38  
    3942 
    4043if sys.platform.count("win32") > 0: 
     
    7881    a Modal Dialog. 
    7982 
    80     :TODO the build in compiler currently balks at when it tries to import 
     83    :TODO the built in compiler currently balks at when it tries to import 
    8184    a model whose name contains spaces or symbols (such as + ... underscore 
    8285    should be fine).  Have fixed so the editor cannot save such a file name 
     
    335338            list_fnames = os.listdir(self.plugin_dir) 
    336339            # fake existing regular model name list 
    337             m_list = [model + ".py" for model in self.model_list] 
     340            m_list = [model.name + ".py" for model in self.model_list] 
    338341            list_fnames.append(m_list) 
    339342            if t_fname in list_fnames and title != mname: 
     
    533536            desc_line = "\nmodel_info.description = '{}'".format(description) 
    534537        name = os.path.splitext(os.path.basename(self.fname))[0] 
    535         output = SUM_TEMPLATE.format(name=name, model1=model1_name,  
     538        output = SUM_TEMPLATE.format(name=name, model1=model1_name, 
    536539            model2=model2_name, operator=self._operator, desc_line=desc_line) 
    537540        with open(self.fname, 'w') as out_f: 
     
    789792                    exec "float(math.%s)" % item 
    790793                    self.math_combo.Append(str(item)) 
    791                 except: 
     794                except Exception: 
    792795                    self.math_combo.Append(str(item) + "()") 
    793796        self.math_combo.Bind(wx.EVT_COMBOBOX, self._on_math_select) 
     
    914917            msg = "Name exists already." 
    915918 
    916         # Prepare the messagebox 
     919        # 
    917920        if self.base is not None and not msg: 
    918921            self.base.update_custom_combo() 
    919             # Passed exception in import test as it will fail for sasmodels.sasview_model class 
    920             # Should add similar test for new style? 
    921             Model = None 
    922             try: 
    923                 exec "from %s import Model" % name 
    924             except: 
    925                 logger.error(sys.exc_value) 
    926922 
    927923        # Prepare the messagebox 
     
    956952        :param func_str: content of func; Strings 
    957953        """ 
    958         try: 
    959             out_f = open(fname, 'w') 
    960         except: 
    961             raise 
    962         # Prepare the content of the function 
    963         lines = CUSTOM_TEMPLATE.split('\n') 
    964  
    965         has_scipy = func_str.count("scipy.") 
    966         if has_scipy: 
    967             lines.insert(0, 'import scipy') 
    968  
    969         # Think about 2D later 
    970         #self.is_2d = func_str.count("#self.ndim = 2") 
    971         #line_2d = '' 
    972         #if self.is_2d: 
    973         #    line_2d = CUSTOM_2D_TEMP.split('\n') 
    974  
    975         # Also think about test later 
    976         #line_test = TEST_TEMPLATE.split('\n') 
    977         #local_params = '' 
    978         #spaces = '        '#8spaces 
    979         spaces4  = ' '*4 
    980         spaces13 = ' '*13 
    981         spaces16 = ' '*16 
     954        out_f = open(fname, 'w') 
     955 
     956        out_f.write(CUSTOM_TEMPLATE % { 
     957            'name': name, 
     958            'title': 'User model for ' + name, 
     959            'description': desc_str, 
     960            'date': datetime.datetime.now().strftime('%YYYY-%mm-%dd'), 
     961        }) 
     962 
     963        # Write out parameters 
    982964        param_names = []    # to store parameter names 
    983         has_scipy = func_str.count("scipy.") 
    984         if has_scipy: 
    985             lines.insert(0, 'import scipy') 
    986  
    987         # write function here 
    988         for line in lines: 
    989             # The location where to put the strings is 
    990             # hard-coded in the template as shown below. 
    991             out_f.write(line + '\n') 
    992             if line.count('#name'): 
    993                 out_f.write('name = "%s" \n' % name) 
    994             elif line.count('#title'): 
    995                 out_f.write('title = "User model for %s"\n' % name) 
    996             elif line.count('#description'): 
    997                 out_f.write('description = "%s"\n' % desc_str) 
    998             elif line.count('#parameters'): 
    999                 out_f.write('parameters = [ \n') 
    1000                 for param_line in param_str.split('\n'): 
    1001                     p_line = param_line.lstrip().rstrip() 
    1002                     if p_line: 
    1003                         pname, pvalue, desc = self.get_param_helper(p_line) 
    1004                         param_names.append(pname) 
    1005                         out_f.write("%s['%s', '', %s, [-numpy.inf, numpy.inf], '', '%s'],\n" % (spaces16, pname, pvalue, desc)) 
    1006                 for param_line in pd_param_str.split('\n'): 
    1007                     p_line = param_line.lstrip().rstrip() 
    1008                     if p_line: 
    1009                         pname, pvalue, desc = self.get_param_helper(p_line) 
    1010                         param_names.append(pname) 
    1011                         out_f.write("%s['%s', '', %s, [-numpy.inf, numpy.inf], 'volume', '%s'],\n" % (spaces16, pname, pvalue, desc)) 
    1012                 out_f.write('%s]\n' % spaces13) 
    1013  
    1014         # No form_volume or ER available in simple model editor 
    1015         out_f.write('def form_volume(*arg): \n') 
    1016         out_f.write('    return 1.0 \n') 
    1017         out_f.write('\n') 
    1018         out_f.write('def ER(*arg): \n') 
    1019         out_f.write('    return 1.0 \n') 
    1020  
    1021         # function to compute 
    1022         out_f.write('\n') 
    1023         out_f.write('def Iq(x ') 
    1024         for name in param_names: 
    1025             out_f.write(', %s' % name) 
    1026         out_f.write('):\n') 
     965        pd_params = [] 
     966        out_f.write('parameters = [ \n') 
     967        out_f.write('#   ["name", "units", default, [lower, upper], "type", "description"],\n') 
     968        for pname, pvalue, desc in self.get_param_helper(param_str): 
     969            param_names.append(pname) 
     970            out_f.write("    ['%s', '', %s, [-inf, inf], '', '%s'],\n" 
     971                        % (pname, pvalue, desc)) 
     972        for pname, pvalue, desc in self.get_param_helper(pd_param_str): 
     973            param_names.append(pname) 
     974            pd_params.append(pname) 
     975            out_f.write("    ['%s', '', %s, [-inf, inf], 'volume', '%s'],\n" 
     976                        % (pname, pvalue, desc)) 
     977        out_f.write('    ]\n') 
     978 
     979        # Write out function definition 
     980        out_f.write('def Iq(%s):\n' % ', '.join(['x'] + param_names)) 
     981        out_f.write('    """Absolute scattering"""\n') 
     982        if "scipy." in func_str: 
     983            out_f.write('    import scipy') 
     984        if "numpy." in func_str: 
     985            out_f.write('    import numpy') 
     986        if "np." in func_str: 
     987            out_f.write('    import numpy as np') 
    1027988        for func_line in func_str.split('\n'): 
    1028989            out_f.write('%s%s\n' % (spaces4, func_line)) 
    1029  
    1030         Iqxy_string = 'return Iq(numpy.sqrt(x**2+y**2) ' 
    1031  
     990        out_f.write('## uncomment the following if Iq works for vector x\n') 
     991        out_f.write('#Iq.vectorized = True\n') 
     992 
     993        # If polydisperse, create place holders for form_volume, ER and VR 
     994        if pd_params: 
     995            out_f.write('\n') 
     996            out_f.write(CUSTOM_TEMPLATE_PD % {'args': ', '.join(pd_params)}) 
     997 
     998        # Create place holder for Iqxy 
    1032999        out_f.write('\n') 
    1033         out_f.write('def Iqxy(x, y ') 
    1034         for name in param_names: 
    1035             out_f.write(', %s' % name) 
    1036             Iqxy_string += ', ' + name 
    1037         out_f.write('):\n') 
    1038         Iqxy_string += ')' 
    1039         out_f.write('%s%s\n' % (spaces4, Iqxy_string)) 
     1000        out_f.write('#def Iqxy(%s):\n' % ', '.join(["x", "y"] + param_names)) 
     1001        out_f.write('#    """Absolute scattering of oriented particles."""\n') 
     1002        out_f.write('#    ...\n') 
     1003        out_f.write('#    return oriented_form(x, y, args)\n') 
     1004        out_f.write('## uncomment the following if Iqxy works for vector x, y\n') 
     1005        out_f.write('#Iqxy.vectorized = True\n') 
    10401006 
    10411007        out_f.close() 
    10421008 
    1043     def get_param_helper(self, line): 
    1044         """ 
    1045         Get string in line to define the params dictionary 
    1046  
    1047         :param line: one line of string got from the param_str 
    1048         """ 
    1049         items = line.split(";") 
    1050         for item in items: 
    1051             name = item.split("=")[0].strip() 
    1052             description = "" 
    1053             try: 
    1054                 value = item.split("=")[1].strip() 
    1055                 if value.count("#"): 
    1056                     # If line ends in a comment, remove it before parsing float 
    1057                     index = value.index("#") 
    1058                     description = value[(index + 1):].strip() 
    1059                     value = value[:value.index("#")].strip() 
    1060                 float(value) 
    1061             except ValueError: 
    1062                 value = 1.0 # default 
    1063  
    1064         return name, value, description 
     1009    def get_param_helper(self, param_str): 
     1010        """ 
     1011        yield a sequence of name, value pairs for the parameters in param_str 
     1012 
     1013        Parameters can be defined by one per line by name=value, or multiple 
     1014        on the same line by separating the pairs by semicolon or comma.  The 
     1015        value is optional and defaults to "1.0". 
     1016        """ 
     1017        for line in param_str.replace(';', ',').split('\n'): 
     1018            for item in line.split(','): 
     1019                defn, desc = item.split('#', 1) if '#' in item else (item, '') 
     1020                name, value = defn.split('=', 1) if '=' in defn else (defn, '1.0') 
     1021                if name: 
     1022                    yield [v.strip() for v in (name, value, desc)] 
    10651023 
    10661024    def set_function_helper(self, line): 
     
    10961054        running "file:///...." 
    10971055 
    1098     :param evt: Triggers on clicking the help button 
    1099     """ 
     1056        :param evt: Triggers on clicking the help button 
     1057        """ 
    11001058 
    11011059        _TreeLocation = "user/sasgui/perspectives/fitting/fitting_help.html" 
     
    11401098## Templates for plugin models 
    11411099 
    1142 CUSTOM_TEMPLATE = """ 
     1100CUSTOM_TEMPLATE = '''\ 
     1101r""" 
     1102Definition 
     1103---------- 
     1104 
     1105Calculates %(name)s. 
     1106 
     1107%(description)s 
     1108 
     1109References 
     1110---------- 
     1111 
     1112Authorship and Verification 
     1113--------------------------- 
     1114 
     1115* **Author:** --- **Date:** %(date)s 
     1116* **Last Modified by:** --- **Date:** %(date)s 
     1117* **Last Reviewed by:** --- **Date:** %(date)s 
     1118""" 
     1119 
    11431120from math import * 
    1144 import os 
    1145 import sys 
    1146 import numpy 
    1147  
    1148 #name 
    1149  
    1150 #title 
    1151  
    1152 #description 
    1153  
    1154 #parameters 
    1155  
    1156 """ 
    1157  
    1158 CUSTOM_2D_TEMP = """ 
    1159     def run(self, x=0.0, y=0.0): 
    1160         if x.__class__.__name__ == 'list': 
    1161             x_val = x[0] 
    1162             y_val = y[0]*0.0 
    1163             return self.function(x_val, y_val) 
    1164         elif x.__class__.__name__ == 'tuple': 
    1165             msg = "Tuples are not allowed as input to BaseComponent models" 
    1166             raise ValueError, msg 
    1167         else: 
    1168             return self.function(x, 0.0) 
    1169     def runXY(self, x=0.0, y=0.0): 
    1170         if x.__class__.__name__ == 'list': 
    1171             return self.function(x, y) 
    1172         elif x.__class__.__name__ == 'tuple': 
    1173             msg = "Tuples are not allowed as input to BaseComponent models" 
    1174             raise ValueError, msg 
    1175         else: 
    1176             return self.function(x, y) 
    1177     def evalDistribution(self, qdist): 
    1178         if qdist.__class__.__name__ == 'list': 
    1179             msg = "evalDistribution expects a list of 2 ndarrays" 
    1180             if len(qdist)!=2: 
    1181                 raise RuntimeError, msg 
    1182             if qdist[0].__class__.__name__ != 'ndarray': 
    1183                 raise RuntimeError, msg 
    1184             if qdist[1].__class__.__name__ != 'ndarray': 
    1185                 raise RuntimeError, msg 
    1186             v_model = numpy.vectorize(self.runXY, otypes=[float]) 
    1187             iq_array = v_model(qdist[0], qdist[1]) 
    1188             return iq_array 
    1189         elif qdist.__class__.__name__ == 'ndarray': 
    1190             v_model = numpy.vectorize(self.runXY, otypes=[float]) 
    1191             iq_array = v_model(qdist) 
    1192             return iq_array 
    1193 """ 
    1194 TEST_TEMPLATE = """ 
    1195 ###################################################################### 
    1196 ## THIS IS FOR TEST. DO NOT MODIFY THE FOLLOWING LINES!!!!!!!!!!!!!!!! 
    1197 if __name__ == "__main__": 
    1198     m= Model() 
    1199     out1 = m.runXY(0.0) 
    1200     out2 = m.runXY(0.01) 
    1201     isfine1 = numpy.isfinite(out1) 
    1202     isfine2 = numpy.isfinite(out2) 
    1203     print "Testing the value at Q = 0.0:" 
    1204     print out1, " : finite? ", isfine1 
    1205     print "Testing the value at Q = 0.01:" 
    1206     print out2, " : finite? ", isfine2 
    1207     if isfine1 and isfine2: 
    1208         print "===> Simple Test: Passed!" 
    1209     else: 
    1210         print "===> Simple Test: Failed!" 
    1211 """ 
     1121from numpy import inf 
     1122 
     1123name = "%(name)s" 
     1124title = "%(title)s" 
     1125description = """%(description)s""" 
     1126 
     1127''' 
     1128 
     1129CUSTOM_TEMPLATE_PD = '''\ 
     1130def form_volume(%(args)s): 
     1131    """ 
     1132    Volume of the particles used to compute absolute scattering intensity 
     1133    and to weight polydisperse parameter contributions. 
     1134    """ 
     1135    return 0.0 
     1136 
     1137def ER(%(args)s): 
     1138    """ 
     1139    Effective radius of particles to be used when computing structure factors. 
     1140 
     1141    Input parameters are vectors ranging over the mesh of polydispersity values. 
     1142    """ 
     1143    return 0.0 
     1144 
     1145def VR(%(args)s): 
     1146    """ 
     1147    Volume ratio of particles to be used when computing structure factors. 
     1148 
     1149    Input parameters are vectors ranging over the mesh of polydispersity values. 
     1150    """ 
     1151    return 1.0 
     1152''' 
     1153 
    12121154SUM_TEMPLATE = """ 
    12131155from sasmodels.core import load_model_info 
     
    12191161""" 
    12201162if __name__ == "__main__": 
    1221 #    app = wx.PySimpleApp() 
    12221163    main_app = wx.App() 
    12231164    main_frame = TextDialog(id=1, model_list=["SphereModel", "CylinderModel"], 
    1224                        plugin_dir='../fitting/plugin_models') 
     1165                            plugin_dir='../fitting/plugin_models') 
    12251166    main_frame.ShowModal() 
    12261167    main_app.MainLoop() 
    1227  
    1228 #if __name__ == "__main__": 
    1229 #    from sas.sasgui.perspectives.fitting import models 
    1230 #    dir_path = models.find_plugins_dir() 
    1231 #    app = wx.App() 
    1232 #    window = EditorWindow(parent=None, base=None, path=dir_path, title="Editor") 
    1233 #    app.MainLoop() 
Note: See TracChangeset for help on using the changeset viewer.