Changeset d3b0c77 in sasview for src/sas/sasgui/perspectives/calculator
- Timestamp:
- Sep 23, 2017 4:24:27 PM (7 years ago)
- 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. - Location:
- src/sas/sasgui/perspectives/calculator
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/sasgui/perspectives/calculator/__init__.py
r959eb01 r5a405bd 18 18 path = os.path.dirname(__file__) 19 19 #Look for maximum n_dir up of the current dir to find media 20 20 21 21 #for i in range(n_dir): 22 22 i = 0 … … 30 30 return media_path 31 31 i += 1 32 32 33 33 raise RuntimeError('Could not find calculator media files') 34 34 … … 36 36 """ 37 37 Return the data files associated with media calculator. 38 38 39 39 The format is a list of (directory, [files...]) pairs which can be 40 40 used directly in setup(...,data_files=...) for setup.py. … … 42 42 """ 43 43 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")))) 47 45 return data_files -
src/sas/sasgui/perspectives/calculator/model_editor.py
r23359ccb r69363c7 31 31 import re 32 32 import logging 33 import datetime 34 33 35 from wx.py.editwindow import EditWindow 36 34 37 from sas.sasgui.guiframe.documentation_window import DocumentationWindow 38 35 39 from .pyconsole import show_model_output, check_model 36 40 37 41 logger = logging.getLogger(__name__) 38 39 42 40 43 if sys.platform.count("win32") > 0: … … 78 81 a Modal Dialog. 79 82 80 :TODO the buil din compiler currently balks at when it tries to import83 :TODO the built in compiler currently balks at when it tries to import 81 84 a model whose name contains spaces or symbols (such as + ... underscore 82 85 should be fine). Have fixed so the editor cannot save such a file name … … 335 338 list_fnames = os.listdir(self.plugin_dir) 336 339 # 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] 338 341 list_fnames.append(m_list) 339 342 if t_fname in list_fnames and title != mname: … … 533 536 desc_line = "\nmodel_info.description = '{}'".format(description) 534 537 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, 536 539 model2=model2_name, operator=self._operator, desc_line=desc_line) 537 540 with open(self.fname, 'w') as out_f: … … 789 792 exec "float(math.%s)" % item 790 793 self.math_combo.Append(str(item)) 791 except :794 except Exception: 792 795 self.math_combo.Append(str(item) + "()") 793 796 self.math_combo.Bind(wx.EVT_COMBOBOX, self._on_math_select) … … 914 917 msg = "Name exists already." 915 918 916 # Prepare the messagebox919 # 917 920 if self.base is not None and not msg: 918 921 self.base.update_custom_combo() 919 # Passed exception in import test as it will fail for sasmodels.sasview_model class920 # Should add similar test for new style?921 Model = None922 try:923 exec "from %s import Model" % name924 except:925 logger.error(sys.exc_value)926 922 927 923 # Prepare the messagebox … … 956 952 :param func_str: content of func; Strings 957 953 """ 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 982 964 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') 1027 988 for func_line in func_str.split('\n'): 1028 989 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 1032 999 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') 1040 1006 1041 1007 out_f.close() 1042 1008 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)] 1065 1023 1066 1024 def set_function_helper(self, line): … … 1096 1054 running "file:///...." 1097 1055 1098 :param evt: Triggers on clicking the help button1099 """1056 :param evt: Triggers on clicking the help button 1057 """ 1100 1058 1101 1059 _TreeLocation = "user/sasgui/perspectives/fitting/fitting_help.html" … … 1140 1098 ## Templates for plugin models 1141 1099 1142 CUSTOM_TEMPLATE = """ 1100 CUSTOM_TEMPLATE = '''\ 1101 r""" 1102 Definition 1103 ---------- 1104 1105 Calculates %(name)s. 1106 1107 %(description)s 1108 1109 References 1110 ---------- 1111 1112 Authorship 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 1143 1120 from 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 """ 1121 from numpy import inf 1122 1123 name = "%(name)s" 1124 title = "%(title)s" 1125 description = """%(description)s""" 1126 1127 ''' 1128 1129 CUSTOM_TEMPLATE_PD = '''\ 1130 def 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 1137 def 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 1145 def 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 1212 1154 SUM_TEMPLATE = """ 1213 1155 from sasmodels.core import load_model_info … … 1219 1161 """ 1220 1162 if __name__ == "__main__": 1221 # app = wx.PySimpleApp()1222 1163 main_app = wx.App() 1223 1164 main_frame = TextDialog(id=1, model_list=["SphereModel", "CylinderModel"], 1224 plugin_dir='../fitting/plugin_models')1165 plugin_dir='../fitting/plugin_models') 1225 1166 main_frame.ShowModal() 1226 1167 main_app.MainLoop() 1227 1228 #if __name__ == "__main__":1229 # from sas.sasgui.perspectives.fitting import models1230 # 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.