Changeset c79304b in sasview
- Timestamp:
- Oct 1, 2016 3:57:20 PM (8 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, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
- Children:
- b61bd57
- Parents:
- 9bbc074 (diff), a235f715 (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. - git-author:
- Andrew Jackson <andrew.jackson@…> (10/01/16 15:57:20)
- git-committer:
- GitHub <noreply@…> (10/01/16 15:57:20)
- Files:
-
- 2 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/sascalc/dataloader/readers/anton_paar_saxs_reader.py
r80c5d46 ra235f715 45 45 output = None 46 46 47 def __init__(self):47 def reset_state(self): 48 48 self.current_dataset = Data1D(np.empty(0), np.empty(0), 49 49 np.empty(0), np.empty(0)) … … 72 72 73 73 ## Reinitialize the class when loading a new data file to reset all class variables 74 self. __init__()74 self.reset_state() 75 75 ## Check that the file exists 76 76 if os.path.isfile(filename): … … 84 84 self.raw_data = buff.splitlines() 85 85 self.read_data() 86 xml_intermediate = self.raw_data[self.upper:]87 xml = ''.join(xml_intermediate)88 self.set_xml_file(xml)89 86 return self.output 90 87 … … 100 97 self.lower = 5 101 98 self.upper = self.lower + self.data_points 102 self.detector.distance = float(line4[1]) 99 self.source.radiation = 'x-ray' 100 normal = float(line4[3]) 103 101 self.current_dataset.source.radiation = "x-ray" 104 102 self.current_dataset.source.name = "Anton Paar SAXSess Instrument" 105 103 self.current_dataset.source.wavelength = float(line4[4]) 106 normal = line4[3] 104 xvals = [] 105 yvals = [] 106 dyvals = [] 107 107 for i in range(self.lower, self.upper): 108 index = i - self.lower 108 109 data = self.raw_data[i].split() 109 x_val = [float(data[0])] 110 y_val = [float(data[1])] 111 dy_val = [float(data[2])] 112 self.current_dataset.x = np.append(self.current_dataset.x, x_val) 113 self.current_dataset.y = np.append(self.current_dataset.y, y_val) 114 self.current_dataset.dy = np.append(self.current_dataset.dy, dy_val) 115 self.current_dataset.xaxis("Q (%s)" % (q_unit), q_unit) 116 self.current_dataset.yaxis("Intensity (%s)" % (i_unit), i_unit) 117 self.current_dataset.detector.append(self.detector) 110 xvals.insert(index, normal * float(data[0])) 111 yvals.insert(index, normal * float(data[1])) 112 dyvals.insert(index, normal * float(data[2])) 113 self.current_dataset.x = np.append(self.current_dataset.x, xvals) 114 self.current_dataset.y = np.append(self.current_dataset.y, yvals) 115 self.current_dataset.dy = np.append(self.current_dataset.dy, dyvals) 116 if self.data_points != self.current_dataset.x.size: 117 self.errors.add("Not all data was loaded properly.") 118 if self.current_dataset.dx.size != self.current_dataset.x.size: 119 dxvals = np.zeros(self.current_dataset.x.size) 120 self.current_dataset.dx = dxvals 121 if self.current_dataset.x.size != self.current_dataset.y.size: 122 self.errors.add("The x and y data sets are not the same size.") 123 if self.current_dataset.y.size != self.current_dataset.dy.size: 124 self.errors.add("The y and dy datasets are not the same size.") 125 self.current_dataset.errors = self.errors 126 self.current_dataset.xaxis("Q", q_unit) 127 self.current_dataset.yaxis("Intensity", i_unit) 128 xml_intermediate = self.raw_data[self.upper:] 129 xml = ''.join(xml_intermediate) 130 self.set_xml_string(xml) 131 dom = self.xmlroot.xpath('/fileinfo') 132 self._parse_child(dom) 118 133 self.output.append(self.current_dataset) 134 135 def _parse_child(self, dom, parent=''): 136 """ 137 Recursive method for stepping through the embedded XML 138 :param dom: XML node with or without children 139 """ 140 for node in dom: 141 tagname = node.tag 142 value = node.text 143 attr = node.attrib 144 key = attr.get("key", '') 145 if len(node.getchildren()) > 1: 146 self._parse_child(node, key) 147 if key == "SampleDetector": 148 self.current_dataset.detector.append(self.detector) 149 self.detector = Detector() 150 else: 151 if key == "value": 152 if parent == "Wavelength": 153 self.current_dataset.source.wavelength = value 154 elif parent == "SampleDetector": 155 self.detector.distance = value 156 elif parent == "Temperature": 157 self.current_dataset.sample.temperature = value 158 elif parent == "CounterSlitLength": 159 self.detector.slit_length = value 160 elif key == "unit": 161 value = value.replace("_", "") 162 if parent == "Wavelength": 163 self.current_dataset.source.wavelength_unit = value 164 elif parent == "SampleDetector": 165 self.detector.distance_unit = value 166 elif parent == "X": 167 self.current_dataset.xaxis(self.current_dataset._xaxis, value) 168 elif parent == "Y": 169 self.current_dataset.yaxis(self.current_dataset._yaxis, value) 170 elif parent == "Temperature": 171 self.current_dataset.sample.temperature_unit = value 172 elif parent == "CounterSlitLength": 173 self.detector.slit_length_unit = value 174 elif key == "quantity": 175 if parent == "X": 176 self.current_dataset.xaxis(value, self.current_dataset._xunit) 177 elif parent == "Y": 178 self.current_dataset.yaxis(value, self.current_dataset._yunit) -
src/sas/sascalc/dataloader/readers/xml_reader.py
rb699768 ra235f715 70 70 self.xmldoc = etree.parse(self.xml, parser=PARSER) 71 71 self.xmlroot = self.xmldoc.getroot() 72 except etree.XMLSyntaxError as xml_error: 73 logging.info(xml_error) 74 except Exception: 75 self.xml = None 76 self.xmldoc = None 77 self.xmlroot = None 78 79 def set_xml_string(self, tag_soup): 80 """ 81 Set an XML string as the working XML. 82 83 :param tag_soup: XML formatted string 84 """ 85 try: 86 self.xml = tag_soup 87 self.xmldoc = tag_soup 88 self.xmlroot = etree.fromstring(tag_soup) 72 89 except etree.XMLSyntaxError as xml_error: 73 90 logging.info(xml_error) -
docs/sphinx-docs/source/user/sasgui/perspectives/invariant/invariant_help.rst
r49148bb r9bbc074 4 4 .. by S King, ISIS, during SasView CodeCamp-III in Feb 2015. 5 5 6 Invariant Calculation Perspective7 ===================== ============6 Invariant Calculation 7 ===================== 8 8 9 9 Description … … 19 19 .. image:: image001.gif 20 20 21 where *g = Q* for pinhole geometry (SAS) and *g = Qv*(the slit height) for21 where *g = q* for pinhole geometry (SAS) and *g = q*\ :sub:`v` (the slit height) for 22 22 slit geometry (USAS). 23 23 … … 45 45 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 46 46 47 Using the perspective48 --------------------- 47 Using invariant analysis 48 ------------------------ 49 49 50 50 1) Select *Invariant* from the *Analysis* menu on the SasView toolbar. … … 53 53 54 54 3) Select a dataset and use the *Send To* button on the *Data Explorer* to load 55 the dataset into the *Invariant* p erspective.55 the dataset into the *Invariant* panel. 56 56 57 4) Use the *Customised Input* boxes on the *Invariant* p erspectiveto subtract57 4) Use the *Customised Input* boxes on the *Invariant* panel to subtract 58 58 any background, specify the contrast (i.e. difference in SLDs - this must be 59 59 specified for the eventual value of Q*\ to be on an absolute scale), or to … … 73 73 74 74 8) If the value of Q*\ calculated with the extrapolated regions is invalid, a 75 red warning will appear at the top of the *Invariant* p erspective panel.75 red warning will appear at the top of the *Invariant* panel. 76 76 77 77 The details of the calculation are available by clicking the *Details* -
docs/sphinx-docs/source/user/user.rst
r5a71761 r20a3c55 14 14 15 15 Working with SasView <working> 16 17 Computations with GPU <gpu_computations> -
sasview/local_config.py
rd85c194 r9bbc074 82 82 _corner_image = os.path.join(icon_path, "angles_flat.png") 83 83 _welcome_image = os.path.join(icon_path, "SVwelcome.png") 84 _copyright = "(c) 2009 - 201 3, UTK, UMD, NIST, ORNL, ISIS, ESS and ILL"84 _copyright = "(c) 2009 - 2016, UTK, UMD, NIST, ORNL, ISIS, ESS and ILL" 85 85 86 86 -
sasview/setup_exe.py
r525aaa2 r9bbc074 165 165 self.version = local_config.__version__ 166 166 self.company_name = "SasView.org" 167 self.copyright = "copyright 2009 - 201 3"167 self.copyright = "copyright 2009 - 2016" 168 168 self.name = "SasView" 169 169 -
src/sas/sasgui/guiframe/utils.py
rd85c194 ra0373d5 46 46 return flag 47 47 48 48 49 def check_int(item): 50 """ 51 :param item: txtcrtl containing a value 52 """ 53 flag = True 54 try: 55 mini = int(item.GetValue()) 56 item.SetBackgroundColour(wx.WHITE) 57 item.Refresh() 58 except: 59 flag = False 60 item.SetBackgroundColour("pink") 61 item.Refresh() 62 return flag 63 64 49 65 class PanelMenu(wx.Menu): 50 66 """ -
src/sas/sasgui/perspectives/fitting/basepage.py
ree4b3cb r6c382da 17 17 from wx.lib.scrolledpanel import ScrolledPanel 18 18 19 import sasmodels.sasview_model 19 from sasmodels.weights import MODELS as POLYDISPERSITY_MODELS 20 20 21 from sas.sasgui.guiframe.panel_base import PanelBase 21 from sas.sasgui.guiframe.utils import format_number, check_float, IdList 22 from sas.sasgui.guiframe.utils import format_number, check_float, IdList, check_int 22 23 from sas.sasgui.guiframe.events import PanelOnFocusEvent 23 24 from sas.sasgui.guiframe.events import StatusEvent … … 626 627 self.disp_help_bt.Bind(wx.EVT_BUTTON, self.on_pd_help_clicked, 627 628 id=self.disp_help_bt.GetId()) 628 self.disp_help_bt.SetToolTipString("Help s for Polydispersion.")629 self.disp_help_bt.SetToolTipString("Help for polydispersion.") 629 630 630 631 self.Bind(wx.EVT_RADIOBUTTON, self._set_dipers_Param, … … 932 933 if len(self._disp_obj_dict) > 0: 933 934 for k, v in self._disp_obj_dict.iteritems(): 934 self.state._disp_obj_dict[k] = v 935 self.state._disp_obj_dict[k] = v.type 935 936 936 937 self.state.values = copy.deepcopy(self.values) … … 1009 1010 if len(self._disp_obj_dict) > 0: 1010 1011 for k, v in self._disp_obj_dict.iteritems(): 1011 self.state._disp_obj_dict[k] = v 1012 self.state._disp_obj_dict[k] = v.type 1012 1013 1013 1014 self.state.values = copy.deepcopy(self.values) … … 1123 1124 state.disp_cb_dict[item]) 1124 1125 # Create the dispersion objects 1125 from sas.models.dispersion_models import ArrayDispersion 1126 disp_model = ArrayDispersion() 1126 disp_model = POLYDISPERSITY_MODELS['array']() 1127 1127 if hasattr(state, "values") and \ 1128 1128 self.disp_cb_dict[item].GetValue() == True: … … 1379 1379 self.weights = copy.deepcopy(state.weights) 1380 1380 1381 for key, disp in state._disp_obj_dict.iteritems(): 1382 # From saved file, disp_model can not be sent in model obj. 1383 # it will be sent as a string here, then converted to model object. 1384 if disp.__class__.__name__ == 'str': 1385 disp_model = None 1386 com_str = "from sasmodels.weights " 1387 com_str += "import %s as disp_func \ndisp_model = disp_func()" 1388 exec com_str % disp 1389 else: 1390 disp_model = disp 1381 for key, disp_type in state._disp_obj_dict.iteritems(): 1382 #disp_model = disp 1383 disp_model = POLYDISPERSITY_MODELS[disp_type]() 1391 1384 self._disp_obj_dict[key] = disp_model 1392 1385 param_name = key.split('.')[0] … … 2281 2274 continue 2282 2275 2283 name = str(item[1]) 2284 if name.endswith(".npts") or name.endswith(".nsigmas"): 2276 value_ctrl = item[2] 2277 if not value_ctrl.IsEnabled(): 2278 # ArrayDispersion disables PD, Min, Max, Npts, Nsigs 2285 2279 continue 2286 2280 2287 # Check that min, max and value are floats 2288 value_ctrl, min_ctrl, max_ctrl = item[2], item[5], item[6] 2289 min_str = min_ctrl.GetValue().strip() 2290 max_str = max_ctrl.GetValue().strip() 2281 name = item[1] 2291 2282 value_str = value_ctrl.GetValue().strip() 2292 validity = check_float(value_ctrl) 2293 if min_str != "": 2294 validity = validity and check_float(min_ctrl) 2295 if max_str != "": 2296 validity = validity and check_float(max_ctrl) 2297 if not validity: 2298 continue 2299 2300 # Check that min is less than max 2301 low = -numpy.inf if min_str == "" else float(min_str) 2302 high = numpy.inf if max_str == "" else float(max_str) 2303 if high < low: 2304 min_ctrl.SetBackgroundColour("pink") 2305 min_ctrl.Refresh() 2306 max_ctrl.SetBackgroundColour("pink") 2307 max_ctrl.Refresh() 2308 #msg = "Invalid fit range for %s: min must be smaller than max"%name 2309 #wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 2310 continue 2311 2312 # Force value between min and max 2313 value = float(value_str) 2314 if value < low: 2315 value = low 2316 value_ctrl.SetValue(format_number(value)) 2317 elif value > high: 2318 value = high 2319 value_ctrl.SetValue(format_number(value)) 2283 if name.endswith(".npts"): 2284 validity = check_int(value_ctrl) 2285 if not validity: 2286 continue 2287 value = int(value_str) 2288 2289 elif name.endswith(".nsigmas"): 2290 validity = check_float(value_ctrl) 2291 if not validity: 2292 continue 2293 value = float(value_str) 2294 2295 else: # value or polydispersity 2296 2297 # Check that min, max and value are floats 2298 min_ctrl, max_ctrl = item[5], item[6] 2299 min_str = min_ctrl.GetValue().strip() 2300 max_str = max_ctrl.GetValue().strip() 2301 validity = check_float(value_ctrl) 2302 if min_str != "": 2303 validity = validity and check_float(min_ctrl) 2304 if max_str != "": 2305 validity = validity and check_float(max_ctrl) 2306 if not validity: 2307 continue 2308 2309 # Check that min is less than max 2310 low = -numpy.inf if min_str == "" else float(min_str) 2311 high = numpy.inf if max_str == "" else float(max_str) 2312 if high < low: 2313 min_ctrl.SetBackgroundColour("pink") 2314 min_ctrl.Refresh() 2315 max_ctrl.SetBackgroundColour("pink") 2316 max_ctrl.Refresh() 2317 #msg = "Invalid fit range for %s: min must be smaller than max"%name 2318 #wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 2319 continue 2320 2321 # Force value between min and max 2322 value = float(value_str) 2323 if value < low: 2324 value = low 2325 value_ctrl.SetValue(format_number(value)) 2326 elif value > high: 2327 value = high 2328 value_ctrl.SetValue(format_number(value)) 2329 2330 if name not in self.model.details.keys(): 2331 self.model.details[name] = ["", None, None] 2332 old_low, old_high = self.model.details[name][1:3] 2333 if old_low != low or old_high != high: 2334 # The configuration has changed but it won't change the 2335 # computed curve so no need to set is_modified to True 2336 #is_modified = True 2337 self.model.details[name][1:3] = low, high 2320 2338 2321 2339 # Update value in model if it has changed … … 2323 2341 self.model.setParam(name, value) 2324 2342 is_modified = True 2325 2326 if name not in self.model.details.keys():2327 self.model.details[name] = ["", None, None]2328 old_low, old_high = self.model.details[name][1:3]2329 if old_low != low or old_high != high:2330 # The configuration has changed but it won't change the2331 # computed curve so no need to set is_modified to True2332 #is_modified = True2333 self.model.details[name][1:3] = low, high2334 2343 2335 2344 return is_modified … … 2504 2513 self._disp_obj_dict[name1] = disp_model 2505 2514 self.model.set_dispersion(param_name, disp_model) 2506 self.state._disp_obj_dict[name1] = disp_model 2515 self.state._disp_obj_dict[name1] = disp_model.type 2507 2516 2508 2517 value1 = str(format_number(self.model.getParam(name1), True)) … … 2527 2536 item[0].Enable() 2528 2537 item[2].Enable() 2538 item[3].Show(True) 2539 item[4].Show(True) 2529 2540 item[5].Enable() 2530 2541 item[6].Enable() … … 2619 2630 self._disp_obj_dict[name] = disp 2620 2631 self.model.set_dispersion(name.split('.')[0], disp) 2621 self.state._disp_obj_dict[name] = disp 2632 self.state._disp_obj_dict[name] = disp.type 2622 2633 self.values[name] = values 2623 2634 self.weights[name] = weights … … 2687 2698 :param disp_function: dispersion distr. function 2688 2699 """ 2689 # List of the poly_model name in the combobox2690 list = ["RectangleDispersion", "ArrayDispersion",2691 "LogNormalDispersion", "GaussianDispersion",2692 "SchulzDispersion"]2693 2694 2700 # Find the selection 2695 try: 2696 selection = list.index(disp_func.__class__.__name__) 2697 return selection 2698 except: 2699 return 3 2701 if disp_func is not None: 2702 try: 2703 return POLYDISPERSITY_MODELS.values().index(disp_func.__class__) 2704 except ValueError: 2705 pass # Fall through to default class 2706 return POLYDISPERSITY_MODELS.keys().index('gaussian') 2700 2707 2701 2708 def on_reset_clicked(self, event): … … 3284 3291 pd = content[name][1] 3285 3292 if name.count('.') > 0: 3293 # If this is parameter.width, then pd may be a floating 3294 # point value or it may be an array distribution. 3295 # Nothing to do for parameter.npts or parameter.nsigmas. 3286 3296 try: 3287 3297 float(pd) 3288 except: 3298 if name.endswith('.npts'): 3299 pd = int(pd) 3300 except Exception: 3289 3301 #continue 3290 3302 if not pd and pd != '': … … 3294 3306 # Only array func has pd == '' case. 3295 3307 item[2].Enable(False) 3308 else: 3309 item[2].Enable(True) 3296 3310 if item[2].__class__.__name__ == "ComboBox": 3297 3311 if content[name][1] in self.model.fun_list: … … 3320 3334 pd = value[0] 3321 3335 if name.count('.') > 0: 3336 # If this is parameter.width, then pd may be a floating 3337 # point value or it may be an array distribution. 3338 # Nothing to do for parameter.npts or parameter.nsigmas. 3322 3339 try: 3323 3340 pd = float(pd) 3341 if name.endswith('.npts'): 3342 pd = int(pd) 3324 3343 except: 3325 3344 #continue … … 3330 3349 # Only array func has pd == '' case. 3331 3350 item[2].Enable(False) 3351 else: 3352 item[2].Enable(True) 3332 3353 if item[2].__class__.__name__ == "ComboBox": 3333 3354 if value[0] in self.model.fun_list: … … 3349 3370 Helps get paste for poly function 3350 3371 3351 :param item: Gui param items 3352 :param value: the values for parameter ctrols 3353 """ 3354 is_array = False 3355 if len(value[1]) > 0: 3356 # Only for dispersion func.s 3357 try: 3358 item[7].SetValue(value[1]) 3359 selection = item[7].GetCurrentSelection() 3360 name = item[7].Name 3361 param_name = name.split('.')[0] 3362 dispersity = item[7].GetClientData(selection) 3363 disp_model = dispersity() 3364 # Only for array disp 3365 try: 3366 pd_vals = numpy.array(value[2]) 3367 pd_weights = numpy.array(value[3]) 3368 if len(pd_vals) > 0 and len(pd_vals) > 0: 3369 if len(pd_vals) == len(pd_weights): 3370 self._set_disp_array_cb(item=item) 3371 self._set_array_disp_model(name=name, 3372 disp=disp_model, 3373 values=pd_vals, 3374 weights=pd_weights) 3375 is_array = True 3376 except Exception: 3377 logging.error(traceback.format_exc()) 3378 if not is_array: 3379 self._disp_obj_dict[name] = disp_model 3380 self.model.set_dispersion(name, 3381 disp_model) 3382 self.state._disp_obj_dict[name] = \ 3383 disp_model 3384 self.model.set_dispersion(param_name, disp_model) 3385 self.state.values = self.values 3386 self.state.weights = self.weights 3387 self.model._persistency_dict[param_name] = \ 3388 [self.state.values, 3389 self.state.weights] 3390 3391 except Exception: 3392 logging.error(traceback.format_exc()) 3393 print "Error in BasePage._paste_poly_help: %s" % \ 3394 sys.exc_info()[1] 3395 3396 def _set_disp_array_cb(self, item): 3372 *item* is the parameter name 3373 3374 *value* depends on which parameter is being processed, and whether it 3375 has array polydispersity. 3376 3377 For parameters without array polydispersity: 3378 3379 parameter => ['FLOAT', ''] 3380 parameter.width => ['FLOAT', 'DISTRIBUTION', ''] 3381 parameter.npts => ['FLOAT', ''] 3382 parameter.nsigmas => ['FLOAT', ''] 3383 3384 For parameters with array polydispersity: 3385 3386 parameter => ['FLOAT', ''] 3387 parameter.width => ['FILENAME', 'array', [x1, ...], [w1, ...]] 3388 parameter.npts => ['FLOAT', ''] 3389 parameter.nsigmas => ['FLOAT', ''] 3390 """ 3391 # Do nothing if not setting polydispersity 3392 if len(value[1]) == 0: 3393 return 3394 3395 try: 3396 name = item[7].Name 3397 param_name = name.split('.')[0] 3398 item[7].SetValue(value[1]) 3399 selection = item[7].GetCurrentSelection() 3400 dispersity = item[7].GetClientData(selection) 3401 disp_model = dispersity() 3402 3403 if value[1] == 'array': 3404 pd_vals = numpy.array(value[2]) 3405 pd_weights = numpy.array(value[3]) 3406 if len(pd_vals) == 0 or len(pd_vals) != len(pd_weights): 3407 msg = ("bad array distribution parameters for %s" 3408 % param_name) 3409 raise ValueError(msg) 3410 self._set_disp_cb(True, item=item) 3411 self._set_array_disp_model(name=name, 3412 disp=disp_model, 3413 values=pd_vals, 3414 weights=pd_weights) 3415 else: 3416 self._set_disp_cb(False, item=item) 3417 self._disp_obj_dict[name] = disp_model 3418 self.model.set_dispersion(param_name, disp_model) 3419 self.state._disp_obj_dict[name] = disp_model.type 3420 # TODO: It's not an array, why update values and weights? 3421 self.model._persistency_dict[param_name] = \ 3422 [self.values, self.weights] 3423 self.state.values = self.values 3424 self.state.weights = self.weights 3425 3426 except Exception: 3427 logging.error(traceback.format_exc()) 3428 print "Error in BasePage._paste_poly_help: %s" % \ 3429 sys.exc_info()[1] 3430 3431 def _set_disp_cb(self, isarray, item): 3397 3432 """ 3398 3433 Set cb for array disp 3399 3434 """ 3400 item[0].SetValue(False) 3401 item[0].Enable(False) 3402 item[2].Enable(False) 3403 item[3].Show(False) 3404 item[4].Show(False) 3405 item[5].SetValue('') 3406 item[5].Enable(False) 3407 item[6].SetValue('') 3408 item[6].Enable(False) 3435 if isarray: 3436 item[0].SetValue(False) 3437 item[0].Enable(False) 3438 item[2].Enable(False) 3439 item[3].Show(False) 3440 item[4].Show(False) 3441 item[5].SetValue('') 3442 item[5].Enable(False) 3443 item[6].SetValue('') 3444 item[6].Enable(False) 3445 else: 3446 item[0].Enable() 3447 item[2].Enable() 3448 item[3].Show(True) 3449 item[4].Show(True) 3450 item[5].Enable() 3451 item[6].Enable() 3409 3452 3410 3453 def update_pinhole_smear(self): -
src/sas/sasgui/perspectives/fitting/fitpage.py
ree4b3cb r6c382da 10 10 import math 11 11 import time 12 import traceback 12 13 13 14 from sasmodels.weights import MODELS as POLYDISPERSITY_MODELS … … 2058 2059 msg = "Error: This model state has missing or outdated " 2059 2060 msg += "information.\n" 2060 msg += "%s" % (sys.exc_value)2061 msg += traceback.format_exc() 2061 2062 wx.PostEvent(self._manager.parent, 2062 2063 StatusEvent(status=msg, info="error")) -
src/sas/sasgui/perspectives/fitting/media/plugin.rst
r05829fb re925f61 1 1 .. _Writing_a_Plugin: 2 2 3 Writing a Plugin 4 ================ 5 6 Users can write their own models and save it to the the SasView 3 Writing a Plugin Model 4 ====================== 5 6 Overview 7 ^^^^^^^^ 8 9 You can write your own model and save it to the the SasView 7 10 *plugin_models* folder 8 11 9 *C:\\Users\\[username]\\.sasview\\plugin_models* -(on Windows)12 *C:\\Users\\[username]\\.sasview\\plugin_models* (on Windows) 10 13 11 14 The next time SasView is started it will compile the plugin and add 12 it to the list of *Customized Models* . It is recommended that an15 it to the list of *Customized Models* in a FitPage. It is recommended that an 13 16 existing model be used as a template. 14 15 This page was originally written by our MOST experienced developers,16 but has subsequently been edited by our LEAST experienced developer who felt17 some instructions could have been clearer, and learnt one or two things that18 were missing altogether! But they succeeded in converting a model that passed19 testing, so there is no reason why you should not be able to do the same.20 17 21 18 SasView has three ways of writing models: … … 29 26 `cylinder.c <https://github.com/SasView/sasmodels/blob/master/sasmodels/models/cylinder.c>`_ 30 27 31 Many models are available for download from the 32 `model marketplace <http://marketplace.sasview.org/>`_. 33 34 The builtin modules are available in the *sasmodels-data/models* subdirectory 35 of the sasview distribution. On Windows, this will be something like 36 *C:\Program Files (x86)\SasView\models*. On MacOSX, these will be within 28 The built-in modules are available in the *sasmodels-data\\models* subdirectory 29 of your SasView installation folder. On Windows, this will be something like 30 *C:\\Program Files (x86)\\SasView\\sasmodels-data\\models*. On Mac OSX, these will be within 37 31 the application bundle as 38 32 */Applications/SasView 4.0.app/Contents/Resources/sasmodels-data/models*. 39 33 34 Other models are available for download from our 35 `Model Marketplace <http://marketplace.sasview.org/>`_. You can contribute your own models to the 36 Marketplace aswell. 37 40 38 Create New Model Files 41 39 ^^^^^^^^^^^^^^^^^^^^^^ 42 40 43 In the *~ /.sasview/plugin_models* directory, copy the appropriate files41 In the *~\\.sasview\\plugin_models* directory, copy the appropriate files 44 42 (using the examples above as templates) to mymodel.py (and mymodel.c, etc) 45 43 as required, where "mymodel" is the name for the model you are creating. … … 47 45 *Please follow these naming rules:* 48 46 49 - No capitalization and thus no CamelCase .50 - If necessary use underscore to separate (i.e. barbell not BarBell or47 - No capitalization and thus no CamelCase 48 - If necessary use underscore to separate words (i.e. barbell not BarBell or 51 49 broad_peak not BroadPeak) 52 - Do n't include âmodelâ in the name (i.e. barbell not BarBellModel)50 - Do not include âmodelâ in the name (i.e. barbell not BarBellModel) 53 51 54 52 55 53 Edit New Model Files 56 54 ^^^^^^^^^^^^^^^^^^^^ 55 56 Model Contents 57 .............. 57 58 58 59 The model interface definition is in the .py file. This file contains: … … 65 66 - without spaces (use underscores to separate words instead) 66 67 - without any capitalization or CamelCase 67 - without incorporating the word 'model'68 - without incorporating the word "model" 68 69 - examples: *barbell* **not** *BarBell*; *broad_peak* **not** *BroadPeak*; 69 70 *barbell* **not** *BarBellModel* … … 72 73 - this is the **title** string in the *.py* file 73 74 - this is a one or two line description of the model, which will appear 74 at the start of the model documentation and as a tooltip in the GUI75 at the start of the model documentation and as a tooltip in the SasView GUI 75 76 76 77 - a **short discription**: 77 78 - this is the **description** string in the *.py* file 78 79 - this is a medium length description which appears when you click 79 *Description* on the model fit page80 *Description* on the model FitPage 80 81 81 82 - a **parameter table**: … … 85 86 - this is ReStructuredText enclosed between the r""" and """ delimiters 86 87 at the top of the *.py* file 88 - what you write here is abstracted into the SasView help documentation 89 - this is what other users will refer to when they want to know what your model does; 90 so please be helpful! 87 91 88 92 - a **definition** of the model: … … 97 101 98 102 - a **plot** of the function, with a **figure caption**: 99 - this is automatically generated from thedefault parameters103 - this is automatically generated from your default parameters 100 104 101 105 - at least one **reference**: … … 107 111 - the *.py* file should also contain a comment identifying *who* 108 112 converted/created the model file 113 114 Models that do not conform to these requirements will *never* be incorporated 115 into the built-in library. 109 116 110 117 More complete documentation for the sasmodels package can be found at … … 170 177 171 178 The model should include a **formula** written using LaTeX markup. 172 The above example uses the *math* command to make a displayed equation. You179 The example above uses the *math* command to make a displayed equation. You 173 180 can also use *\$formula\$* for an inline formula. This is handy for defining 174 181 the relationship between the model parameters and formula variables, such 175 182 as the phrase "\$r\$ is the radius" used above. The live demo MathJax 176 183 page `<http://www.mathjax.org/>`_ is handy for checking that the equations 177 will look like you expect.184 will look like you intend. 178 185 179 186 Math layout uses the `amsmath <http://www.ams.org/publications/authors/tex/amslatex>`_ … … 207 214 208 215 name = "sphere" # optional: defaults to the filename without .py 216 209 217 title = "Spheres with uniform scattering length density" 218 210 219 description = """\ 211 220 P(q)=(scale/V)*[3V(sld-sld_solvent)*(sin(qr)-qr cos(qr)) … … 216 225 sld_solvent: the SLD of the solvent 217 226 """ 227 218 228 category = "shape:sphere" 229 219 230 single = True # optional: defaults to True 231 220 232 opencl = False # optional: defaults to False 233 221 234 structure_factor = False # optional: defaults to False 222 235 … … 229 242 **title = "short description"** is short description of the model which 230 243 is included after the model name in the automatically generated documentation. 231 The title can also be used for a tooltip , for example.244 The title can also be used for a tooltip. 232 245 233 246 **description = """doc string"""** is a longer description of the model. It 234 shows up when you press the "Description" button of the SasView fit page.247 shows up when you press the "Description" button of the SasView FitPage. 235 248 It should give a brief description of the equation and the parameters 236 249 without the need to read the entire model documentation. The triple quotes 237 250 allow you to write the description over multiple lines. Keep the lines 238 251 short since the GUI will wrap each one separately if they are too long. 239 **Make sure the parameter names in the description match the model definition .**252 **Make sure the parameter names in the description match the model definition!** 240 253 241 254 **category = "shape:sphere"** defines where the model will appear in the 242 255 model documentation. In this example, the model will appear alphabetically 243 in the list of spheroid models .256 in the list of spheroid models in the *Shape* category. 244 257 245 258 **single = True** indicates that the model can be run using single … … 275 288 ["radius", "Ang", 50, [0, inf], "volume", "Sphere radius"], 276 289 ] 277 # pylint: disable=bad-whitespace, line-too-long290 # pylint: enable=bad-whitespace, line-too-long 278 291 279 292 **parameters = [["name", "units", default, [min,max], "type", "tooltip"],...]** 280 defines the parameters form the model. 281 282 - **the order of the parameters in the definition will be the order of 283 the parameters in the user interface and the order of the parameters 284 in Iq(), Iqxy() and form_volume().** 285 286 - **scale and background parameters are implicit to all models, so 287 they do not need to be included in the parameter table** 288 289 - **"name"** is the name of the parameter shown on the fit screen 293 defines the parameters that form the model. 294 295 **Note: The order of the parameters in the definition will be the order of the 296 parameters in the user interface and the order of the parameters in Iq(), 297 Iqxy() and form_volume(). And** *scale* **and** *background* **parameters are 298 implicit to all models, so they do not need to be included in the parameter table.** 299 300 - **"name"** is the name of the parameter shown on the FitPage. 290 301 291 302 - parameter names should follow the mathematical convention; e.g., 292 *radius_core* not *core_radius*, or *sld_solvent* not *solvent_sld* 303 *radius_core* not *core_radius*, or *sld_solvent* not *solvent_sld*. 304 293 305 - model parameter names should be consistent between different models, 294 306 so *sld_solvent*, for example, should have exactly the same name 295 in every model 307 in every model. 308 296 309 - to see all the parameter names currently in use, type the following in the 297 310 python shell/editor under the Tools menu:: … … 301 314 302 315 *re-use* as many as possible!!! 316 303 317 - use "name[n]" for multiplicity parameters, where *n* is the name of 304 318 the parameter defining the number of shells/layers/segments, etc. … … 306 320 - **"units"** are displayed along with the parameter name 307 321 308 - every parameter should have units; use "None" if there are no units 322 - every parameter should have units; use "None" if there are no units. 323 309 324 - **sld's should be given in units of 1e-6/Ang^2, and not simply 310 325 1/Ang^2 to be consistent with the builtin models. Adjust your formulas 311 326 appropriately.** 327 312 328 - fancy units markup is available for some units, including:: 313 329 … … 322 338 and using negative exponents instead of the / operator, though 323 339 the unit name should use the / operator for consistency. 324 - p ost a message to the sasview developers list with the changes325 326 - **default** is the initial value for the parameter 340 - please post a message to the SasView developers mailing list with your changes. 341 342 - **default** is the initial value for the parameter. 327 343 328 344 - **the parameter default values are used to auto-generate a plot of 329 345 the model function in the documentation.** 330 346 331 - **[min, max]** are the lower and upper limits on the parameter 332 333 - lower and upper limits can be any number, or -inf or inf. 347 - **[min, max]** are the lower and upper limits on the parameter. 348 349 - lower and upper limits can be any number, or *-inf* or *inf*. 350 334 351 - the limits will show up as the default limits for the fit making it easy, 335 352 for example, to force the radius to always be greater than zero. 336 353 337 - **"type"** can be one of: "", "sld", "volume", or "orientation" 354 - **"type"** can be one of: "", "sld", "volume", or "orientation". 338 355 339 356 - "sld" parameters can have magnetic moments when fitting magnetic models; 340 357 depending on the spin polarization of the beam and the $q$ value being 341 358 examined, the effective sld for that material will be used to compute the 342 scattered intensity 359 scattered intensity. 360 343 361 - "volume" parameters are passed to Iq(), Iqxy(), and form_volume(), and 344 362 have polydispersity loops generated automatically. 363 345 364 - "orientation" parameters are only passed to Iqxy(), and have angular 346 365 dispersion. … … 380 399 ............. 381 400 382 For pure python models, define the Iq funtion::401 For pure python models, define the *Iq* function:: 383 402 384 403 import numpy as np … … 391 410 The parameters *par1, par2, ...* are the list of non-orientation parameters 392 411 to the model in the order that they appear in the parameter table. 393 **Note that the autogenerated model file uses *x* rather than *q*.**412 **Note that the autogenerated model file uses** *x* **rather than** *q*. 394 413 395 414 The *.py* file should import trigonometric and exponential functions from 396 numpy rather tha tfrom math. This lets us evaluate the model for the whole415 numpy rather than from math. This lets us evaluate the model for the whole 397 416 range of $q$ values at once rather than looping over each $q$ separately in 398 417 python. With $q$ as a vector, you cannot use if statements, but must instead … … 430 449 list includes the *volume* parameters in order. This is used for a weighted 431 450 volume normalization so that scattering is on an absolute scale. If 432 *form_volume* is not defin ded, then the default *form_volume = 1.0* will be451 *form_volume* is not defined, then the default *form_volume = 1.0* will be 433 452 used. 434 453 … … 436 455 ................. 437 456 438 Like pure python models, inline C models need define an *Iq* function::457 Like pure python models, inline C models need to define an *Iq* function:: 439 458 440 459 Iq = """ … … 516 535 These functions have been tuned to be fast and numerically stable down 517 536 to $q=0$ even in single precision. In some cases they work around bugs 518 which appear on some platforms but not others. 537 which appear on some platforms but not others. So use them where needed!!! 519 538 520 539 Models are defined using double precision declarations for the 521 540 parameters and return values. Declarations and constants will be converted 522 541 to float or long double depending on the precision requested. 542 523 543 **Floating point constants must include the decimal point.** This allows us 524 544 to convert values such as 1.0 (double precision) to 1.0f (single precision) … … 540 560 541 561 A value defined as SAS_DOUBLE will stay double precision; this should 542 not be used since some graphics card don't support double precision.562 not be used since some graphics cards do not support double precision. 543 563 544 564 … … 557 577 Form Factors 558 578 ............ 559 560 ::561 562 def ER(radius, thickness):563 """Effective radius of a core-shell sphere."""564 return radius + thickness565 579 566 580 Away from the dilute limit you can estimate scattering including … … 572 586 form averaged over all the polydispersity values. 573 587 574 Consider the *core_shell_sphere*, which has a simple effective radius 588 :: 589 590 def ER(radius, thickness): 591 """Effective radius of a core-shell sphere.""" 592 return radius + thickness 593 594 Now consider the *core_shell_sphere*, which has a simple effective radius 575 595 equal to the radius of the core plus the thickness of the shell, as 576 596 shown above. Given polydispersity over *(r1, r2, ..., rm)* in radius and … … 597 617 one return value for each point in the mesh grid. 598 618 599 *NOTE: we may be removing or modifying this feature soon. * As of this600 writing, core-shell sphere returns (1., 1.) for *VR*, giving a volume601 ratio of 1.0. 619 *NOTE: we may be removing or modifying this feature soon. As of the 620 time of writing, core-shell sphere returns (1., 1.) for VR, giving a volume 621 ratio of 1.0.* 602 622 603 623 Unit Tests … … 640 660 ^^^^^^^^^^^^^^^^^^^ 641 661 662 Installed SasView 663 ................. 664 642 665 If you are editing your model from the SasView GUI, you can test it 643 by selecting *Run -> Compile* from the *Model Editor* menu bar. An666 by selecting *Run > Compile* from the *Model Editor* menu bar. An 644 667 *Info* box will appear with the results of the compilation and a 645 668 check that the model runs. 646 669 670 671 Built SasView 672 ............. 673 647 674 If the model compiles and runs, you can next run the unit tests that 648 you have added using the **test =** values. Switch to the *Shell* tab675 you have added using the **test =** values. Switch to the *Shell* tab 649 676 and type the following:: 650 677 … … 686 713 For the random models, 687 714 688 - sld will be in(-0.5,10.5),689 - angles ( theta, phi, psi) will be in(-180,180),690 - angular dispersion will be in (0,45),691 - polydispersity will be in (0,1)692 - other values will be in (0, 2*v) where vis the value of the parameter in demo.693 694 Dispersion parameters n, sigma and typewill be unchanged from demo so that715 - *sld* will be in the range (-0.5,10.5), 716 - angles (*theta, phi, psi*) will be in the range (-180,180), 717 - angular dispersion will be in the range (0,45), 718 - polydispersity will be in the range (0,1) 719 - other values will be in the range (0, 2\ *v*), where *v* is the value of the parameter in demo. 720 721 Dispersion parameters *n*\, *sigma* and *type* will be unchanged from demo so that 695 722 run times are predictable. 696 723 … … 701 728 702 729 703 Clean Lint 704 ^^^^^^^^^^ 705 706 **NB: For now we are not providing pylint with SasView; unless you have a707 SasView development environment available, you can ignore this section.**730 Clean Lint - (Developer Version Only) 731 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 732 733 **NB: For now we are not providing pylint with the installer version of SasView; 734 so unless you have a SasView build environment available, you can ignore this section!** 708 735 709 736 Run the lint check with:: … … 717 744 for standard model functions *Iq*, *Iqxy*, etc. 718 745 719 We will have delinting sessions at the SasView code camps, where we can746 We will have delinting sessions at the SasView Code Camps, where we can 720 747 decide on standards for model files, parameter names, etc. 721 748 722 For now, you can tell pylint to ignore things. For example, to align you 749 For now, you can tell pylint to ignore things. For example, to align your 723 750 parameters in blocks:: 724 751 … … 738 765 Don't put in too many pylint statements, though, since they make the code ugly. 739 766 740 Check The Docs 741 ^^^^^^^^^^^^^^ 767 Check The Docs - (Developer Version Only) 768 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 742 769 743 770 You can get a rough idea of how the documentation will look using the … … 756 783 - `amsmath <http://www.ams.org/publications/authors/tex/amslatex>`_ 757 784 758 Finally 759 ^^^^^^^ 785 There is also a neat online WYSIWYG ReStructuredText editor at http://rst.ninjs.org\ . 786 787 Share Your Model! 788 ^^^^^^^^^^^^^^^^^ 760 789 761 790 Once compare and the unit test(s) pass properly and everything is done, 762 791 consider adding your model to the 763 `model marketplace <http://marketplace.sasview.org/>`_. 764 792 `Model Marketplace <http://marketplace.sasview.org/>`_ so that others may use it! -
src/sas/sasgui/perspectives/fitting/pagestate.py
r654e8e0 r6c382da 24 24 from xml.dom.minidom import parseString 25 25 from lxml import etree 26 27 import sasmodels.weights 26 28 27 29 import sas.sascalc.dataloader … … 474 476 value = content[1] 475 477 except Exception: 476 logging.error(traceback.format_exc()) 478 msg = "Report string expected 'name: value' but got %r"%line 479 logging.error(msg) 477 480 if name.count("State created"): 478 481 repo_time = "" + value … … 516 519 title_name = HEADER % title 517 520 except Exception: 518 logging.error(traceback.format_exc()) 521 msg = "While parsing 'data: ...'\n" 522 logging.error(msg + traceback.format_exc()) 519 523 if name == "model name ": 520 524 try: … … 531 535 q_range = CENTRE % q_name 532 536 except Exception: 533 logging.error(traceback.format_exc()) 537 msg = "While parsing 'Plotting Range: ...'\n" 538 logging.error(msg + traceback.format_exc()) 534 539 paramval = "" 535 540 for lines in param_string.split(":"): … … 711 716 # For self.values ={ disp_param_name: [vals,...],...} 712 717 # and for self.weights ={ disp_param_name: [weights,...],...} 713 value_list = {}714 718 for item in LIST_OF_MODEL_ATTRIBUTES: 715 719 element = newdoc.createElement(item[0]) … … 725 729 726 730 # Create doc for the dictionary of self._disp_obj_dic 727 for item in DISPERSION_LIST: 728 element = newdoc.createElement(item[0]) 729 value_list = getattr(self, item[1]) 730 for key, val in value_list.iteritems(): 731 value = repr(val) 731 for tagname, varname, tagtype in DISPERSION_LIST: 732 element = newdoc.createElement(tagname) 733 value_list = getattr(self, varname) 734 for key, value in value_list.iteritems(): 732 735 sub_element = newdoc.createElement(key) 733 736 sub_element.setAttribute('name', str(key)) … … 847 850 # Recover _disp_obj_dict from xml file 848 851 self._disp_obj_dict = {} 849 for item in DISPERSION_LIST: 850 # Get node 851 node = get_content("ns:%s" % item[0], entry) 852 for tagname, varname, tagtype in DISPERSION_LIST: 853 node = get_content("ns:%s" % tagname, entry) 852 854 for attr in node: 853 name = str(attr.get('name')) 854 val = attr.get('value') 855 value = val.split(" instance")[0] 856 disp_name = value.split("<")[1] 857 try: 858 # Try to recover disp_model object from strings 859 com = "from sas.models.dispersion_models " 860 com += "import %s as disp" 861 com_name = disp_name.split(".")[3] 862 exec com % com_name 863 disp_model = disp() 864 attribute = getattr(self, item[1]) 865 attribute[name] = com_name 866 except Exception: 867 logging.error(traceback.format_exc()) 855 parameter = str(attr.get('name')) 856 value = attr.get('value') 857 if value.startswith("<"): 858 try: 859 # <path.to.NamedDistribution object/instance...> 860 cls_name = value[1:].split()[0].split('.')[-1] 861 cls = getattr(sasmodels.weights, cls_name) 862 value = cls.type 863 except Exception: 864 logging.error("unable to load distribution %r for %s" 865 % (value, parameter)) 866 continue 867 _disp_obj_dict = getattr(self, varname) 868 _disp_obj_dict[parameter] = value 868 869 869 870 # get self.values and self.weights dic. if exists 870 for itemin LIST_OF_MODEL_ATTRIBUTES:871 node = get_content("ns:%s" % item[0], entry)871 for tagname, varname in LIST_OF_MODEL_ATTRIBUTES: 872 node = get_content("ns:%s" % tagname, entry) 872 873 dic = {} 873 874 value_list = [] 874 875 for par in node: 875 876 name = par.get('name') 876 values = par.text.split( '\n')877 values = par.text.split() 877 878 # Get lines only with numbers 878 879 for line in values: … … 882 883 except Exception: 883 884 # pass if line is empty (it happens) 884 logging.error(traceback.format_exc()) 885 msg = ("Error reading %r from %s %s\n" 886 % (line, tagname, name)) 887 logging.error(msg + traceback.format_exc()) 885 888 dic[name] = numpy.array(value_list) 886 setattr(self, item[1], dic)889 setattr(self, varname, dic) 887 890 888 891 def set_plot_state(self, figs, canvases): … … 1231 1234 1232 1235 except: 1233 logging.info("XML document does not contain fitting information.\n %s" % sys.exc_value) 1236 logging.info("XML document does not contain fitting information.\n" 1237 + traceback.format_exc()) 1234 1238 1235 1239 return state
Note: See TracChangeset
for help on using the changeset viewer.