Changes in / [1e6d9340:6e546f8] in sasview
- Files:
-
- 21 added
- 4 deleted
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
.pydevproject
r9d93c37 r26c8be3 4 4 <pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property> 5 5 <pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH"> 6 <path>/sasview /src</path>6 <path>/sasview4/src</path> 7 7 </pydev_pathproperty> 8 8 </pydev_project> -
sasview/sasview.py
r3b0f8cc rf36e01f 74 74 PLUGIN_MODEL_DIR = 'plugin_models' 75 75 APP_NAME = 'SasView' 76 77 # Set SAS_MODELPATH so sasmodels can find our custom models78 os.environ['SAS_MODELPATH'] = os.path.join(sasdir, PLUGIN_MODEL_DIR)79 76 80 77 from matplotlib import backend_bases -
src/sas/sascalc/dataloader/data_info.py
r17e257b5 ra1b8fee 1161 1161 final_dataset = None 1162 1162 if isinstance(data, plottable_1D): 1163 final_dataset = Data1D(data.x, data.y , isSesans=datainfo.isSesans)1163 final_dataset = Data1D(data.x, data.y) 1164 1164 final_dataset.dx = data.dx 1165 1165 final_dataset.dy = data.dy 1166 1166 final_dataset.dxl = data.dxl 1167 1167 final_dataset.dxw = data.dxw 1168 final_dataset.x_unit = data._xunit1169 final_dataset.y_unit = data._yunit1170 1168 final_dataset.xaxis(data._xaxis, data._xunit) 1171 1169 final_dataset.yaxis(data._yaxis, data._yunit) -
src/sas/sascalc/dataloader/file_reader_base_class.py
ra78a02f rdcb91cf 6 6 7 7 import os 8 import re9 8 import logging 10 9 import numpy as np … … 107 106 for data in self.output: 108 107 if isinstance(data, Data1D): 109 # Normalize the units for110 data.x_unit = self.format_unit(data.x_unit)111 data.y_unit = self.format_unit(data.y_unit)112 108 # Sort data by increasing x and remove 1st point 113 109 ind = np.lexsort((data.y, data.x)) … … 135 131 for dataset in self.output: 136 132 if isinstance(dataset, Data2D): 137 # Normalize the units for138 dataset.x_unit = self.format_unit(dataset.Q_unit)139 dataset.y_unit = self.format_unit(dataset.I_unit)140 133 dataset.data = dataset.data.astype(np.float64) 141 134 dataset.qx_data = dataset.qx_data.astype(np.float64) … … 162 155 dataset.data = dataset.data.flatten() 163 156 164 def format_unit(self, unit=None):165 """166 Format units a common way167 :param unit:168 :return:169 """170 if unit:171 split = unit.split("/")172 if len(split) == 1:173 return unit174 elif split[0] == '1':175 return "{0}^".format(split[1]) + "{-1}"176 else:177 return "{0}*{1}^".format(split[0], split[1]) + "{-1}"178 179 157 def set_all_to_none(self): 180 158 """ -
src/sas/sascalc/dataloader/readers/cansas_reader.py
ra78a02f rdcb91cf 299 299 self.current_dataset.dx = np.append(self.current_dataset.dx, data_point) 300 300 elif tagname == 'dQw': 301 if self.current_dataset.dxw is None: 302 self.current_dataset.dxw = np.empty(0) 301 if self.current_dataset.dqw is None: self.current_dataset.dqw = np.empty(0) 303 302 self.current_dataset.dxw = np.append(self.current_dataset.dxw, data_point) 304 303 elif tagname == 'dQl': 305 if self.current_dataset.dxl is None: 306 self.current_dataset.dxl = np.empty(0) 304 if self.current_dataset.dxl is None: self.current_dataset.dxl = np.empty(0) 307 305 self.current_dataset.dxl = np.append(self.current_dataset.dxl, data_point) 308 306 elif tagname == 'Qmean': -
src/sas/sascalc/dataloader/readers/danse_reader.py
ra78a02f r713a047 189 189 x_vals = np.tile(x_vals, (size_y, 1)).flatten() 190 190 y_vals = np.tile(y_vals, (size_x, 1)).T.flatten() 191 if (np.all(self.current_dataset.err_data == None) 192 or np.any(self.current_dataset.err_data <= 0)): 191 if self.current_dataset.err_data == np.all(np.array(None)) or np.any(self.current_dataset.err_data <= 0): 193 192 new_err_data = np.sqrt(np.abs(self.current_dataset.data)) 194 193 else: -
src/sas/sasgui/guiframe/local_perspectives/plotting/plotting.py
r2d9526d r235f514 14 14 import wx 15 15 import sys 16 from copy import deepcopy17 16 from sas.sasgui.guiframe.events import EVT_NEW_PLOT 18 17 from sas.sasgui.guiframe.events import EVT_PLOT_QRANGE … … 276 275 action_check = True 277 276 else: 278 if action_string == 'update':279 # Update all existing plots of data with this ID280 for data in event.plots:281 for panel in self.plot_panels.values():282 if data.id in panel.plots.keys():283 plot_exists = True284 # Pass each panel it's own copy of the data285 # that's being updated, otherwise things like286 # colour and line thickness are unintentionally287 # synced across panels288 self.update_panel(deepcopy(data), panel)289 return290 291 277 group_id = event.group_id 292 if group_id in self.plot_panels :278 if group_id in self.plot_panels.keys(): 293 279 #remove data from panel 294 280 if action_string == 'remove': -
src/sas/sasgui/perspectives/calculator/model_editor.py
r23359ccb r07ec714 106 106 self.model2_string = "cylinder" 107 107 self.name = 'Sum' + M_NAME 108 self.factor = 'scale_factor' 108 109 self._notes = '' 109 110 self._operator = '+' … … 132 133 self.model2_name = str(self.model2.GetValue()) 133 134 self.good_name = True 134 self.fill_op erator_combox()135 self.fill_oprator_combox() 135 136 136 137 def _layout_name(self): … … 490 491 a sum or multiply model then create the appropriate string 491 492 """ 493 492 494 name = '' 495 493 496 if operator == '*': 494 497 name = 'Multi' 495 factor = 'background' 498 factor = 'BackGround' 499 f_oper = '+' 496 500 else: 497 501 name = 'Sum' 498 502 factor = 'scale_factor' 499 503 f_oper = '*' 504 505 self.factor = factor 500 506 self._operator = operator 501 self.explanation = (" Plugin_model = scale_factor * (model_1 {} "502 "model_2) + background").format(operator)507 self.explanation = " Plugin Model = %s %s (model1 %s model2)\n" % \ 508 (self.factor, f_oper, self._operator) 503 509 self.explanationctr.SetLabel(self.explanation) 504 510 self.name = name + M_NAME 505 511 506 512 507 def fill_op erator_combox(self):513 def fill_oprator_combox(self): 508 514 """ 509 515 fill the current combobox with the operator … … 521 527 return [self.model1_name, self.model2_name] 522 528 523 def write_string(self, fname, model1_name, model2_name):529 def write_string(self, fname, name1, name2): 524 530 """ 525 531 Write and Save file … … 527 533 self.fname = fname 528 534 description = self.desc_tcl.GetValue().lstrip().rstrip() 529 desc_line = '' 530 if description.strip() != '': 531 # Sasmodels generates a description for us. If the user provides 532 # their own description, add a line to overwrite the sasmodels one 533 desc_line = "\nmodel_info.description = '{}'".format(description) 534 name = os.path.splitext(os.path.basename(self.fname))[0] 535 output = SUM_TEMPLATE.format(name=name, model1=model1_name, 536 model2=model2_name, operator=self._operator, desc_line=desc_line) 537 with open(self.fname, 'w') as out_f: 538 out_f.write(output) 535 if description == '': 536 description = name1 + self._operator + name2 537 text = self._operator_choice.GetValue() 538 if text.count('+') > 0: 539 factor = 'scale_factor' 540 f_oper = '*' 541 default_val = '1.0' 542 else: 543 factor = 'BackGround' 544 f_oper = '+' 545 default_val = '0.0' 546 path = self.fname 547 try: 548 out_f = open(path, 'w') 549 except: 550 raise 551 lines = SUM_TEMPLATE.split('\n') 552 for line in lines: 553 try: 554 if line.count("scale_factor"): 555 line = line.replace('scale_factor', factor) 556 #print "scale_factor", line 557 if line.count("= %s"): 558 out_f.write(line % (default_val) + "\n") 559 elif line.count("import Model as P1"): 560 if self.is_p1_custom: 561 line = line.replace('#', '') 562 out_f.write(line % name1 + "\n") 563 else: 564 out_f.write(line + "\n") 565 elif line.count("import %s as P1"): 566 if not self.is_p1_custom: 567 line = line.replace('#', '') 568 out_f.write(line % (name1) + "\n") 569 else: 570 out_f.write(line + "\n") 571 elif line.count("import Model as P2"): 572 if self.is_p2_custom: 573 line = line.replace('#', '') 574 out_f.write(line % name2 + "\n") 575 else: 576 out_f.write(line + "\n") 577 elif line.count("import %s as P2"): 578 if not self.is_p2_custom: 579 line = line.replace('#', '') 580 out_f.write(line % (name2) + "\n") 581 else: 582 out_f.write(line + "\n") 583 elif line.count("P1 = find_model"): 584 out_f.write(line % (name1) + "\n") 585 elif line.count("P2 = find_model"): 586 out_f.write(line % (name2) + "\n") 587 588 elif line.count("self.description = '%s'"): 589 out_f.write(line % description + "\n") 590 #elif line.count("run") and line.count("%s"): 591 # out_f.write(line % self._operator + "\n") 592 #elif line.count("evalDistribution") and line.count("%s"): 593 # out_f.write(line % self._operator + "\n") 594 elif line.count("return") and line.count("%s") == 2: 595 #print "line return", line 596 out_f.write(line % (f_oper, self._operator) + "\n") 597 elif line.count("out2")and line.count("%s"): 598 out_f.write(line % self._operator + "\n") 599 else: 600 out_f.write(line + "\n") 601 except: 602 raise 603 out_f.close() 604 #else: 605 # msg = "Name exists already." 539 606 540 607 def compile_file(self, path): … … 1211 1278 """ 1212 1279 SUM_TEMPLATE = """ 1213 from sasmodels.core import load_model_info 1214 from sasmodels.sasview_model import make_model_from_info 1215 1216 model_info = load_model_info('{model1}{operator}{model2}') 1217 model_info.name = '{name}'{desc_line} 1218 Model = make_model_from_info(model_info) 1280 # A sample of an experimental model function for Sum/Multiply(Pmodel1,Pmodel2) 1281 import os 1282 import sys 1283 import copy 1284 import collections 1285 1286 import numpy 1287 1288 from sas.sascalc.fit.pluginmodel import Model1DPlugin 1289 from sasmodels.sasview_model import find_model 1290 1291 class Model(Model1DPlugin): 1292 name = os.path.splitext(os.path.basename(__file__))[0] 1293 is_multiplicity_model = False 1294 def __init__(self, multiplicity=1): 1295 Model1DPlugin.__init__(self, name='') 1296 P1 = find_model('%s') 1297 P2 = find_model('%s') 1298 p_model1 = P1() 1299 p_model2 = P2() 1300 ## Setting model name model description 1301 self.description = '%s' 1302 if self.name.rstrip().lstrip() == '': 1303 self.name = self._get_name(p_model1.name, p_model2.name) 1304 if self.description.rstrip().lstrip() == '': 1305 self.description = p_model1.name 1306 self.description += p_model2.name 1307 self.fill_description(p_model1, p_model2) 1308 1309 ## Define parameters 1310 self.params = collections.OrderedDict() 1311 1312 ## Parameter details [units, min, max] 1313 self.details = {} 1314 ## Magnetic Panrameters 1315 self.magnetic_params = [] 1316 # non-fittable parameters 1317 self.non_fittable = p_model1.non_fittable 1318 self.non_fittable += p_model2.non_fittable 1319 1320 ##models 1321 self.p_model1= p_model1 1322 self.p_model2= p_model2 1323 1324 1325 ## dispersion 1326 self._set_dispersion() 1327 ## Define parameters 1328 self._set_params() 1329 ## New parameter:scaling_factor 1330 self.params['scale_factor'] = %s 1331 1332 ## Parameter details [units, min, max] 1333 self._set_details() 1334 self.details['scale_factor'] = ['', 0.0, numpy.inf] 1335 1336 1337 #list of parameter that can be fitted 1338 self._set_fixed_params() 1339 1340 ## parameters with orientation 1341 self.orientation_params = [] 1342 for item in self.p_model1.orientation_params: 1343 new_item = "p1_" + item 1344 if not new_item in self.orientation_params: 1345 self.orientation_params.append(new_item) 1346 1347 for item in self.p_model2.orientation_params: 1348 new_item = "p2_" + item 1349 if not new_item in self.orientation_params: 1350 self.orientation_params.append(new_item) 1351 ## magnetic params 1352 self.magnetic_params = [] 1353 for item in self.p_model1.magnetic_params: 1354 new_item = "p1_" + item 1355 if not new_item in self.magnetic_params: 1356 self.magnetic_params.append(new_item) 1357 1358 for item in self.p_model2.magnetic_params: 1359 new_item = "p2_" + item 1360 if not new_item in self.magnetic_params: 1361 self.magnetic_params.append(new_item) 1362 # get multiplicity if model provide it, else 1. 1363 try: 1364 multiplicity1 = p_model1.multiplicity 1365 try: 1366 multiplicity2 = p_model2.multiplicity 1367 except: 1368 multiplicity2 = 1 1369 except: 1370 multiplicity1 = 1 1371 multiplicity2 = 1 1372 ## functional multiplicity of the model 1373 self.multiplicity1 = multiplicity1 1374 self.multiplicity2 = multiplicity2 1375 self.multiplicity_info = [] 1376 1377 def _clone(self, obj): 1378 import copy 1379 obj.params = copy.deepcopy(self.params) 1380 obj.description = copy.deepcopy(self.description) 1381 obj.details = copy.deepcopy(self.details) 1382 obj.dispersion = copy.deepcopy(self.dispersion) 1383 obj.p_model1 = self.p_model1.clone() 1384 obj.p_model2 = self.p_model2.clone() 1385 #obj = copy.deepcopy(self) 1386 return obj 1387 1388 def _get_name(self, name1, name2): 1389 p1_name = self._get_upper_name(name1) 1390 if not p1_name: 1391 p1_name = name1 1392 name = p1_name 1393 name += "_and_" 1394 p2_name = self._get_upper_name(name2) 1395 if not p2_name: 1396 p2_name = name2 1397 name += p2_name 1398 return name 1399 1400 def _get_upper_name(self, name=None): 1401 if name is None: 1402 return "" 1403 upper_name = "" 1404 str_name = str(name) 1405 for index in range(len(str_name)): 1406 if str_name[index].isupper(): 1407 upper_name += str_name[index] 1408 return upper_name 1409 1410 def _set_dispersion(self): 1411 self.dispersion = collections.OrderedDict() 1412 ##set dispersion only from p_model 1413 for name , value in self.p_model1.dispersion.iteritems(): 1414 #if name.lower() not in self.p_model1.orientation_params: 1415 new_name = "p1_" + name 1416 self.dispersion[new_name]= value 1417 for name , value in self.p_model2.dispersion.iteritems(): 1418 #if name.lower() not in self.p_model2.orientation_params: 1419 new_name = "p2_" + name 1420 self.dispersion[new_name]= value 1421 1422 def function(self, x=0.0): 1423 return 0 1424 1425 def getProfile(self): 1426 try: 1427 x,y = self.p_model1.getProfile() 1428 except: 1429 x = None 1430 y = None 1431 1432 return x, y 1433 1434 def _set_params(self): 1435 for name , value in self.p_model1.params.iteritems(): 1436 # No 2D-supported 1437 #if name not in self.p_model1.orientation_params: 1438 new_name = "p1_" + name 1439 self.params[new_name]= value 1440 1441 for name , value in self.p_model2.params.iteritems(): 1442 # No 2D-supported 1443 #if name not in self.p_model2.orientation_params: 1444 new_name = "p2_" + name 1445 self.params[new_name]= value 1446 1447 # Set "scale" as initializing 1448 self._set_scale_factor() 1449 1450 1451 def _set_details(self): 1452 for name ,detail in self.p_model1.details.iteritems(): 1453 new_name = "p1_" + name 1454 #if new_name not in self.orientation_params: 1455 self.details[new_name]= detail 1456 1457 for name ,detail in self.p_model2.details.iteritems(): 1458 new_name = "p2_" + name 1459 #if new_name not in self.orientation_params: 1460 self.details[new_name]= detail 1461 1462 def _set_scale_factor(self): 1463 pass 1464 1465 1466 def setParam(self, name, value): 1467 # set param to this (p1, p2) model 1468 self._setParamHelper(name, value) 1469 1470 ## setParam to p model 1471 model_pre = '' 1472 new_name = '' 1473 name_split = name.split('_', 1) 1474 if len(name_split) == 2: 1475 model_pre = name.split('_', 1)[0] 1476 new_name = name.split('_', 1)[1] 1477 if model_pre == "p1": 1478 if new_name in self.p_model1.getParamList(): 1479 self.p_model1.setParam(new_name, value) 1480 elif model_pre == "p2": 1481 if new_name in self.p_model2.getParamList(): 1482 self.p_model2.setParam(new_name, value) 1483 elif name == 'scale_factor': 1484 self.params['scale_factor'] = value 1485 else: 1486 raise ValueError, "Model does not contain parameter %s" % name 1487 1488 def getParam(self, name): 1489 # Look for dispersion parameters 1490 toks = name.split('.') 1491 if len(toks)==2: 1492 for item in self.dispersion.keys(): 1493 # 2D not supported 1494 if item.lower()==toks[0].lower(): 1495 for par in self.dispersion[item]: 1496 if par.lower() == toks[1].lower(): 1497 return self.dispersion[item][par] 1498 else: 1499 # Look for standard parameter 1500 for item in self.params.keys(): 1501 if item.lower()==name.lower(): 1502 return self.params[item] 1503 return 1504 #raise ValueError, "Model does not contain parameter %s" % name 1505 1506 def _setParamHelper(self, name, value): 1507 # Look for dispersion parameters 1508 toks = name.split('.') 1509 if len(toks)== 2: 1510 for item in self.dispersion.keys(): 1511 if item.lower()== toks[0].lower(): 1512 for par in self.dispersion[item]: 1513 if par.lower() == toks[1].lower(): 1514 self.dispersion[item][par] = value 1515 return 1516 else: 1517 # Look for standard parameter 1518 for item in self.params.keys(): 1519 if item.lower()== name.lower(): 1520 self.params[item] = value 1521 return 1522 1523 raise ValueError, "Model does not contain parameter %s" % name 1524 1525 1526 def _set_fixed_params(self): 1527 self.fixed = [] 1528 for item in self.p_model1.fixed: 1529 new_item = "p1" + item 1530 self.fixed.append(new_item) 1531 for item in self.p_model2.fixed: 1532 new_item = "p2" + item 1533 self.fixed.append(new_item) 1534 1535 self.fixed.sort() 1536 1537 1538 def run(self, x = 0.0): 1539 self._set_scale_factor() 1540 return self.params['scale_factor'] %s \ 1541 (self.p_model1.run(x) %s self.p_model2.run(x)) 1542 1543 def runXY(self, x = 0.0): 1544 self._set_scale_factor() 1545 return self.params['scale_factor'] %s \ 1546 (self.p_model1.runXY(x) %s self.p_model2.runXY(x)) 1547 1548 ## Now (May27,10) directly uses the model eval function 1549 ## instead of the for-loop in Base Component. 1550 def evalDistribution(self, x = []): 1551 self._set_scale_factor() 1552 return self.params['scale_factor'] %s \ 1553 (self.p_model1.evalDistribution(x) %s \ 1554 self.p_model2.evalDistribution(x)) 1555 1556 def set_dispersion(self, parameter, dispersion): 1557 value= None 1558 new_pre = parameter.split("_", 1)[0] 1559 new_parameter = parameter.split("_", 1)[1] 1560 try: 1561 if new_pre == 'p1' and \ 1562 new_parameter in self.p_model1.dispersion.keys(): 1563 value= self.p_model1.set_dispersion(new_parameter, dispersion) 1564 if new_pre == 'p2' and \ 1565 new_parameter in self.p_model2.dispersion.keys(): 1566 value= self.p_model2.set_dispersion(new_parameter, dispersion) 1567 self._set_dispersion() 1568 return value 1569 except: 1570 raise 1571 1572 def fill_description(self, p_model1, p_model2): 1573 description = "" 1574 description += "This model gives the summation or multiplication of" 1575 description += "%s and %s. "% ( p_model1.name, p_model2.name ) 1576 self.description += description 1577 1578 if __name__ == "__main__": 1579 m1= Model() 1580 #m1.setParam("p1_scale", 25) 1581 #m1.setParam("p1_length", 1000) 1582 #m1.setParam("p2_scale", 100) 1583 #m1.setParam("p2_rg", 100) 1584 out1 = m1.runXY(0.01) 1585 1586 m2= Model() 1587 #m2.p_model1.setParam("scale", 25) 1588 #m2.p_model1.setParam("length", 1000) 1589 #m2.p_model2.setParam("scale", 100) 1590 #m2.p_model2.setParam("rg", 100) 1591 out2 = m2.p_model1.runXY(0.01) %s m2.p_model2.runXY(0.01)\n 1592 print "My name is %s."% m1.name 1593 print out1, " = ", out2 1594 if out1 == out2: 1595 print "===> Simple Test: Passed!" 1596 else: 1597 print "===> Simple Test: Failed!" 1219 1598 """ 1599 1220 1600 if __name__ == "__main__": 1221 1601 # app = wx.PySimpleApp() -
src/sas/sasgui/perspectives/fitting/fitting.py
r2d9526d r489f53a 1742 1742 @param unsmeared_error: data error, rescaled to unsmeared model 1743 1743 """ 1744 1744 1745 number_finite = np.count_nonzero(np.isfinite(y)) 1745 1746 np.nan_to_num(y) … … 1747 1748 data_description=model.name, 1748 1749 data_id=str(page_id) + " " + data.name) 1749 plots_to_update = [] # List of plottables that have changed since last calculation1750 # Create the new theories1751 1750 if unsmeared_model is not None: 1752 unsmeared_model_plot = self.create_theory_1D(x, unsmeared_model, 1753 page_id, model, data, state, 1751 self.create_theory_1D(x, unsmeared_model, page_id, model, data, state, 1754 1752 data_description=model.name + " unsmeared", 1755 1753 data_id=str(page_id) + " " + data.name + " unsmeared") 1756 plots_to_update.append(unsmeared_model_plot)1757 1754 1758 1755 if unsmeared_data is not None and unsmeared_error is not None: 1759 unsmeared_data_plot = self.create_theory_1D(x, unsmeared_data, 1760 page_id, model, data, state, 1756 self.create_theory_1D(x, unsmeared_data, page_id, model, data, state, 1761 1757 data_description="Data unsmeared", 1762 1758 data_id="Data " + data.name + " unsmeared", 1763 1759 dy=unsmeared_error) 1764 plots_to_update.append(unsmeared_data_plot) 1765 if sq_model is not None and pq_model is not None: 1766 sq_id = str(page_id) + " " + data.name + " S(q)" 1767 sq_plot = self.create_theory_1D(x, sq_model, page_id, model, data, state, 1768 data_description=model.name + " S(q)", 1769 data_id=sq_id) 1770 plots_to_update.append(sq_plot) 1771 pq_id = str(page_id) + " " + data.name + " P(q)" 1772 pq_plot = self.create_theory_1D(x, pq_model, page_id, model, data, state, 1773 data_description=model.name + " P(q)", 1774 data_id=pq_id) 1775 plots_to_update.append(pq_plot) 1776 # Update the P(Q), S(Q) and unsmeared theory plots if they exist 1777 wx.PostEvent(self.parent, NewPlotEvent(plots=plots_to_update, 1778 action='update')) 1760 # Comment this out until we can get P*S models with correctly populated parameters 1761 #if sq_model is not None and pq_model is not None: 1762 # self.create_theory_1D(x, sq_model, page_id, model, data, state, 1763 # data_description=model.name + " S(q)", 1764 # data_id=str(page_id) + " " + data.name + " S(q)") 1765 # self.create_theory_1D(x, pq_model, page_id, model, data, state, 1766 # data_description=model.name + " P(q)", 1767 # data_id=str(page_id) + " " + data.name + " P(q)") 1779 1768 1780 1769 current_pg = self.fit_panel.get_page_by_id(page_id) -
src/sas/sasgui/perspectives/fitting/media/fitting_help.rst
rca383a0 r5ed76f8 195 195 the :ref:`Advanced_Plugin_Editor` . 196 196 197 **SasView version 4.2** made it possible to specify whether a plugin created with198 the *New Plugin Model* dialog is actually a form factor P(Q) or a structure factor199 S(Q). To do this, simply add one or other of the following lines under the *import*200 statements.201 202 For a form factor::203 204 form_factor = True205 206 or for a structure factor::207 208 structure_factor = True209 210 If the plugin is a structure factor it is *also* necessary to add two variables to211 the parameter list::212 213 parameters = [214 ['radius_effective', '', 1, [0.0, numpy.inf], 'volume', ''],215 ['volfraction', '', 1, [0.0, 1.0], '', ''],216 [...],217 218 and to the declarations of the functions Iq and Iqxy:::219 220 def Iq(x , radius_effective, volfraction, ...):221 222 def Iqxy(x, y, radius_effective, volfraction, ...):223 224 Such a plugin should then be available in the S(Q) drop-down box on a FitPage (once225 a P(Q) model has been selected).226 227 197 Sum|Multi(p1,p2) 228 198 ^^^^^^^^^^^^^^^^ … … 236 206 or:: 237 207 238 Plugin Model = scale_factor * (model1 * model2)+ background208 Plugin Model = scale_factor * model_1 /* model_2 + background 239 209 240 210 In the *Easy Sum/Multi Editor* give the new model a function name and brief 241 211 description (to appear under the *Details* button on the *FitPage*). Then select 242 212 two existing models, as p1 and p2, and the required operator, '+' or '*' between 243 them. Finally, click the *Apply* button to generate and test the model and then click *Close*. 244 245 Any changes to a plugin model generated in this way only become effective *after* it is re-selected 246 from the plugin models drop-down menu on the FitPage. If the model is not listed you can force a 247 recompilation of the plugins by selecting *Fitting* > *Plugin Model Operations* > *Load Plugin Models*. 248 249 **SasView version 4.2** introduced a much simplified and more extensible structure for plugin models 250 generated through the Easy Sum/Multi Editor. For example, the code for a combination of a sphere model 251 with a power law model now looks like this:: 252 253 from sasmodels.core import load_model_info 254 from sasmodels.sasview_model import make_model_from_info 255 256 model_info = load_model_info('sphere+power_law') 257 model_info.name = 'MyPluginModel' 258 model_info.description = 'sphere + power_law' 259 Model = make_model_from_info(model_info) 260 261 To change the models or operators contributing to this plugin it is only necessary to edit the string 262 in the brackets after *load_model_info*, though it would also be a good idea to update the model name 263 and description too!!! 264 265 The model specification string can handle multiple models and combinations of operators (+ or *) which 266 are processed according to normal conventions. Thus 'model1+model2*model3' would be valid and would 267 multiply model2 by model3 before adding model1. In this example, parameters in the *FitPage* would be 268 prefixed A (for model2), B (for model3) and C (for model1). Whilst this might appear a little 269 confusing, unless you were creating a plugin model from multiple instances of the same model the parameter 270 assignments ought to be obvious when you load the plugin. 271 272 If you need to include another plugin model in the model specification string, just prefix the name of 273 that model with *custom*. For instance:: 274 275 sphere+custom.MyPluginModel 276 277 To create a P(Q)*\S(Q) model use the @ symbol instead of * like this:: 278 279 sphere@hardsphere 280 281 This streamlined approach to building complex plugin models from existing library models, or models 282 available on the *Model Marketplace*, also permits the creation of P(Q)*\S(Q) plugin models, something 283 that was not possible in earlier versions of SasView. 213 them. Finally, click the *Apply* button to generate the model and then click *Close*. 214 215 Any changes to a plugin model generated in this way only become effective *after* it is re-selected from the model drop-down menu on the FitPage. 284 216 285 217 .. _Advanced_Plugin_Editor: … … 552 484 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 553 485 554 .. _Batch_Fit_Mode:555 556 486 Batch Fit Mode 557 487 -------------- … … 706 636 707 637 Example: radius [2 : 5] , radius [10 : 25] 708 709 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 710 711 Combined Batch Fit Mode 712 ----------------------- 713 714 The purpose of the Combined Batch Fit is to allow running two or more batch 715 fits in sequence without overwriting the output table of results. This may be 716 of interest for example if one is fitting a series of data sets where there is 717 a shape change occurring in the series that requires changing the model part 718 way through the series; for example a sphere to rod transition. Indeed the 719 regular batch mode does not allow for multiple models and requires all the 720 files in the series to be fit with single model and set of parameters. While 721 it is of course possible to just run part of the series as a batch fit using 722 model one followed by running another batch fit on the rest of the series with 723 model two (and/or model three etc), doing so will overwrite the table of 724 outputs from the previous batch fit(s). This may not be desirable if one is 725 interested in comparing the parameters: for example the sphere radius of set 726 one and the cylinder radius of set two. 727 728 Method 729 ^^^^^^ 730 731 In order to use the *Combined Batch Fit*, first load all the data needed as 732 described in :ref:`Loading_data`. Next start up two or more *BatchPage* fits 733 following the instructions in :ref:`Batch_Fit_Mode` but **DO NOT PRESS FIT**. 734 At this point the *Combine Batch Fit* menu item under the *Fitting menu* should 735 be active (if there is one or no *BatchPage* the menu item will be greyed out 736 and inactive). Clicking on *Combine Batch Fit* will bring up a new panel, 737 similar to the *Const & Simult Fit* panel. In this case there will be a 738 checkbox for each *BatchPage* instead of each *FitPage* that should be included 739 in the fit. Once all are selected, click the Fit button on 740 the *BatchPage* to run each batch fit in *sequence* 741 742 .. image:: combine_batch_page.png 743 744 The batch table will then pop up at the end as for the case of the simple Batch 745 Fitting with the following caveats: 746 747 .. note:: 748 The order matters. The parameters in the table will be taken from the model 749 used in the first *BatchPage* of the list. Any parameters from the 750 second and later *BatchPage* s that have the same name as a parameter in the 751 first will show up allowing for plotting of that parameter across the 752 models. The other parameters will not be available in the grid. 753 .. note:: 754 a corralary of the above is that currently models created as a sum|multiply 755 model will not work as desired because the generated model parameters have a 756 p#_ appended to the beginning and thus radius and p1_radius will not be 757 recognized as the same parameter. 758 759 .. image:: combine_batch_grid.png 760 761 In the example shown above the data is a time series with a shifting peak. 762 The first part of the series was fitted using the *broad_peak* model, while 763 the rest of the data were fit using the *gaussian_peak* model. Unfortunately the 764 time is not listed in the file but the file name contains the information. As 765 described in :ref:`Grid_Window`, a column can be added manually, in this case 766 called time, and the peak position plotted against time. 767 768 .. image:: combine_batch_plot.png 769 770 Note the discontinuity in the peak position. This reflects the fact that the 771 Gaussian fit is a rather poor model for the data and is not actually 772 finding the peak. 773 774 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 775 776 .. note:: This help document was last changed by Paul Butler, 10 September 777 2017 638 639 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 640 641 .. note:: This help document was last changed by Steve King, 10Oct2016 -
src/sas/sasgui/perspectives/fitting/media/plugin.rst
re081946 r96f00a0 18 18 * By writing a model from scratch outside of SasView (only recommended for 19 19 code monkeys!) 20 21 **What follows below is quite technical. If you just want a helping hand to get22 started creating your own models see** :ref:`Adding_your_own_models`.23 20 24 21 Overview -
src/sas/sasgui/perspectives/fitting/model_thread.py
r0f9ea1c r7432acb 71 71 (self.data.qy_data * self.data.qy_data)) 72 72 73 # For theory, qmax is based on 1d qmax 73 # For theory, qmax is based on 1d qmax 74 74 # so that must be mulitified by sqrt(2) to get actual max for 2d 75 75 index_model = (self.qmin <= radius) & (radius <= self.qmax) … … 91 91 self.data.qy_data[index_model] 92 92 ]) 93 # Initialize output to NaN so masked elements do not get plotted. 94 output = np.empty_like(self.data.qx_data) 93 output = np.zeros(len(self.data.qx_data)) 95 94 # output default is None 96 95 # This method is to distinguish between masked 97 96 #point(nan) and data point = 0. 98 output [:] = np.NaN97 output = output / output 99 98 # set value for self.mask==True, else still None to Plottools 100 99 output[index_model] = value … … 199 198 output[index] = self.model.evalDistribution(self.data.x[index]) 200 199 201 x=self.data.x[index]202 y=output[index]203 200 sq_values = None 204 201 pq_values = None 202 s_model = None 203 p_model = None 205 204 if isinstance(self.model, MultiplicationModel): 206 205 s_model = self.model.s_model 207 206 p_model = self.model.p_model 208 sq_values = s_model.evalDistribution(x) 209 pq_values = p_model.evalDistribution(x) 210 elif hasattr(self.model, "calc_composition_models"): 211 results = self.model.calc_composition_models(x) 212 if results is not None: 213 pq_values, sq_values = results 214 207 elif hasattr(self.model, "get_composition_models"): 208 p_model, s_model = self.model.get_composition_models() 209 210 if p_model is not None and s_model is not None: 211 sq_values = np.zeros((len(self.data.x))) 212 pq_values = np.zeros((len(self.data.x))) 213 sq_values[index] = s_model.evalDistribution(self.data.x[index]) 214 pq_values[index] = p_model.evalDistribution(self.data.x[index]) 215 215 216 216 elapsed = time.time() - self.starttime 217 217 218 self.complete(x= x, y=y,218 self.complete(x=self.data.x[index], y=output[index], 219 219 page_id=self.page_id, 220 220 state=self.state, -
src/sas/sasgui/perspectives/fitting/simfitpage.py
ra9f9ca4 r959eb01 1 1 """ 2 Simultaneous or Batchfit page2 Simultaneous fit page 3 3 """ 4 # Note that this is used for both Simultaneous/Constrained fit AND for5 # 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 in7 # if not batch_on:8 # xxxx9 # else:10 # xxxx11 # This is just wrong but dont have time to fix this go. Proper approach would be12 # to strip all parts of the code that depend on batch_on and create the top13 # level class from which a contrained/simultaneous fit page and a combined14 # batch page inherit.15 #16 # 04/09/2017 --PDB17 18 4 import sys 19 5 from collections import namedtuple … … 414 400 # General Help button 415 401 self.btHelp = wx.Button(self, wx.ID_HELP, 'HELP') 416 if self.batch_on: 417 self.btHelp.SetToolTipString("Combined Batch Fitting help.") 418 else: 419 self.btHelp.SetToolTipString("Simultaneous/Constrained Fitting help.") 402 self.btHelp.SetToolTipString("Simultaneous/Constrained Fitting help.") 420 403 self.btHelp.Bind(wx.EVT_BUTTON, self._on_help) 421 404 … … 544 527 """ 545 528 _TreeLocation = "user/sasgui/perspectives/fitting/fitting_help.html" 546 if not self.batch_on: 547 _PageAnchor = "#simultaneous-fit-mode" 548 _doc_viewer = DocumentationWindow(self, self.ID_DOC, _TreeLocation, 529 _PageAnchor = "#simultaneous-fit-mode" 530 _doc_viewer = DocumentationWindow(self, self.ID_DOC, _TreeLocation, 549 531 _PageAnchor, 550 532 "Simultaneous/Constrained Fitting Help") 551 else:552 _PageAnchor = "#combined-batch-fit-mode"553 _doc_viewer = DocumentationWindow(self, self.ID_DOC, _TreeLocation,554 _PageAnchor,555 "Combined Batch Fit Help")556 533 557 534 def set_manager(self, manager): -
src/sas/sasgui/plottools/plottables.py
r2d9526d r45dffa69 239 239 def replace(self, plottable): 240 240 """Replace an existing plottable from the graph""" 241 # If the user has set a custom color, ensure the new plot is the same color 242 selected_color = plottable.custom_color 241 selected_color = None 243 242 selected_plottable = None 244 243 for p in self.plottables.keys(): 245 244 if plottable.id == p.id: 246 245 selected_plottable = p 247 if selected_color is None: 248 selected_color = self.plottables[p] 246 selected_color = self.plottables[p] 249 247 break 250 if selected_plottable is not None and selected_color is not None:248 if selected_plottable is not None and selected_color is not None: 251 249 del self.plottables[selected_plottable] 252 plottable.custom_color = selected_color253 250 self.plottables[plottable] = selected_color 254 251 -
test/sasdataloader/test/utest_abs_reader.py
ra78a02f rce8c7bd 20 20 def setUp(self): 21 21 reader = AbsReader() 22 data = reader.read("jan08002.ABS") 23 self.data= data[0] 22 self.data = reader.read("jan08002.ABS") 24 23 25 24 def test_abs_checkdata(self): … … 48 47 self.assertEqual(self.data.detector[0].beam_center.y, center_y) 49 48 50 self.assertEqual(self.data.y_unit, ' cm^{-1}')49 self.assertEqual(self.data.y_unit, '1/cm') 51 50 self.assertEqual(self.data.x[0], 0.002618) 52 51 self.assertEqual(self.data.x[1], 0.007854) … … 70 69 # the generic loader should work as well 71 70 data = Loader().load("jan08002.ABS") 72 self.assertEqual(data [0].meta_data['loader'], "IGOR 1D")71 self.assertEqual(data.meta_data['loader'], "IGOR 1D") 73 72 74 73 class DanseReaderTests(unittest.TestCase): … … 76 75 def setUp(self): 77 76 reader = DANSEReader() 78 data = reader.read("MP_New.sans") 79 self.data = data[0] 77 self.data = reader.read("MP_New.sans") 80 78 81 79 def test_checkdata(self): … … 114 112 # the generic loader should work as well 115 113 data = Loader().load("MP_New.sans") 116 self.assertEqual(data [0].meta_data['loader'], "DANSE")114 self.assertEqual(data.meta_data['loader'], "DANSE") 117 115 118 116 … … 146 144 # Data 147 145 self.assertEqual(len(self.data.x), 2) 148 self.assertEqual(self.data.x_unit, ' A^{-1}')149 self.assertEqual(self.data.y_unit, ' cm^{-1}')146 self.assertEqual(self.data.x_unit, '1/A') 147 self.assertEqual(self.data.y_unit, '1/cm') 150 148 self.assertAlmostEqual(self.data.x[0], 0.02, 6) 151 149 self.assertAlmostEqual(self.data.y[0], 1000, 6) … … 259 257 self.assertTrue(item.date in ['04-Sep-2007 18:35:02', 260 258 '03-SEP-2006 11:42:47']) 259 print(item.term) 261 260 for t in item.term: 262 261 if (t['name'] == "ABS:DSTAND" … … 310 309 311 310 self.assertEqual(self.data.meta_data['loader'], "CanSAS XML 1D") 312 self.assertEqual(len(self.data.errors), 0) 311 print(self.data.errors) 312 self.assertEqual(len(self.data.errors), 1) 313 313 314 314 def test_slits(self): … … 324 324 # Data 325 325 self.assertEqual(len(self.data.x), 2) 326 self.assertEqual(self.data.x_unit, ' A^{-1}')327 self.assertEqual(self.data.y_unit, ' cm^{-1}')326 self.assertEqual(self.data.x_unit, '1/A') 327 self.assertEqual(self.data.y_unit, '1/cm') 328 328 self.assertEqual(self.data.x[0], 0.02) 329 329 self.assertEqual(self.data.y[0], 1000) … … 333 333 self.assertEqual(self.data.x[1], 0.03) 334 334 self.assertAlmostEquals(self.data.y[1], 1001.0) 335 self.assertEqual(self.data.dx [0], 0.0)335 self.assertEqual(self.data.dx, None) 336 336 self.assertEqual(self.data.dxl[1], 0.005) 337 337 self.assertEqual(self.data.dxw[1], 0.001) -
test/sasdataloader/test/utest_ascii.py
ra78a02f rad92c5a 32 32 self.assertEqual(self.f1.x[0],0.002618) 33 33 self.assertEqual(self.f1.x[9],0.0497) 34 self.assert True(self.f1.x_unit == 'A^{-1}')35 self.assert True(self.f1.y_unit == 'cm^{-1}')34 self.assertEqual(self.f1.x_unit, '1/A') 35 self.assertEqual(self.f1.y_unit, '1/cm') 36 36 37 37 self.assertEqual(self.f1.meta_data['loader'],"ASCII") -
test/sasdataloader/test/utest_cansas.py
r17e257b5 r1fc50fb2 20 20 21 21 from lxml import etree 22 from lxml.etree import XMLSyntaxError23 22 from xml.dom import minidom 24 23 … … 63 62 """ 64 63 invalid = StringIO.StringIO('<a><c></b></a>') 65 self.assertRaises(XMLSyntaxError, lambda: XMLreader(invalid))64 XMLreader(invalid) 66 65 67 66 def test_xml_validate(self): … … 303 302 self.assertTrue(data._yunit == "cm^{-1}") 304 303 self.assertTrue(data.y.size == 100) 305 self.assertAlmostEqual(data.y[ 40], 0.952749011516985)306 self.assertAlmostEqual(data.x[ 40], 0.3834415188257777)304 self.assertAlmostEqual(data.y[9], 0.952749011516985) 305 self.assertAlmostEqual(data.x[9], 0.3834415188257777) 307 306 self.assertAlmostEqual(len(data.meta_data), 0) 308 307 -
test/sasdataloader/test/utest_sesans.py
ra78a02f ra67c494 4 4 5 5 import unittest 6 from sas.sascalc.dataloader.loader_exceptions import FileContentsException,\7 DefaultReaderException8 6 from sas.sascalc.dataloader.readers.sesans_reader import Reader 9 7 from sas.sascalc.dataloader.loader import Loader … … 19 17 Test .SES in the full loader to make sure that the file type is correctly accepted 20 18 """ 21 file = Loader().load("sesans_examples/sphere2micron.ses") 22 f = file[0] 19 f = Loader().load("sesans_examples/sphere2micron.ses") 23 20 # self.assertEqual(f, 5) 24 21 self.assertEqual(len(f.x), 40) … … 37 34 Test .SES loading on a TOF dataset 38 35 """ 39 file = self.loader("sesans_examples/sphere_isis.ses") 40 f = file[0] 36 f = self.loader("sesans_examples/sphere_isis.ses") 41 37 self.assertEqual(len(f.x), 57) 42 38 self.assertEqual(f.x[-1], 19303.4) … … 52 48 """ 53 49 self.assertRaises( 54 FileContentsException,50 RuntimeError, 55 51 self.loader, 56 52 "sesans_examples/sesans_no_data.ses") … … 61 57 """ 62 58 self.assertRaises( 63 FileContentsException,59 RuntimeError, 64 60 self.loader, 65 61 "sesans_examples/no_spin_echo_unit.ses") 62 63 def test_sesans_no_version(self): 64 """ 65 Confirm that sesans files with no file format version raise an appropriate error 66 """ 67 self.assertRaises( 68 RuntimeError, 69 self.loader, 70 "sesans_examples/no_version.ses") 66 71 67 72 def test_sesans_future_version(self): … … 70 75 """ 71 76 self.assertRaises( 72 FileContentsException,77 RuntimeError, 73 78 self.loader, 74 79 "sesans_examples/next_gen.ses") … … 79 84 """ 80 85 self.assertRaises( 81 FileContentsException,86 RuntimeError, 82 87 self.loader, 83 88 "sesans_examples/no_wavelength.ses") … … 88 93 """ 89 94 self.assertRaises( 90 FileContentsException,95 RuntimeError, 91 96 self.loader, 92 97 "sesans_examples/too_many_headers.ses") -
test/utest_sasview.py
rb54440d raaf5e49 44 44 n_errors = 0 45 45 n_failures = 0 46 46 47 47 for d in (dirs if dirs else os.listdir(test_root)): 48 48 49 49 # Check for modules to be skipped 50 50 if d in SKIPPED_DIRS: 51 51 continue 52 52 53 53 54 54 # Go through modules looking for unit tests … … 64 64 #print std_out 65 65 #sys.exit() 66 has_failed = True 66 67 m = re.search("Ran ([0-9]+) test", std_out) 67 68 if m is not None: 69 has_failed = False 68 70 n_tests += int(m.group(1)) 69 has_tests = True70 else:71 has_tests = False72 71 73 has_failed = "FAILED (" in std_out 74 m = re.search("FAILED \(.*errors=([0-9]+)", std_out) 72 m = re.search("FAILED \(errors=([0-9]+)\)", std_out) 75 73 if m is not None: 74 has_failed = True 76 75 n_errors += int(m.group(1)) 77 m = re.search("FAILED \(.*failures=([0-9]+)", std_out) 76 77 m = re.search("FAILED \(failures=([0-9]+)\)", std_out) 78 78 if m is not None: 79 has_failed = True 79 80 n_failures += int(m.group(1)) 80 81 if has_failed or not has_tests:81 82 if has_failed: 82 83 failed += 1 83 84 print("Result for %s (%s): FAILED" % (module_name, module_dir)) … … 101 102 print(" Test errors: %d" % n_errors) 102 103 print("----------------------------------------------") 103 104 104 105 return failed 105 106 … … 109 110 if run_tests(dirs=dirs, all=all)>0: 110 111 sys.exit(1) 111 112
Note: See TracChangeset
for help on using the changeset viewer.