Changeset d3b0c77 in sasview for src/sas/sasgui/perspectives
- 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
- Files:
-
- 1 deleted
- 14 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/fitting/__init__.py
r959eb01 r12d3e0e 13 13 # Check for data path next to exe/zip file. 14 14 # If we are inside a py2exe zip file, we need to go up 15 # to get to the directory containing 15 # to get to the directory containing 16 16 # the media for this module 17 17 path = os.path.dirname(__file__) … … 26 26 return module_media_path 27 27 return media_path 28 28 29 29 raise RuntimeError('Could not find models media files') 30 30 … … 32 32 """ 33 33 Return the data files associated with media. 34 34 35 35 The format is a list of (directory, [files...]) pairs which can be 36 36 used directly in setup(...,data_files=...) for setup.py. … … 38 38 """ 39 39 data_files = [] 40 path = os.path.dirname(__file__) 41 p_path = os.path.join(path, 'plugin_models') 42 for f in findall(p_path): 43 data_files.append(('plugin_models', [f])) 44 # path = get_data_path(media="media") 45 for f in findall(path): 46 data_files.append(('media/fitting_media', [f])) 47 40 # Note: windows installer requires the plugin_models directory 41 plugin_models = os.path.join(os.path.dirname(__file__), "plugin_models") 42 data_files.append(('plugin_models', findall(plugin_models))) 43 data_files.append(('media/fitting_media', findall(get_data_path("media")))) 44 48 45 return data_files -
src/sas/sasgui/perspectives/fitting/basepage.py
r69363c7 rd3b0c77 12 12 import logging 13 13 import traceback 14 from Queue import Queue 15 from threading import Thread 14 16 from collections import defaultdict 15 17 … … 248 250 self.set_layout() 249 251 252 # Setting up a thread for the fitting 253 self.threaded_draw_queue = Queue() 254 255 self.draw_worker_thread = Thread(target = self._threaded_draw_worker, 256 args = (self.threaded_draw_queue,)) 257 self.draw_worker_thread.setDaemon(True) 258 self.draw_worker_thread.start() 259 260 # And a home for the thread submission times 261 self.last_time_fit_submitted = 0.00 262 250 263 def set_index_model(self, index): 251 264 """ … … 1735 1748 :param chisqr: update chisqr value [bool] 1736 1749 """ 1737 wx.CallAfter(self._draw_model_after, update_chisqr, source) 1750 self.threaded_draw_queue.put([copy.copy(update_chisqr), copy.copy(source)]) 1751 1752 def _threaded_draw_worker(self, threaded_draw_queue): 1753 while True: 1754 # sit and wait for the next task 1755 next_task = threaded_draw_queue.get() 1756 1757 # sleep for 1/10th second in case some other tasks accumulate 1758 time.sleep(0.1) 1759 1760 # skip all intermediate tasks 1761 while self.threaded_draw_queue.qsize() > 0: 1762 self.threaded_draw_queue.task_done() 1763 next_task = self.threaded_draw_queue.get() 1764 1765 # and finally, do the task 1766 self._draw_model_after(*next_task) 1767 threaded_draw_queue.task_done() 1738 1768 1739 1769 def _draw_model_after(self, update_chisqr=True, source='model'): … … 1757 1787 toggle_mode_on = self.model_view.IsEnabled() 1758 1788 is_2d = self._is_2D() 1789 1759 1790 self._manager.draw_model(self.model, 1760 1791 data=self.data, -
src/sas/sasgui/perspectives/invariant/__init__.py
r959eb01 r5a405bd 15 15 # Check for data path next to exe/zip file. 16 16 # If we are inside a py2exe zip file, we need to go up 17 # to get to the directory containing 17 # to get to the directory containing 18 18 # the media for this module 19 19 path = os.path.dirname(__file__) … … 28 28 return module_media_path 29 29 return media_path 30 30 31 31 raise RuntimeError('Could not find invariant media files') 32 32 … … 34 34 """ 35 35 Return the data files associated with media invariant. 36 36 37 37 The format is a list of (directory, [files...]) pairs which can be 38 38 used directly in setup(...,data_files=...) for setup.py. … … 40 40 """ 41 41 data_files = [] 42 path = get_data_path(media="media") 43 for f in findall(path): 44 data_files.append(('media/invariant_media', [f])) 42 data_files.append(('media/invariant_media', findall(get_data_path("media")))) 45 43 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() -
src/sas/sasgui/perspectives/fitting/batchfitpage.py
r7432acb r50fcb09 5 5 import wx.lib.newevent 6 6 import math 7 8 from sas.sascalc.fit.qsmearing import smear_selection 9 7 10 from sas.sasgui.guiframe.events import StatusEvent 8 11 from sas.sasgui.guiframe.events import NewPlotEvent 12 from sas.sasgui.perspectives.fitting.basepage import PageInfoEvent 13 from sas.sasgui.perspectives.fitting.fitpage import FitPage 14 from sas.sasgui.perspectives.fitting.fitpage import check_data_validity 9 15 10 16 (Chi2UpdateEvent, EVT_CHI2_UPDATE) = wx.lib.newevent.NewEvent() … … 13 19 SMEAR_SIZE_L = 0.00 14 20 SMEAR_SIZE_H = 0.00 15 16 from sas.sasgui.perspectives.fitting.basepage import PageInfoEvent17 from sas.sascalc.data_util.qsmearing import smear_selection18 from sas.sasgui.perspectives.fitting.fitpage import FitPage19 from sas.sasgui.perspectives.fitting.fitpage import check_data_validity20 21 21 22 class BatchFitPage(FitPage): … … 76 77 # """ 77 78 # is_2Ddata = False 78 # 79 # 79 80 # # Check if data is 2D 80 81 # if self.data.__class__.__name__ == "Data2D" or \ 81 82 # self.enable2D: 82 83 # is_2Ddata = True 83 # 84 # title = "Fitting" 84 # 85 # title = "Fitting" 85 86 # self._get_smear_info() 86 # 87 # 87 88 # #Sizers 88 89 # box_description_range = wx.StaticBox(self, wx.ID_ANY, str(title)) 89 # boxsizer_range = wx.StaticBoxSizer(box_description_range, wx.VERTICAL) 90 # boxsizer_range = wx.StaticBoxSizer(box_description_range, wx.VERTICAL) 90 91 # self.sizer_set_smearer = wx.BoxSizer(wx.VERTICAL) 91 92 # #sizer_smearer = wx.BoxSizer(wx.HORIZONTAL) … … 93 94 # self.sizer_set_masking = wx.BoxSizer(wx.HORIZONTAL) 94 95 # sizer_chi2 = wx.BoxSizer(wx.VERTICAL) 95 # 96 # 96 97 # sizer_fit = wx.GridSizer(2, 4, 2, 6) 97 98 # #Fit button … … 100 101 # self.btFit.Bind(wx.EVT_BUTTON, self._onFit, id= self.btFit.GetId()) 101 102 # self.btFit.SetToolTipString("Start fitting.") 102 # 103 # 103 104 # # Update and Draw button 104 105 # self.draw_button = wx.Button(self, self._ids.next(), 'Compute', size=(88, 24)) 105 106 # self.draw_button.Bind(wx.EVT_BUTTON, \ 106 107 # self._onDraw,id=self.draw_button.GetId()) 107 # self.draw_button.SetToolTipString("Compute and Draw.") 108 # self.draw_button.SetToolTipString("Compute and Draw.") 108 109 # sizer_fit.Add(self.draw_button, 0, 0) 109 # sizer_fit.Add(self.btFit, 0, 0) 110 # sizer_fit.Add(self.btFit, 0, 0) 110 111 # sizer_chi2.Add((-1, 5)) 111 112 # # get smear_selection … … 114 115 # #2D data? default 115 116 # is_2Ddata = False 116 # 117 # 117 118 # #check if it is 2D data 118 119 # if self.data.__class__.__name__ == "Data2D" or \ 119 120 # self.enable2D: 120 121 # is_2Ddata = True 121 # 122 # 122 123 # self.sizer5.Clear(True) 123 # 124 # 124 125 # self.qmin = ModelTextCtrl(self, wx.ID_ANY, size=(_BOX_WIDTH, 20), 125 # style=wx.TE_PROCESS_ENTER, 126 # style=wx.TE_PROCESS_ENTER, 126 127 # text_enter_callback = self._onQrangeEnter) 127 128 # self.qmin.SetValue(str(self.qmin_x)) 128 129 # self.qmin.SetToolTipString("Minimun value of Q in linear scale.") 129 # 130 # 130 131 # self.qmax = ModelTextCtrl(self, wx.ID_ANY, size=(_BOX_WIDTH, 20), 131 # style=wx.TE_PROCESS_ENTER, 132 # style=wx.TE_PROCESS_ENTER, 132 133 # text_enter_callback=self._onQrangeEnter) 133 134 # self.qmax.SetValue(str(self.qmax_x)) 134 135 # self.qmax.SetToolTipString("Maximum value of Q in linear scale.") 135 # 136 # 136 137 # id = self._ids.next() 137 138 # self.reset_qrange =wx.Button(self, id, 'Reset', size=(77, 20)) 138 # 139 # 139 140 # self.reset_qrange.Bind(wx.EVT_BUTTON, self.on_reset_clicked, id=id) 140 141 # self.reset_qrange.SetToolTipString(\ 141 142 # "Reset Q range to the default values") 142 # 143 # 143 144 # sizer_horizontal = wx.BoxSizer(wx.HORIZONTAL) 144 145 # sizer = wx.GridSizer(2, 4, 2, 6) 145 # 146 # 146 147 # self.btEditMask = wx.Button(self, self._ids.next(),'Editor', size=(88, 23)) 147 # self.btEditMask.Bind(wx.EVT_BUTTON, 148 # self.btEditMask.Bind(wx.EVT_BUTTON, 148 149 # self._onMask,id=self.btEditMask.GetId()) 149 150 # self.btEditMask.SetToolTipString("Edit Mask.") 150 151 # self.EditMask_title = wx.StaticText(self, wx.ID_ANY, ' Masking(2D)') 151 # 152 # 152 153 # sizer.Add(wx.StaticText(self, wx.ID_ANY, 'Q range')) 153 154 # sizer.Add(wx.StaticText(self, wx.ID_ANY, ' Min[1/A]')) 154 155 # sizer.Add(wx.StaticText(self, wx.ID_ANY, ' Max[1/A]')) 155 156 # sizer.Add(self.EditMask_title) 156 # 157 # sizer.Add(self.reset_qrange) 157 # 158 # sizer.Add(self.reset_qrange) 158 159 # sizer.Add(self.qmin) 159 160 # sizer.Add(self.qmax) 160 # 161 # 161 162 # sizer.Add(self.btEditMask) 162 # boxsizer_range.Add(sizer_chi2) 163 # boxsizer_range.Add(sizer_chi2) 163 164 # boxsizer_range.Add((10, 10)) 164 165 # boxsizer_range.Add(sizer) 165 # 166 # 166 167 # boxsizer_range.Add((10, 15)) 167 168 # boxsizer_range.Add(sizer_fit) 168 169 # if is_2Ddata: 169 # self.btEditMask.Enable() 170 # self.EditMask_title.Enable() 170 # self.btEditMask.Enable() 171 # self.EditMask_title.Enable() 171 172 # else: 172 # self.btEditMask.Disable() 173 # self.btEditMask.Disable() 173 174 # self.EditMask_title.Disable() 174 # 175 # 175 176 # ## save state 176 177 # #self.save_current_state() 177 # 178 # 178 179 # self.sizer5.Add(boxsizer_range, 0, wx.EXPAND | wx.ALL, 10) 179 180 # self.sizer5.Layout() 180 # 181 # def _on_select_model(self, event=None): 181 # 182 # def _on_select_model(self, event=None): 182 183 # """ 183 184 # call back for model selection 184 # """ 185 # 186 # self.Show(False) 187 # self._on_select_model_helper() 188 # self.set_model_param_sizer(self.model) 185 # """ 186 # 187 # self.Show(False) 188 # self._on_select_model_helper() 189 # self.set_model_param_sizer(self.model) 189 190 # if self.model is None: 190 191 # self._set_bookmark_flag(False) … … 199 200 # self.state.structurecombobox = self.structurebox.GetCurrentSelection() 200 201 # self.state.formfactorcombobox = self.formfactorbox.GetCurrentSelection() 201 # 202 # 202 203 # if self.model is not None: 203 204 # self._set_copy_flag(True) … … 206 207 # self._set_bookmark_flag(False) 207 208 # self._keep.Enable(False) 208 # 209 # 209 210 # temp_smear = None 210 211 # ## event to post model to fit to fitting plugins 211 212 # (ModelEventbox, _) = wx.lib.newevent.NewEvent() 212 # 213 # ## set smearing value whether or not 213 # 214 # ## set smearing value whether or not 214 215 # # the data contain the smearing info 215 # evt = ModelEventbox(model=self.model, 216 # smearer=temp_smear, 216 # evt = ModelEventbox(model=self.model, 217 # smearer=temp_smear, 217 218 # qmin=float(self.qmin_x), 218 219 # uid=self.uid, 219 # qmax=float(self.qmax_x)) 220 # 220 # qmax=float(self.qmax_x)) 221 # 221 222 # self._manager._on_model_panel(evt=evt) 222 223 # self.mbox_description.SetLabel("Model [%s]" % str(self.model.name)) 223 224 # self.state.model = self.model.clone() 224 225 # self.state.model.name = self.model.name 225 # 226 # 226 # 227 # 227 228 # if event is not None: 228 229 # ## post state to fit panel 229 230 # new_event = PageInfoEvent(page = self) 230 # wx.PostEvent(self.parent, new_event) 231 # wx.PostEvent(self.parent, new_event) 231 232 # #update list of plugins if new plugin is available 232 233 # if self.plugin_rbutton.GetValue(): … … 243 244 # self._draw_model() 244 245 # self.SetupScrolling() 245 # self.Show(True) 246 # 246 # self.Show(True) 247 # 247 248 # def _update_paramv_on_fit(self): 248 249 # """ … … 253 254 # self.fitrange = True 254 255 # is_modified = False 255 # 256 # 256 257 # if self.model is not None: 257 258 # ##Check the values … … 259 260 # self._check_value_enter( self.fixed_param) 260 261 # self._check_value_enter( self.parameters) 261 # 262 # # If qmin and qmax have been modified, update qmin and qmax and 262 # 263 # # If qmin and qmax have been modified, update qmin and qmax and 263 264 # # Here we should check whether the boundaries have been modified. 264 # # If qmin and qmax have been modified, update qmin and qmax and 265 # # If qmin and qmax have been modified, update qmin and qmax and 265 266 # # set the is_modified flag to True 266 267 # self.fitrange = self._validate_qrange(self.qmin, self.qmax) … … 273 274 # self.qmax_x = tempmax 274 275 # if tempmax == tempmin: 275 # flag = False 276 # flag = False 276 277 # #temp_smearer = None 277 278 # if self._is_2D(): 278 # # only 2D case set mask 279 # # only 2D case set mask 279 280 # flag = self._validate_Npts() 280 281 # if not flag: 281 282 # return flag 282 283 # else: flag = False 283 # else: 284 # else: 284 285 # flag = False 285 # 286 # #For invalid q range, disable the mask editor and fit button, vs. 286 # 287 # #For invalid q range, disable the mask editor and fit button, vs. 287 288 # if not self.fitrange: 288 289 # #self.btFit.Disable() … … 293 294 # if self._is_2D() and self.data is not None: 294 295 # self.btEditMask.Enable(True) 295 # 296 # 296 297 # if not flag: 297 298 # msg = "Cannot Plot or Fit :Must select a " 298 299 # msg += " model or Fitting range is not valid!!! " 299 300 # wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 300 # 301 # 301 302 # self.save_current_state() 302 # 303 # return flag 303 # 304 # return flag 304 305 # def save_current_state(self): 305 306 # """ 306 307 # Currently no save option implemented for batch page 307 308 # """ 308 # pass 309 # pass 309 310 # def save_current_state_fit(self): 310 311 # """ … … 314 315 # def set_data(self, data): 315 316 # """ 316 # reset the current data 317 # reset the current data 317 318 # """ 318 319 # #id = None … … 340 341 # self._set_save_flag(False) 341 342 # self._set_preview_flag(True) 342 # 343 # 343 344 # self.formfactorbox.Enable() 344 345 # self.structurebox.Enable() … … 346 347 # #set maximum range for x in linear scale 347 348 # if not hasattr(self.data,"data"): #Display only for 1D data fit 348 # # Minimum value of data 349 # # Minimum value of data 349 350 # data_min = min(self.data.x) 350 # # Maximum value of data 351 # # Maximum value of data 351 352 # data_max = max(self.data.x) 352 # self.btEditMask.Disable() 353 # self.btEditMask.Disable() 353 354 # self.EditMask_title.Disable() 354 355 # else: 355 # 356 # ## Minimum value of data 356 # 357 # ## Minimum value of data 357 358 # data_min = 0 358 # x = max(math.fabs(self.data.xmin), math.fabs(self.data.xmax)) 359 # x = max(math.fabs(self.data.xmin), math.fabs(self.data.xmax)) 359 360 # y = max(math.fabs(self.data.ymin), math.fabs(self.data.ymax)) 360 # ## Maximum value of data 361 # ## Maximum value of data 361 362 # data_max = math.sqrt(x*x + y*y) 362 # self.btEditMask.Enable() 363 # self.EditMask_title.Enable() 364 # 363 # self.btEditMask.Enable() 364 # self.EditMask_title.Enable() 365 # 365 366 # self.dataSource.SetValue(data_name) 366 367 # self.qmin_x = data_min … … 375 376 # self.state.qmin = self.qmin_x 376 377 # self.state.qmax = self.qmax_x 377 # 378 # 378 379 # #update model plot with new data information 379 380 # if flag: … … 385 386 # self.enable2D = False 386 387 # self.model_view.SetLabel("1D Mode") 387 # 388 # 388 389 # self.model_view.Disable() 389 # 390 # wx.PostEvent(self._manager.parent, 390 # 391 # wx.PostEvent(self._manager.parent, 391 392 # NewPlotEvent(group_id=group_id, 392 393 # action="delete")) 393 394 # #plot the current selected data 394 # wx.PostEvent(self._manager.parent, NewPlotEvent(plot=self.data, 395 # wx.PostEvent(self._manager.parent, NewPlotEvent(plot=self.data, 395 396 # title=str(self.data.title))) 396 397 # self._manager.store_data(uid=self.uid, data=data, -
src/sas/sasgui/perspectives/fitting/fit_thread.py
r959eb01 rba8d326 29 29 worktime=0.03, 30 30 reset_flag=False): 31 CalcThread.__init__(self, 32 completefn, 33 updatefn, 34 yieldtime, 35 worktime) 31 CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime) 36 32 self.handler = handler 37 33 self.fitter = fn … … 93 89 # Real code should not print, but this is an example... 94 90 #print "keyboard exception" 95 #Stop on exception during fitting. Todo: need to put 91 #Stop on exception during fitting. Todo: need to put 96 92 #some mssg and reset progress bar. 97 93 … … 100 96 if self.handler is not None: 101 97 self.handler.stop(msg=msg) 102 except: 98 except: # catch-all: show every exception which stops the thread 103 99 import traceback 104 100 if self.handler is not None: -
src/sas/sasgui/perspectives/fitting/fitpage.py
r13374be r9706d88 14 14 from sasmodels.weights import MODELS as POLYDISPERSITY_MODELS 15 15 16 from sas.sascalc.fit.qsmearing import smear_selection 17 16 18 from sas.sasgui.guiframe.events import StatusEvent, NewPlotEvent, \ 17 19 PlotQrangeEvent … … 23 25 from sas.sasgui.perspectives.fitting.basepage import PageInfoEvent as \ 24 26 PageInfoEvent 25 from sas.sascalc.data_util.qsmearing import smear_selection26 27 from .basepage import ModelTextCtrl 27 28 … … 1142 1143 self.model.name = "M" + str(self.index_model) 1143 1144 1144 def _on_select_model(self, event=None ):1145 def _on_select_model(self, event=None, keep_pars=False): 1145 1146 """ 1146 1147 call back for model selection 1147 1148 """ 1148 1149 self.Show(False) 1149 copy_flag = False1150 is_poly_enabled = None1151 1150 if event is not None: 1152 if (event.GetEventObject() == self.formfactorbox 1153 and self.structurebox.GetLabel() != 'None')\ 1154 or event.GetEventObject() == self.structurebox\ 1155 or event.GetEventObject() == self.multifactorbox: 1156 copy_flag = self.get_copy_params() 1157 is_poly_enabled = self.enable_disp.GetValue() 1151 control = event.GetEventObject() 1152 if ((control == self.formfactorbox 1153 and self.structurebox.GetLabel() != 'None') 1154 or control == self.structurebox 1155 or control == self.multifactorbox): 1156 keep_pars = True 1157 1158 if keep_pars: 1159 saved_pars = self.get_copy_params() 1160 is_poly_enabled = self.enable_disp.GetValue() 1161 else: 1162 saved_pars = None 1163 is_poly_enabled = None 1164 1158 1165 try: 1159 1166 self._on_select_model_helper() … … 1177 1184 try: 1178 1185 self.set_dispers_sizer() 1179 except :1186 except Exception: 1180 1187 pass 1181 1188 self.state.enable_disp = self.enable_disp.GetValue() … … 1238 1245 self.state.model.name = self.model.name 1239 1246 1247 # when select a model only from guictr/button 1248 if is_poly_enabled is not None: 1249 self.enable_disp.SetValue(is_poly_enabled) 1250 self.disable_disp.SetValue(not is_poly_enabled) 1251 self._set_dipers_Param(event=None) 1252 self.state.enable_disp = self.enable_disp.GetValue() 1253 self.state.disable_disp = self.disable_disp.GetValue() 1254 1255 # Keep the previous param values 1256 if saved_pars: 1257 self.get_paste_params(saved_pars) 1258 1240 1259 if event is not None: 1260 # update list of plugins if new plugin is available 1261 # mod_cat = self.categorybox.GetStringSelection() 1262 # if mod_cat == CUSTOM_MODEL: 1263 # temp = self.parent.update_model_list() 1264 # for v in self.parent.model_dictionary.values(): 1265 # if v.id == self.model.id: 1266 # self.model = v() 1267 # break 1268 # if temp: 1269 # self.model_list_box = temp 1270 # current_val = self.formfactorbox.GetLabel() 1271 # pos = self.formfactorbox.GetSelection() 1272 # self._show_combox_helper() 1273 # self.formfactorbox.SetStringSelection(current_val) 1274 # self.formfactorbox.SetValue(current_val) 1241 1275 # post state to fit panel 1242 1276 new_event = PageInfoEvent(page=self) 1243 1277 wx.PostEvent(self.parent, new_event) 1244 # update list of plugins if new plugin is available1245 mod_cat = self.categorybox.GetStringSelection()1246 if mod_cat == CUSTOM_MODEL:1247 temp_id = self.model.id1248 temp = self.parent.update_model_list()1249 for v in self.parent.model_dictionary.values():1250 if v.id == temp_id:1251 self.model = v()1252 break1253 if temp:1254 self.model_list_box = temp1255 current_val = self.formfactorbox.GetLabel()1256 pos = self.formfactorbox.GetSelection()1257 self._show_combox_helper()1258 self.formfactorbox.SetSelection(pos)1259 self.formfactorbox.SetValue(current_val)1260 # when select a model only from guictr/button1261 if is_poly_enabled is not None:1262 self.enable_disp.SetValue(is_poly_enabled)1263 self.disable_disp.SetValue(not is_poly_enabled)1264 self._set_dipers_Param(event=None)1265 self.state.enable_disp = self.enable_disp.GetValue()1266 self.state.disable_disp = self.disable_disp.GetValue()1267 1268 # Keep the previous param values1269 if copy_flag:1270 self.get_paste_params(copy_flag)1271 1278 wx.CallAfter(self._onDraw, None) 1272 1279 … … 1726 1733 ind = 0 1727 1734 while(ind < len(list)): 1728 for key, val in list.ite ritems():1729 if (val == ind):1735 for key, val in list.items(): 1736 if val == ind: 1730 1737 fun_box.Append(key, val) 1731 1738 break -
src/sas/sasgui/perspectives/fitting/fitpanel.py
r13374be r69363c7 9 9 from wx.aui import AuiNotebook as nb 10 10 11 from sas.sascalc.fit.models import ModelManager 12 11 13 from sas.sasgui.guiframe.panel_base import PanelBase 12 14 from sas.sasgui.guiframe.events import PanelOnFocusEvent, StatusEvent 13 15 from sas.sasgui.guiframe.dataFitting import check_data_validity 14 from sas.sasgui.perspectives.fitting.simfitpage import SimultaneousFitPage 15 16 import basepage 17 import models 16 17 18 from . import basepage 19 from .fitpage import FitPage 20 from .simfitpage import SimultaneousFitPage 21 from .batchfitpage import BatchFitPage 22 from .fitting_widgets import BatchDataDialog 23 18 24 _BOX_WIDTH = 80 19 25 … … 46 52 self.event_owner = None 47 53 # dictionary of miodel {model class name, model class} 48 self.menu_mng = models.ModelManager()54 self.menu_mng = ModelManager() 49 55 self.model_list_box = self.menu_mng.get_model_list() 50 56 # pageClosedEvent = nb.EVT_FLATNOTEBOOK_PAGE_CLOSING … … 114 120 """ 115 121 temp = self.menu_mng.update() 116 if len(temp):122 if temp: 117 123 self.model_list_box = temp 118 124 return temp … … 121 127 """ 122 128 """ 123 temp = self.menu_mng.plugins_reset() 124 if len(temp): 125 self.model_list_box = temp 126 return temp 129 self.model_list_box = self.menu_mng.plugins_reset() 130 return self.model_list_box 127 131 128 132 def get_page_by_id(self, uid): … … 298 302 self.model_list_box = dict 299 303 300 def set_model_dict (self, m_dict):304 def set_model_dictionary(self, model_dictionary): 301 305 """ 302 306 copy a dictionary of model name -> model object 303 307 304 :param m _dict: dictionary linking model name -> model object308 :param model_dictionary: dictionary linking model name -> model object 305 309 """ 306 310 … … 316 320 Add the simultaneous fit page 317 321 """ 318 from simfitpage import SimultaneousFitPage319 322 page_finder = self._manager.get_page_finder() 320 323 if caption == "Const & Simul Fit": … … 344 347 """ 345 348 if self.batch_on: 346 from batchfitpage import BatchFitPage347 349 panel = BatchFitPage(parent=self) 348 350 self.batch_page_index += 1 … … 351 353 else: 352 354 # Increment index of fit page 353 from fitpage import FitPage354 355 panel = FitPage(parent=self) 355 356 self.fit_page_index += 1 … … 359 360 panel._set_save_flag(not panel.batch_on) 360 361 panel.set_model_dictionary(self.model_dictionary) 361 panel.populate_box(model_ dict=self.model_list_box)362 panel.populate_box(model_list_box=self.model_list_box) 362 363 panel.formfactor_combo_init() 363 364 panel.set_manager(self._manager) … … 445 446 if data_1d_list and data_2d_list: 446 447 # need to warning the user that this batch is a special case 447 from sas.sasgui.perspectives.fitting.fitting_widgets import \448 BatchDataDialog449 448 dlg = BatchDataDialog(self) 450 449 if dlg.ShowModal() == wx.ID_OK: -
src/sas/sasgui/perspectives/fitting/fitproblem.py
r959eb01 r251ef684 14 14 ################################################################################ 15 15 import copy 16 from sas.sascalc.data_util.qsmearing import smear_selection 17 18 class FitProblemComponent(object): 16 17 from sas.sascalc.fit.qsmearing import smear_selection 18 19 class FitProblem(object): 19 20 """ 20 Inferface containing information to store data, model, range of data, etc... 21 and retreive this information. This is an inferface 22 for a fitProblem i.e relationship between data and model. 21 Define the relationship between data and model, including range, weights, 22 etc. 23 23 """ 24 def __init__(self): 25 """ 26 contains information about data and model to fit 27 """ 28 ## data used for fitting 29 self.fit_data = None 30 self.theory_data = None 31 self.residuals = None 32 # original data: should not be modified 33 self.original_data = None 34 ## the current model 35 self.model = None 36 ## if 1 this fit problem will be selected to fit , if 0 37 ## it will not be selected for fit 38 self.schedule = 0 39 ##list containing parameter name and value 40 self.list_param = [] 41 self.list_param2fit = [] 42 ## smear object to smear or not data1D 43 self.smearer_computed = False 44 self.smearer_enable = False 45 self.smearer_computer_value = None 46 ## fitting range 47 self.qmin = None 48 self.qmax = None 49 # fit weight 50 self.weight = None 51 self.result = None 52 self.fit_tab_caption = None 53 self.name_per_page = None 54 24 55 def enable_smearing(self, flag=False): 25 56 """ … … 27 58 flag is 0 ingore smear value. 28 59 """ 60 self.smearer_enable = flag 61 62 def set_smearer(self, smearer): 63 """ 64 save reference of smear object on fitdata 65 66 :param smear: smear object from DataLoader 67 68 """ 69 self.smearer_computer_value = smearer 29 70 30 71 def get_smearer(self): … … 32 73 return smear object 33 74 """ 75 if not self.smearer_enable: 76 return None 77 if not self.smearer_computed: 78 #smeari_selection should be call only once per fitproblem 79 self.smearer_computer_value = smear_selection(self.fit_data, 80 self.model) 81 self.smearer_computed = True 82 return self.smearer_computer_value 83 34 84 def save_model_name(self, name): 35 85 """ 36 86 """ 87 self.name_per_page = name 37 88 38 89 def get_name(self): 39 90 """ 40 91 """ 92 return self.name_per_page 41 93 42 94 def set_model(self, model): … … 46 98 :param name: name created for model 47 99 """ 100 self.model = model 101 self.smearer_computer_value = smear_selection(self.fit_data, 102 self.model) 103 self.smearer_computed = True 48 104 49 105 def get_model(self): … … 51 107 :return: saved model 52 108 """ 109 return self.model 53 110 54 111 def set_residuals(self, residuals): … … 57 114 :param data: data selected 58 115 """ 116 self.residuals = residuals 59 117 60 118 def get_residuals(self): … … 62 120 :return: residuals 63 121 """ 122 return self.residuals 64 123 65 124 def set_theory_data(self, data): 66 125 """ 67 126 save a copy of the data select to fit 127 68 128 :param data: data selected 69 """ 129 130 """ 131 self.theory_data = copy.deepcopy(data) 70 132 71 133 def get_theory_data(self): 72 134 """ 73 :return: list of data dList 74 """ 135 :return: theory generated with the current model and data of this class 136 """ 137 return self.theory_data 75 138 76 139 def set_fit_data(self, data): 77 140 """ 78 Store of list of data and create by create new fitproblem of each data 79 id, if there was existing information about model, this information 80 get copy to the new fitproblem 141 Store data associated with this class 81 142 :param data: list of data selected 82 143 """ 144 self.original_data = None 145 self.fit_data = None 146 # original data: should not be modified 147 self.original_data = data 148 # fit data: used for fit and can be modified for convenience 149 self.fit_data = copy.deepcopy(data) 150 self.smearer_computer_value = smear_selection(self.fit_data, self.model) 151 self.smearer_computed = True 152 self.result = None 83 153 84 154 def get_fit_data(self): 85 155 """ 86 """ 156 :return: data associate with this class 157 """ 158 return self.fit_data 159 160 def get_origin_data(self): 161 """ 162 """ 163 return self.original_data 164 165 def set_weight(self, is2d, flag=None): 166 """ 167 Received flag and compute error on data. 168 :param flag: flag to transform error of data. 169 :param is2d: flag to distinguish 1D to 2D Data 170 """ 171 from sas.sasgui.perspectives.fitting.utils import get_weight 172 # send original data for weighting 173 self.weight = get_weight(data=self.original_data, is2d=is2d, flag=flag) 174 if is2d: 175 self.fit_data.err_data = self.weight 176 else: 177 self.fit_data.dy = self.weight 178 179 def get_weight(self): 180 """ 181 returns weight array 182 """ 183 return self.weight 184 185 def set_param2fit(self, list): 186 """ 187 Store param names to fit (checked) 188 :param list: list of the param names 189 """ 190 self.list_param2fit = list 191 192 def get_param2fit(self): 193 """ 194 return the list param names to fit 195 """ 196 return self.list_param2fit 87 197 88 198 def set_model_param(self, name, value=None): … … 92 202 :param value: value of that parameter 93 203 """ 94 95 def set_param2fit(self, list): 96 """ 97 Store param names to fit (checked) 98 :param list: list of the param names 99 """ 100 101 def get_param2fit(self): 102 """ 103 return the list param names to fit 104 """ 204 self.list_param.append([name, value]) 105 205 106 206 def get_model_param(self): … … 108 208 return list of couple of parameter name and value 109 209 """ 210 return self.list_param 110 211 111 212 def schedule_tofit(self, schedule=0): … … 113 214 set schedule to true to decide if this fit must be performed 114 215 """ 216 self.schedule = schedule 115 217 116 218 def get_scheduled(self): … … 118 220 return true or false if a problem as being schedule for fitting 119 221 """ 222 return self.schedule 120 223 121 224 def set_range(self, qmin=None, qmax=None): 122 225 """ 123 226 set fitting range 124 """ 227 :param qmin: minimum value to consider for the fit range 228 :param qmax: maximum value to consider for the fit range 229 """ 230 self.qmin = qmin 231 self.qmax = qmax 125 232 126 233 def get_range(self): 127 234 """ 128 235 :return: fitting range 129 """ 130 131 def set_weight(self, flag=None): 132 """ 133 set fitting range 134 """ 135 136 def get_weight(self): 137 """ 138 get fitting weight 139 """ 236 237 """ 238 return self.qmin, self.qmax 140 239 141 240 def clear_model_param(self): … … 143 242 clear constraint info 144 243 """ 244 self.list_param = [] 145 245 146 246 def set_fit_tab_caption(self, caption): 147 247 """ 148 store the caption of the page associated with object149 """248 """ 249 self.fit_tab_caption = str(caption) 150 250 151 251 def get_fit_tab_caption(self): 152 252 """ 153 Return the caption of the page associated with object154 """253 """ 254 return self.fit_tab_caption 155 255 156 256 def set_graph_id(self, id): … … 158 258 Set graph id (from data_group_id at the time the graph produced) 159 259 """ 260 self.graph_id = id 160 261 161 262 def get_graph_id(self): … … 163 264 Get graph_id 164 265 """ 266 return self.graph_id 165 267 166 268 def set_result(self, result): 167 269 """ 168 270 """ 271 self.result = result 169 272 170 273 def get_result(self): … … 172 275 get result 173 276 """ 174 175 176 class FitProblemDictionary(FitProblemComponent, dict): 277 return self.result 278 279 280 class FitProblemDictionary(dict): 177 281 """ 178 282 This module implements a dictionary of fitproblem objects 179 283 """ 180 284 def __init__(self): 181 FitProblemComponent.__init__(self)182 285 dict.__init__(self) 183 286 ## the current model … … 206 309 self._smear_on = flag 207 310 if fid is None: 208 for value in self. itervalues():311 for value in self.values(): 209 312 value.enable_smearing(flag) 210 else: 211 if fid in self.iterkeys(): 212 self[fid].enable_smearing(flag) 313 elif fid in self: 314 self[fid].enable_smearing(flag) 213 315 214 316 def set_smearer(self, smearer, fid=None): … … 218 320 """ 219 321 if fid is None: 220 for value in self. itervalues():322 for value in self.values(): 221 323 value.set_smearer(smearer) 222 else: 223 if fid in self.iterkeys(): 224 self[fid].set_smearer(smearer) 324 elif fid in self: 325 self[fid].set_smearer(smearer) 225 326 226 327 def get_smearer(self, fid=None): … … 228 329 return smear object 229 330 """ 230 if fid in self .iterkeys():331 if fid in self: 231 332 return self[fid].get_smearer() 232 333 … … 235 336 """ 236 337 if fid is None: 237 for value in self. itervalues():338 for value in self.values(): 238 339 value.save_model_name(name) 239 else: 240 if fid in self.iterkeys(): 241 self[fid].save_model_name(name) 340 elif fid in self: 341 self[fid].save_model_name(name) 242 342 243 343 def get_name(self, fid=None): … … 246 346 result = [] 247 347 if fid is None: 248 for value in self. itervalues():348 for value in self.values(): 249 349 result.append(value.get_name()) 250 else: 251 if fid in self.iterkeys(): 252 result.append(self[fid].get_name()) 350 elif fid in self: 351 result.append(self[fid].get_name()) 253 352 return result 254 353 … … 261 360 self.model = model 262 361 if fid is None: 263 for value in self. itervalues():362 for value in self.values(): 264 363 value.set_model(self.model) 265 else: 266 if fid in self.iterkeys(): 267 self[fid].set_model(self.model) 364 elif fid in self: 365 self[fid].set_model(self.model) 268 366 269 367 def get_model(self, fid): … … 271 369 :return: saved model 272 370 """ 273 if fid in self .iterkeys():371 if fid in self: 274 372 return self[fid].get_model() 275 373 … … 291 389 :param data: data selected 292 390 """ 293 if fid in self .iterkeys():391 if fid in self: 294 392 self[fid].set_residuals(residuals) 295 393 … … 298 396 :return: residuals 299 397 """ 300 if fid in self .iterkeys():398 if fid in self: 301 399 return self[fid].get_residuals() 302 400 … … 306 404 :param data: data selected 307 405 """ 308 if fid in self .iterkeys():406 if fid in self: 309 407 self[fid].set_theory_data(data) 310 408 … … 313 411 :return: list of data dList 314 412 """ 315 if fid in self .iterkeys():413 if fid in self: 316 414 return self[fid].get_theory_data() 317 415 … … 322 420 :note: only data changes in the fit problem 323 421 """ 324 if data.id not in self .iterkeys():422 if data.id not in self: 325 423 self[data.id] = FitProblem() 326 424 self[data.id].set_fit_data(data) … … 336 434 data = [] 337 435 for d in data: 338 if (d is not None):339 if (d.id not in self.iterkeys()):436 if d is not None: 437 if d.id not in self: 340 438 self[d.id] = FitProblem() 341 439 self[d.id].set_fit_data(d) … … 348 446 :param fid: key representing a fitproblem, usually extract from data id 349 447 """ 350 if fid in self .iterkeys():448 if fid in self: 351 449 return self[fid].get_fit_data() 352 450 … … 358 456 """ 359 457 if fid is None: 360 for value in self. itervalues():458 for value in self.values(): 361 459 value.set_model_param(name, value) 362 else: 363 if fid in self.iterkeys(): 364 self[fid].set_model_param(name, value) 460 elif fid in self: 461 self[fid].set_model_param(name, value) 365 462 366 463 def get_model_param(self, fid): … … 368 465 return list of couple of parameter name and value 369 466 """ 370 if fid in self .iterkeys():467 if fid in self: 371 468 return self[fid].get_model_param() 372 469 … … 389 486 """ 390 487 self.scheduled = schedule 391 for value in self. itervalues():488 for value in self.values(): 392 489 value.schedule_tofit(schedule) 393 490 … … 405 502 self.qmax = qmax 406 503 if fid is None: 407 for value in self. itervalues():504 for value in self.values(): 408 505 value.set_range(self.qmin, self.qmax) 409 else: 410 if fid in self.iterkeys(): 411 self[fid].value.set_range(self.qmin, self.qmax) 506 elif fid in self: 507 self[fid].value.set_range(self.qmin, self.qmax) 412 508 413 509 def get_range(self, fid): … … 415 511 :return: fitting range 416 512 """ 417 if fid in self .iterkeys():513 if fid in self: 418 514 return self[fid].get_range() 419 515 … … 423 519 """ 424 520 if fid is None: 425 for value in self. itervalues():521 for value in self.values(): 426 522 value.set_weight(flag=flag, is2d=is2d) 427 else: 428 if fid in self.iterkeys(): 429 self[fid].set_weight(flag=flag, is2d=is2d) 523 elif fid in self: 524 self[fid].set_weight(flag=flag, is2d=is2d) 430 525 431 526 def get_weight(self, fid=None): … … 433 528 return fit weight 434 529 """ 435 if fid in self .iterkeys():530 if fid in self: 436 531 return self[fid].get_weight() 437 532 … … 441 536 """ 442 537 if fid is None: 443 for value in self. itervalues():538 for value in self.values(): 444 539 value.clear_model_param() 445 else: 446 if fid in self.iterkeys(): 447 self[fid].clear_model_param() 540 elif fid in self: 541 self[fid].clear_model_param() 448 542 449 543 def get_fit_problem(self): … … 451 545 return fitproblem contained in this dictionary 452 546 """ 453 return self. itervalues()547 return self.values() 454 548 455 549 def set_result(self, result, fid): 456 550 """ 457 551 """ 458 if fid in self .iterkeys():552 if fid in self: 459 553 self[fid].set_result(result) 460 554 … … 470 564 get result 471 565 """ 472 if fid in self .iterkeys():566 if fid in self: 473 567 return self[fid].get_result() 474 568 … … 490 584 """ 491 585 return self.graph_id 492 493 494 class FitProblem(FitProblemComponent):495 """496 FitProblem class allows to link a model with the new name created in _on_model,497 a name theory created with that model and the data fitted with the model.498 FitProblem is mostly used as value of the dictionary by fitting module.499 """500 def __init__(self):501 FitProblemComponent.__init__(self)502 """503 contains information about data and model to fit504 """505 ## data used for fitting506 self.fit_data = None507 self.theory_data = None508 self.residuals = None509 # original data: should not be modified510 self.original_data = None511 ## the current model512 self.model = None513 ## if 1 this fit problem will be selected to fit , if 0514 ## it will not be selected for fit515 self.schedule = 0516 ##list containing parameter name and value517 self.list_param = []518 ## smear object to smear or not data1D519 self.smearer_computed = False520 self.smearer_enable = False521 self.smearer_computer_value = None522 ## fitting range523 self.qmin = None524 self.qmax = None525 # fit weight526 self.weight = None527 self.result = None528 529 def enable_smearing(self, flag=False):530 """531 :param flag: bool.When flag is 1 get the computer smear value. When532 flag is 0 ingore smear value.533 """534 self.smearer_enable = flag535 536 def set_smearer(self, smearer):537 """538 save reference of smear object on fitdata539 540 :param smear: smear object from DataLoader541 542 """543 self.smearer_computer_value = smearer544 545 def get_smearer(self):546 """547 return smear object548 """549 if not self.smearer_enable:550 return None551 if not self.smearer_computed:552 #smeari_selection should be call only once per fitproblem553 self.smearer_computer_value = smear_selection(self.fit_data,554 self.model)555 self.smearer_computed = True556 return self.smearer_computer_value557 558 def save_model_name(self, name):559 """560 """561 self.name_per_page = name562 563 def get_name(self):564 """565 """566 return self.name_per_page567 568 def set_model(self, model):569 """570 associates each model with its new created name571 :param model: model selected572 :param name: name created for model573 """574 self.model = model575 self.smearer_computer_value = smear_selection(self.fit_data,576 self.model)577 self.smearer_computed = True578 579 def get_model(self):580 """581 :return: saved model582 """583 return self.model584 585 def set_residuals(self, residuals):586 """587 save a copy of residual588 :param data: data selected589 """590 self.residuals = residuals591 592 def get_residuals(self):593 """594 :return: residuals595 """596 return self.residuals597 598 def set_theory_data(self, data):599 """600 save a copy of the data select to fit601 602 :param data: data selected603 604 """605 self.theory_data = copy.deepcopy(data)606 607 def get_theory_data(self):608 """609 :return: theory generated with the current model and data of this class610 """611 return self.theory_data612 613 def set_fit_data(self, data):614 """615 Store data associated with this class616 :param data: list of data selected617 """618 self.original_data = None619 self.fit_data = None620 # original data: should not be modified621 self.original_data = data622 # fit data: used for fit and can be modified for convenience623 self.fit_data = copy.deepcopy(data)624 self.smearer_computer_value = smear_selection(self.fit_data,625 self.model)626 self.smearer_computed = True627 self.result = None628 629 def get_fit_data(self):630 """631 :return: data associate with this class632 """633 return self.fit_data634 635 def get_origin_data(self):636 """637 """638 return self.original_data639 640 def set_weight(self, is2d, flag=None):641 """642 Received flag and compute error on data.643 :param flag: flag to transform error of data.644 :param is2d: flag to distinguish 1D to 2D Data645 """646 from sas.sasgui.perspectives.fitting.utils import get_weight647 # send original data for weighting648 self.weight = get_weight(data=self.original_data, is2d=is2d, flag=flag)649 if is2d:650 self.fit_data.err_data = self.weight651 else:652 self.fit_data.dy = self.weight653 654 def get_weight(self):655 """656 returns weight array657 """658 return self.weight659 660 def set_param2fit(self, list):661 """662 Store param names to fit (checked)663 :param list: list of the param names664 """665 self.list_param2fit = list666 667 def get_param2fit(self):668 """669 return the list param names to fit670 """671 return self.list_param2fit672 673 def set_model_param(self, name, value=None):674 """675 Store the name and value of a parameter of this fitproblem's model676 :param name: name of the given parameter677 :param value: value of that parameter678 """679 self.list_param.append([name, value])680 681 def get_model_param(self):682 """683 return list of couple of parameter name and value684 """685 return self.list_param686 687 def schedule_tofit(self, schedule=0):688 """689 set schedule to true to decide if this fit must be performed690 """691 self.schedule = schedule692 693 def get_scheduled(self):694 """695 return true or false if a problem as being schedule for fitting696 """697 return self.schedule698 699 def set_range(self, qmin=None, qmax=None):700 """701 set fitting range702 :param qmin: minimum value to consider for the fit range703 :param qmax: maximum value to consider for the fit range704 """705 self.qmin = qmin706 self.qmax = qmax707 708 def get_range(self):709 """710 :return: fitting range711 712 """713 return self.qmin, self.qmax714 715 def clear_model_param(self):716 """717 clear constraint info718 """719 self.list_param = []720 721 def set_fit_tab_caption(self, caption):722 """723 """724 self.fit_tab_caption = str(caption)725 726 def get_fit_tab_caption(self):727 """728 """729 return self.fit_tab_caption730 731 def set_graph_id(self, id):732 """733 Set graph id (from data_group_id at the time the graph produced)734 """735 self.graph_id = id736 737 def get_graph_id(self):738 """739 Get graph_id740 """741 return self.graph_id742 743 def set_result(self, result):744 """745 """746 self.result = result747 748 def get_result(self):749 """750 get result751 """752 return self.result -
src/sas/sasgui/perspectives/fitting/fitting.py
r66acafe r9706d88 23 23 import traceback 24 24 25 import bumps.options 26 from bumps.gui.fit_dialog import show_fit_config 27 try: 28 from bumps.gui.fit_dialog import EVT_FITTER_CHANGED 29 except ImportError: 30 # CRUFT: bumps 0.7.5.8 and below 31 EVT_FITTER_CHANGED = None # type: wx.PyCommandEvent 32 25 33 from sas.sascalc.dataloader.loader import Loader 34 from sas.sascalc.fit.BumpsFitting import BumpsFit as Fit 35 from sas.sascalc.fit.pagestate import Reader, PageState, SimFitPageState 36 from sas.sascalc.fit import models 37 26 38 from sas.sasgui.guiframe.dataFitting import Data2D 27 39 from sas.sasgui.guiframe.dataFitting import Data1D … … 34 46 from sas.sasgui.guiframe.plugin_base import PluginBase 35 47 from sas.sasgui.guiframe.data_processor import BatchCell 36 from sas.sascalc.fit.BumpsFitting import BumpsFit as Fit 37 from sas.sasgui.perspectives.fitting.console import ConsoleUpdate 38 from sas.sasgui.perspectives.fitting.fitproblem import FitProblemDictionary 39 from sas.sasgui.perspectives.fitting.fitpanel import FitPanel 40 from sas.sasgui.perspectives.fitting.resultpanel import ResultPanel, PlotResultEvent 41 42 from sas.sasgui.perspectives.fitting.fit_thread import FitThread 43 from sas.sasgui.perspectives.fitting.pagestate import Reader 44 from sas.sasgui.perspectives.fitting.fitpage import Chi2UpdateEvent 48 from sas.sasgui.guiframe.gui_manager import MDIFrame 49 from sas.sasgui.guiframe.documentation_window import DocumentationWindow 50 45 51 from sas.sasgui.perspectives.calculator.model_editor import TextDialog 46 52 from sas.sasgui.perspectives.calculator.model_editor import EditorWindow 47 from sas.sasgui.guiframe.gui_manager import MDIFrame 48 from sas.sasgui.guiframe.documentation_window import DocumentationWindow 49 from sas.sasgui.perspectives.fitting.gpu_options import GpuOptions 50 51 from . import models 53 from sas.sasgui.perspectives.calculator.pyconsole import PyConsole 54 55 from .fitting_widgets import DataDialog 56 from .fit_thread import FitThread 57 from .fitpage import Chi2UpdateEvent 58 from .console import ConsoleUpdate 59 from .fitproblem import FitProblemDictionary 60 from .fitpanel import FitPanel 61 from .model_thread import Calc1D, Calc2D 62 from .resultpanel import ResultPanel, PlotResultEvent 63 from .gpu_options import GpuOptions 52 64 53 65 logger = logging.getLogger(__name__) … … 63 75 ON_MAC = True 64 76 65 import bumps.options66 from bumps.gui.fit_dialog import show_fit_config67 try:68 from bumps.gui.fit_dialog import EVT_FITTER_CHANGED69 except ImportError:70 # CRUFT: bumps 0.7.5.8 and below71 EVT_FITTER_CHANGED = None # type: wx.PyCommandEvent72 77 73 78 class Plugin(PluginBase): … … 240 245 event_id = event.GetId() 241 246 label = self.edit_menu.GetLabel(event_id) 242 from sas.sasgui.perspectives.calculator.pyconsole import PyConsole243 247 filename = os.path.join(models.find_plugins_dir(), label) 244 248 frame = PyConsole(parent=self.parent, manager=self, … … 290 294 break 291 295 except Exception: 292 import traceback;traceback.print_exc()296 traceback.print_exc() 293 297 msg = 'Delete Error: \nCould not delete the file; Check if in use.' 294 298 wx.MessageBox(msg, 'Error') … … 300 304 event_id = event.GetId() 301 305 model_manager = models.ModelManager() 302 model_list = model_manager. get_model_name_list()306 model_list = model_manager.composable_models() 303 307 plug_dir = models.find_plugins_dir() 304 308 textdial = TextDialog(None, self, wx.ID_ANY, 'Easy Sum/Multi(p1, p2) Editor', … … 340 344 self.set_edit_menu_helper(self.parent, self.edit_custom_model) 341 345 self.set_edit_menu_helper(self.parent, self.delete_custom_model) 342 temp = self.fit_panel.reset_pmodel_list() 343 if temp: 344 # Set the new plugin model list for all fit pages 345 for uid, page in self.fit_panel.opened_pages.iteritems(): 346 if hasattr(page, "formfactorbox"): 347 page.model_list_box = temp 348 current_val = page.formfactorbox.GetLabel() 349 #if page.plugin_rbutton.GetValue(): 350 mod_cat = page.categorybox.GetStringSelection() 351 if mod_cat == custom_model: 352 #pos = page.formfactorbox.GetSelection() 353 page._show_combox_helper() 354 new_val = page.formfactorbox.GetLabel() 355 if current_val != new_val and new_val != '': 356 page.formfactorbox.SetLabel(new_val) 357 else: 358 page.formfactorbox.SetLabel(current_val) 359 if hasattr(page, 'structurebox'): 360 selected_name = page.structurebox.GetStringSelection() 361 362 page.structurebox.Clear() 363 page.initialize_combox() 364 365 index = page.structurebox.FindString(selected_name) 366 if index == -1: 367 index = 0 368 page.structurebox.SetSelection(index) 369 page._on_select_model() 370 except: 346 new_pmodel_list = self.fit_panel.reset_pmodel_list() 347 if not new_pmodel_list: 348 return 349 # Set the new plugin model list for all fit pages 350 for uid, page in self.fit_panel.opened_pages.iteritems(): 351 if hasattr(page, "formfactorbox"): 352 page.model_list_box = new_pmodel_list 353 mod_cat = page.categorybox.GetStringSelection() 354 if mod_cat == custom_model: 355 box = page.formfactorbox 356 model_name = box.GetValue() 357 model = (box.GetClientData(box.GetCurrentSelection()) 358 if model_name else None) 359 page._show_combox_helper() 360 new_index = box.FindString(model_name) 361 new_model = (box.GetClientData(new_index) 362 if new_index >= 0 else None) 363 if new_index >= 0: 364 box.SetStringSelection(model_name) 365 else: 366 box.SetStringSelection('') 367 if model and new_model != model: 368 page._on_select_model(keep_pars=True) 369 if hasattr(page, "structurebox"): 370 selected_name = page.structurebox.GetStringSelection() 371 372 page.structurebox.Clear() 373 page.initialize_combox() 374 375 index = page.structurebox.FindString(selected_name) 376 if index == -1: 377 index = 0 378 page.structurebox.SetSelection(index) 379 page._on_select_model() 380 except Exception: 371 381 logger.error("update_custom_combo: %s", sys.exc_value) 372 382 … … 378 388 #new_model_menu = wx.Menu() 379 389 self.edit_model_menu.Append(wx_id, 'New Plugin Model', 380 'Add a new model function')390 'Add a new model function') 381 391 wx.EVT_MENU(owner, wx_id, self.make_new_model) 382 392 … … 575 585 else: 576 586 if len(data_list) > MAX_NBR_DATA: 577 from fitting_widgets import DataDialog578 587 dlg = DataDialog(data_list=data_list, nb_data=MAX_NBR_DATA) 579 588 if dlg.ShowModal() == wx.ID_OK: … … 620 629 : param datainfo: data 621 630 """ 622 from pagestate import PageState623 from simfitpage import SimFitPageState624 631 if isinstance(state, PageState): 625 632 state = state.clone() 626 633 self.temp_state.append(state) 627 634 elif isinstance(state, SimFitPageState): 628 state.load_from_save_state(self) 635 if self.fit_panel.sim_page is None: 636 self.fit_panel.add_sim_page() 637 self.fit_panel.sim_page.load_from_save_state(state) 629 638 else: 630 639 self.temp_state = [] … … 661 670 self.parent.add_data(data_list={data.id: data}) 662 671 wx.PostEvent(self.parent, NewPlotEvent(plot=data, 663 672 title=data.title)) 664 673 #need to be fix later make sure we are sendind guiframe.data 665 674 #to panel … … 672 681 self.parent.add_data(data_list={data.id: data}) 673 682 wx.PostEvent(self.parent, NewPlotEvent(plot=data, 674 683 title=data.title)) 675 684 page = self.add_fit_page([data]) 676 685 caption = page.window_caption 677 686 self.store_data(uid=page.uid, data_list=page.get_data_list(), 678 caption=caption)687 caption=caption) 679 688 self.mypanels.append(page) 680 689 … … 793 802 """ 794 803 if item.find(".") >= 0: 795 param_names = re.split( "\.", item)804 param_names = re.split(r"\.", item) 796 805 model_name = param_names[0] 797 806 ##Assume max len is 3; eg., M0.radius.width … … 896 905 897 906 self.draw_model(model=model, data=data, page_id=uid, smearer=smear, 898 enable1D=enable1D, enable2D=enable2D,899 qmin=qmin, qmax=qmax, weight=weight)907 enable1D=enable1D, enable2D=enable2D, 908 qmin=qmin, qmax=qmax, weight=weight) 900 909 901 910 def draw_model(self, model, page_id, data=None, smearer=None, … … 940 949 ## draw model 2D with no initial data 941 950 self._draw_model2D(model=model, 942 943 944 945 946 947 948 949 950 951 952 953 951 page_id=page_id, 952 data=data, 953 enable2D=enable2D, 954 smearer=smearer, 955 qmin=qmin, 956 qmax=qmax, 957 fid=fid, 958 weight=weight, 959 state=state, 960 toggle_mode_on=toggle_mode_on, 961 update_chisqr=update_chisqr, 962 source=source) 954 963 955 964 def onFit(self, uid): … … 960 969 :param uid: id related to the panel currently calling this fit function. 961 970 """ 962 if uid is None: raise RuntimeError("no page to fit") # Should never happen 971 if uid is None: 972 raise RuntimeError("no page to fit") # Should never happen 963 973 964 974 sim_page_uid = getattr(self.sim_page, 'uid', None) … … 994 1004 page = self.fit_panel.get_page_by_id(page_id) 995 1005 self.set_fit_weight(uid=page.uid, 996 flag=page.get_weight_flag(),997 is2d=page._is_2D())1006 flag=page.get_weight_flag(), 1007 is2d=page._is_2D()) 998 1008 if not page.param_toFit: 999 1009 msg = "No fitting parameters for %s" % page.window_caption … … 1019 1029 fitter = sim_fitter 1020 1030 self._add_problem_to_fit(fitproblem=fitproblem, 1021 pars=pars,1022 fitter=fitter,1023 fit_id=fit_id)1031 pars=pars, 1032 fitter=fitter, 1033 fit_id=fit_id) 1024 1034 fit_id += 1 1025 1035 list_page_id.append(page_id) … … 1068 1078 ## Perform more than 1 fit at the time 1069 1079 calc_fit = FitThread(handler=handler, 1070 1071 1072 1073 1074 1075 1080 fn=fitter_list, 1081 batch_inputs=batch_inputs, 1082 batch_outputs=batch_outputs, 1083 page_id=list_page_id, 1084 updatefn=handler.update_fit, 1085 completefn=self._fit_completed) 1076 1086 #self.fit_thread_list[current_page_id] = calc_fit 1077 1087 self.fit_thread_list[uid] = calc_fit … … 1134 1144 evt = StatusEvent(status=msg, info="warning") 1135 1145 wx.PostEvent(self.parent, evt) 1136 except :1146 except Exception: 1137 1147 msg = "Creating Fit page: %s" % sys.exc_value 1138 1148 wx.PostEvent(self.parent, StatusEvent(status=msg, info="error")) … … 1158 1168 group_id = str(page.uid) + " Model1D" 1159 1169 wx.PostEvent(self.parent, 1160 NewPlotEvent(group_id=group_id,1161 1170 NewPlotEvent(group_id=group_id, 1171 action="delete")) 1162 1172 self.parent.update_data(prev_data=theory_data, 1163 1173 new_data=data) 1164 1174 else: 1165 1175 if theory_data is not None: … … 1167 1177 data.group_id = theory_data.group_id 1168 1178 wx.PostEvent(self.parent, 1169 NewPlotEvent(group_id=group_id,1170 1179 NewPlotEvent(group_id=group_id, 1180 action="delete")) 1171 1181 self.parent.update_data(prev_data=theory_data, 1172 1182 new_data=data) 1173 1183 self.store_data(uid=page.uid, data_list=page.get_data_list(), 1174 1184 caption=page.window_caption) … … 1479 1489 if "Data" not in batch_outputs.keys(): 1480 1490 batch_outputs["Data"] = [] 1481 from sas.sasgui.guiframe.data_processor import BatchCell1482 1491 cell = BatchCell() 1483 1492 cell.label = data.name … … 1579 1588 except KeyboardInterrupt: 1580 1589 fit_msg += "\nSingular point: Fitting stopped." 1581 except :1590 except Exception: 1582 1591 fit_msg += "\nSingular point: Fitting error occurred." 1583 1592 if fit_msg: 1584 evt = StatusEvent(status=fit_msg, info="warning", type="stop")1585 wx.PostEvent(self.parent, evt)1586 1587 except :1593 evt = StatusEvent(status=fit_msg, info="warning", type="stop") 1594 wx.PostEvent(self.parent, evt) 1595 1596 except Exception: 1588 1597 msg = ("Fit completed but the following error occurred: %s" 1589 1598 % sys.exc_value) 1590 # import traceback;msg = "\n".join((traceback.format_exc(), msg))1599 #msg = "\n".join((traceback.format_exc(), msg)) 1591 1600 evt = StatusEvent(status=msg, info="warning", type="stop") 1592 1601 wx.PostEvent(self.parent, evt) … … 1743 1752 fid=data.id) 1744 1753 self.parent.update_theory(data_id=data.id, theory=new_plot, 1745 1754 state=state) 1746 1755 return new_plot 1747 1756 … … 1767 1776 # Create the new theories 1768 1777 if unsmeared_model is not None: 1769 unsmeared_model_plot = self.create_theory_1D(x, unsmeared_model, 1778 unsmeared_model_plot = self.create_theory_1D(x, unsmeared_model, 1770 1779 page_id, model, data, state, 1771 1780 data_description=model.name + " unsmeared", … … 1774 1783 1775 1784 if unsmeared_data is not None and unsmeared_error is not None: 1776 unsmeared_data_plot = self.create_theory_1D(x, unsmeared_data, 1785 unsmeared_data_plot = self.create_theory_1D(x, unsmeared_data, 1777 1786 page_id, model, data, state, 1778 1787 data_description="Data unsmeared", … … 1792 1801 plots_to_update.append(pq_plot) 1793 1802 # Update the P(Q), S(Q) and unsmeared theory plots if they exist 1794 wx.PostEvent(self.parent, NewPlotEvent(plots=plots_to_update, 1803 wx.PostEvent(self.parent, NewPlotEvent(plots=plots_to_update, 1795 1804 action='update')) 1796 1805 … … 1808 1817 1809 1818 self.page_finder[page_id].set_theory_data(data=new_plot, 1810 1819 fid=data.id) 1811 1820 if toggle_mode_on: 1812 1821 wx.PostEvent(self.parent, 1813 1822 NewPlotEvent(group_id=str(page_id) + " Model2D", 1814 1823 action="Hide")) 1815 1824 else: 1816 1825 if update_chisqr: 1817 wx.PostEvent(current_pg, 1818 Chi2UpdateEvent(output=self._cal_chisqr( 1819 data=data, 1820 fid=fid, 1821 weight=weight, 1822 page_id=page_id, 1823 index=index))) 1826 output = self._cal_chisqr(data=data, 1827 fid=fid, 1828 weight=weight, 1829 page_id=page_id, 1830 index=index) 1831 wx.PostEvent(current_pg, Chi2UpdateEvent(output=output)) 1824 1832 else: 1825 1833 self._plot_residuals(page_id=page_id, data=data, fid=fid, … … 1829 1837 logger.error("Using the present parameters the model does not return any finite value. ") 1830 1838 msg = "Computing Error: Model did not return any finite value." 1831 wx.PostEvent(self.parent, StatusEvent(status =msg, info="error"))1839 wx.PostEvent(self.parent, StatusEvent(status=msg, info="error")) 1832 1840 else: 1833 1841 msg = "Computation completed!" … … 1854 1862 1855 1863 def _complete2D(self, image, data, model, page_id, elapsed, index, qmin, 1856 qmax, fid=None, weight=None, toggle_mode_on=False, state=None,1857 1864 qmax, fid=None, weight=None, toggle_mode_on=False, state=None, 1865 update_chisqr=True, source='model', plot_result=True): 1858 1866 """ 1859 1867 Complete get the result of modelthread and create model 2D … … 1896 1904 fid=data.id) 1897 1905 self.parent.update_theory(data_id=data.id, 1898 1899 1906 theory=new_plot, 1907 state=state) 1900 1908 current_pg = self.fit_panel.get_page_by_id(page_id) 1901 1909 title = new_plot.title 1902 1910 if not source == 'fit' and plot_result: 1903 wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, 1904 title=title)) 1911 wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=title)) 1905 1912 if toggle_mode_on: 1906 1913 wx.PostEvent(self.parent, 1907 1908 1914 NewPlotEvent(group_id=str(page_id) + " Model1D", 1915 action="Hide")) 1909 1916 else: 1910 1917 # Chisqr in fitpage 1911 1918 if update_chisqr: 1912 wx.PostEvent(current_pg,1913 Chi2UpdateEvent(output=self._cal_chisqr(data=data,1914 weight=weight,1915 fid=fid,1916 page_id=page_id,1917 index=index)))1919 output = self._cal_chisqr(data=data, 1920 weight=weight, 1921 fid=fid, 1922 page_id=page_id, 1923 index=index) 1924 wx.PostEvent(current_pg, Chi2UpdateEvent(output=output)) 1918 1925 else: 1919 1926 self._plot_residuals(page_id=page_id, data=data, fid=fid, 1920 1927 index=index, weight=weight) 1921 1928 1922 1929 if not number_finite: 1923 1930 logger.error("Using the present parameters the model does not return any finite value. ") 1924 1931 msg = "Computing Error: Model did not return any finite value." 1925 wx.PostEvent(self.parent, StatusEvent(status =msg, info="error"))1932 wx.PostEvent(self.parent, StatusEvent(status=msg, info="error")) 1926 1933 else: 1927 1934 msg = "Computation completed!" … … 1939 1946 weight=None, 1940 1947 toggle_mode_on=False, 1941 1948 update_chisqr=True, source='model'): 1942 1949 """ 1943 1950 draw model in 2D … … 1954 1961 return None 1955 1962 try: 1956 from model_thread import Calc2D1957 1963 ## If a thread is already started, stop it 1958 1964 if (self.calc_2D is not None) and self.calc_2D.isrunning(): … … 1986 1992 def _draw_model1D(self, model, page_id, data, 1987 1993 qmin, qmax, smearer=None, 1988 state=None, 1989 weight=None, 1990 fid=None, 1991 toggle_mode_on=False, update_chisqr=True, source='model', 1992 enable1D=True): 1994 state=None, weight=None, fid=None, 1995 toggle_mode_on=False, update_chisqr=True, source='model', 1996 enable1D=True): 1993 1997 """ 1994 1998 Draw model 1D from loaded data1D … … 2001 2005 return 2002 2006 try: 2003 from model_thread import Calc1D2004 2007 ## If a thread is already started, stop it 2005 2008 if (self.calc_1D is not None) and self.calc_1D.isrunning(): -
src/sas/sasgui/perspectives/fitting/model_thread.py
r0f9ea1c r69363c7 1 1 """ 2 2 Calculation thread for modeling 3 3 """ 4 4 5 5 import time 6 import math 7 6 8 import numpy as np 7 import math 9 8 10 from sas.sascalc.data_util.calcthread import CalcThread 9 11 from sas.sascalc.fit.MultiplicationModel import MultiplicationModel … … 28 30 worktime=0.04, 29 31 exception_handler=None, 30 32 ): 31 33 CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime, 32 34 exception_handler=exception_handler) … … 57 59 if self.qmax is None: 58 60 if self.data is not None: 59 newx = math.pow(max(math.fabs(self.data.xmax), 60 math.fabs(self.data.xmin)), 2) 61 newy = math.pow(max(math.fabs(self.data.ymax), 62 math.fabs(self.data.ymin)), 2) 63 self.qmax = math.sqrt(newx + newy) 61 newx = max(math.fabs(self.data.xmax), math.fabs(self.data.xmin)) 62 newy = max(math.fabs(self.data.ymax), math.fabs(self.data.ymin)) 63 self.qmax = math.sqrt(newx**2 + newy**2) 64 64 65 65 if self.data is None: … … 68 68 69 69 # Define matrix where data will be plotted 70 radius = np.sqrt((self.data.qx_data * self.data.qx_data) + \ 71 (self.data.qy_data * self.data.qy_data)) 70 radius = np.sqrt(self.data.qx_data**2 + self.data.qy_data**2) 72 71 73 72 # For theory, qmax is based on 1d qmax 74 73 # so that must be mulitified by sqrt(2) to get actual max for 2d 75 74 index_model = (self.qmin <= radius) & (radius <= self.qmax) 76 index_model = index_model &self.data.mask77 index_model = index_model &np.isfinite(self.data.data)75 index_model &= self.data.mask 76 index_model &= np.isfinite(self.data.data) 78 77 79 78 if self.smearer is not None: … … 101 100 elapsed = time.time() - self.starttime 102 101 self.complete(image=output, 103 104 105 106 107 108 109 110 111 112 113 114 115 116 102 data=self.data, 103 page_id=self.page_id, 104 model=self.model, 105 state=self.state, 106 toggle_mode_on=self.toggle_mode_on, 107 elapsed=elapsed, 108 index=index_model, 109 fid=self.fid, 110 qmin=self.qmin, 111 qmax=self.qmax, 112 weight=self.weight, 113 #qstep=self.qstep, 114 update_chisqr=self.update_chisqr, 115 source=self.source) 117 116 118 117 … … 138 137 worktime=0.01, 139 138 exception_handler=None, 140 139 ): 141 140 """ 142 141 """ … … 193 192 * unsmeared_output[first_bin:last_bin+1]\ 194 193 / output[first_bin:last_bin+1] 195 unsmeared_output =unsmeared_output[index]196 unsmeared_data =unsmeared_data[index]197 unsmeared_error =unsmeared_error194 unsmeared_output = unsmeared_output[index] 195 unsmeared_data = unsmeared_data[index] 196 unsmeared_error = unsmeared_error 198 197 else: 199 198 output[index] = self.model.evalDistribution(self.data.x[index]) … … 243 242 class CalcCommandline: 244 243 def __init__(self, n=20000): 245 #print thread.get_ident()246 from sas.models.CylinderModel import CylinderModel 247 248 model = CylinderModel()249 250 251 print model.runXY([0.01, 0.02])244 #print(thread.get_ident()) 245 246 from sasmodels.sasview_model import _make_standard_model 247 cylinder = _make_standard_model('cylinder') 248 model = cylinder() 249 250 print(model.runXY([0.01, 0.02])) 252 251 253 252 qmax = 0.01 … … 258 257 y = numpy.arange(-qmax, qmax+qstep*0.01, qstep) 259 258 260 261 259 calc_thread_2D = Calc2D(x, y, None, model.clone(),None, 262 260 -qmax, qmax,qstep, 263 264 265 261 completefn=self.complete, 262 updatefn=self.update , 263 yieldtime=0.0) 266 264 267 265 calc_thread_2D.queue() … … 272 270 273 271 def update(self,output): 274 print "update"272 print("update") 275 273 276 274 def complete(self, image, data, model, elapsed, qmin, qmax,index, qstep ): 277 print "complete"275 print("complete") 278 276 self.done = True 279 277 -
src/sas/sasgui/perspectives/fitting/report_dialog.py
r7432acb r78312f7 38 38 # number of images of plot 39 39 self.nimages = len(self.report_list[2]) 40 41 if self.report_list[2] is not None: 42 # put image path in the report string 43 if len(self.report_list[2]) == 1: 44 self.report_html = self.report_list[0] % \ 45 "memory:img_fit0.png" 46 elif len(self.report_list[2]) == 2: 47 self.report_html = self.report_list[0] % \ 48 ("memory:img_fit0.png", 49 "memory:img_fit1.png") 50 # allows up to three images 51 else: 52 self.report_html = self.report_list[0] % \ 53 ("memory:img_fit0.png", 54 "memory:img_fit1.png", 55 "memory:img_fit2.png") 56 else: 57 self.report_html = self.report_list[0] 40 self.report_html = self.report_list[0] 58 41 # layout 59 42 self._setup_layout() … … 105 88 elif self.nimages == 3: 106 89 html = report_frame % (str(pic_fname[0]), str(pic_fname[1]), 107 90 str(pic_fname[2])) 108 91 109 92 # make/open file in case of absence … … 118 101 #Windows 119 102 os.startfile(str(fName)) 120 except :103 except Exception: 121 104 try: 122 105 #Mac 123 106 os.system("open %s" % fName) 124 except :107 except Exception: 125 108 #DO not open 126 109 pass -
src/sas/sasgui/perspectives/fitting/simfitpage.py
ra9f9ca4 r69363c7 2 2 Simultaneous or Batch fit page 3 3 """ 4 # Note that this is used for both Simultaneous/Constrained fit AND for 4 # Note that this is used for both Simultaneous/Constrained fit AND for 5 5 # combined batch fit. This is done through setting of the batch_on parameter. 6 # There are the a half dozen or so places where an if statement is used as in 6 # There are the a half dozen or so places where an if statement is used as in 7 7 # if not batch_on: 8 8 # xxxx … … 11 11 # This is just wrong but dont have time to fix this go. Proper approach would be 12 12 # to strip all parts of the code that depend on batch_on and create the top 13 # level class from which a contrained/simultaneous fit page and a combined 13 # level class from which a contrained/simultaneous fit page and a combined 14 14 # batch page inherit. 15 15 # … … 23 23 from wx.lib.scrolledpanel import ScrolledPanel 24 24 25 from sas.sascalc.fit.pagestate import SimFitPageState 25 26 from sas.sasgui.guiframe.events import StatusEvent, PanelOnFocusEvent 26 27 from sas.sasgui.guiframe.panel_base import PanelBase … … 60 61 61 62 return fittable_param 62 63 63 64 64 class SimultaneousFitPage(ScrolledPanel, PanelBase): … … 157 157 return self.state 158 158 159 def load_from_save_state(self, sim_state): 160 """ 161 Load in a simultaneous/constrained fit from a save state 162 :param fit: Fitpanel object 163 :return: None 164 """ 165 model_map = {} 166 # Process each model and associate old M# with new M# 167 i = 0 168 for model in self.model_list: 169 model_id = self._format_id(model[1].keys()[0]) 170 for saved_model in sim_state.model_list: 171 save_id = saved_model.pop('name') 172 saved_model['name'] = save_id 173 save_id = self._format_id(save_id) 174 if save_id == model_id: 175 model_map[saved_model.pop('fit_page_source')] = \ 176 model[3].name 177 check = bool(saved_model.pop('checked')) 178 self.model_list[i][0].SetValue(check) 179 break 180 i += 1 181 182 self.check_model_name(None) 183 184 if len(sim_state.constraints_list) > 0: 185 self.hide_constraint.SetValue(False) 186 self.show_constraint.SetValue(True) 187 self._display_constraint(None) 188 189 for index, item in enumerate(sim_state.constraints_list): 190 model_cbox = item.pop('model_cbox') 191 if model_cbox != "": 192 constraint_value = item.pop('constraint') 193 param = item.pop('param_cbox') 194 equality = item.pop('egal_txt') 195 for key, value in model_map.iteritems(): 196 model_cbox.replace(key, value) 197 constraint_value.replace(key, value) 198 199 self.constraints_list[index][0].SetValue(model_cbox) 200 self._on_select_model(None) 201 self.constraints_list[index][1].SetValue(param) 202 self.constraints_list[index][2].SetLabel(equality) 203 self.constraints_list[index][3].SetValue(constraint_value) 204 self._on_add_constraint(None) 205 self._manager.sim_page = self 206 207 def _format_id(self, original_id): 208 original_id = original_id.rstrip('1234567890.') 209 new_id_list = original_id.split() 210 new_id = ' '.join(new_id_list) 211 return new_id 212 213 214 159 215 def draw_page(self): 160 216 """ 161 217 Construct the Simultaneous/Constrained fit page. fills the first 162 region (sizer1) with the list of available fit page pairs of data 218 region (sizer1) with the list of available fit page pairs of data 163 219 and models. Then fills sizer2 with the checkbox for adding 164 220 constraints, and finally fills sizer3 with the fit button and … … 1043 1099 cbox.Append(name, value) 1044 1100 cbox.SetStringSelection(selected) 1045 1046 1047 class SimFitPageState:1048 """1049 State of the simultaneous fit page for saving purposes1050 """1051 1052 def __init__(self):1053 # Sim Fit Page Number1054 self.fit_page_no = None1055 # Select all data1056 self.select_all = False1057 # Data sets sent to fit page1058 self.model_list = []1059 # Data sets to be fit1060 self.model_to_fit = []1061 # Number of constraints1062 self.no_constraint = 01063 # Dictionary of constraints1064 self.constraint_dict = {}1065 # List of constraints1066 self.constraints_list = []1067 1068 def load_from_save_state(self, fit):1069 """1070 Load in a simultaneous/constrained fit from a save state1071 :param fit: Fitpanel object1072 :return: None1073 """1074 1075 model_map = {}1076 if fit.fit_panel.sim_page is None:1077 fit.fit_panel.add_sim_page()1078 sim_page = fit.fit_panel.sim_page1079 1080 # Process each model and associate old M# with new M#1081 i = 01082 for model in sim_page.model_list:1083 model_id = self._format_id(model[1].keys()[0])1084 for saved_model in self.model_list:1085 save_id = saved_model.pop('name')1086 saved_model['name'] = save_id1087 save_id = self._format_id(save_id)1088 if save_id == model_id:1089 model_map[saved_model.pop('fit_page_source')] = \1090 model[3].name1091 check = bool(saved_model.pop('checked'))1092 sim_page.model_list[i][0].SetValue(check)1093 break1094 i += 11095 sim_page.check_model_name(None)1096 1097 if len(self.constraints_list) > 0:1098 sim_page.hide_constraint.SetValue(False)1099 sim_page.show_constraint.SetValue(True)1100 sim_page._display_constraint(None)1101 1102 for index, item in enumerate(self.constraints_list):1103 model_cbox = item.pop('model_cbox')1104 if model_cbox != "":1105 constraint_value = item.pop('constraint')1106 param = item.pop('param_cbox')1107 equality = item.pop('egal_txt')1108 for key, value in model_map.iteritems():1109 model_cbox.replace(key, value)1110 constraint_value.replace(key, value)1111 1112 sim_page.constraints_list[index][0].SetValue(model_cbox)1113 sim_page._on_select_model(None)1114 sim_page.constraints_list[index][1].SetValue(param)1115 sim_page.constraints_list[index][2].SetLabel(equality)1116 sim_page.constraints_list[index][3].SetValue(constraint_value)1117 sim_page._on_add_constraint(None)1118 sim_page._manager.sim_page = sim_page1119 1120 def _format_id(self, original_id):1121 original_id = original_id.rstrip('1234567890.')1122 new_id_list = original_id.split()1123 new_id = ' '.join(new_id_list)1124 return new_id
Note: See TracChangeset
for help on using the changeset viewer.