Ignore:
Timestamp:
Sep 1, 2017 5:20:06 AM (7 years ago)
Author:
lewis
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.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
3b0f8cc
Parents:
9d80623
Message:

Update sum/multi models to use sasmodels MixtureModel?

File:
1 edited

Legend:

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

    r9d80623 rc351bf1  
    521521        return [self.model1_name, self.model2_name] 
    522522 
    523     def write_string(self, fname, name1, name2): 
     523    def write_string(self, fname, model1_name, model2_name): 
    524524        """ 
    525525        Write and Save file 
     
    527527        self.fname = fname 
    528528        description = self.desc_tcl.GetValue().lstrip().rstrip() 
    529         if description == '': 
    530             description = name1 + self._operator + name2 
    531         operator_text = self._operator_choice.GetValue() 
    532         f_oper = '*' if '+' in operator_text else '+' 
    533         path = self.fname 
    534         output = SUM_TEMPLATE.format(model1=name1, model2=name2,  
    535             scale_factor_default=1.0, background_default=0.001, 
    536             factor_operator=f_oper, operator=self._operator, 
    537             description=description) 
    538         if self._operator == '*': 
    539             # Multiplication models only have 1 overall scale factor. Don't use 
    540             # sub-models' individual scales as fitting params 
    541             output = output.replace("if name == 'background'",  
    542                 "if name == 'background' or name == 'scale'") 
     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) 
    543537        with open(self.fname, 'w') as out_f: 
    544             out_f.write(output + "\n") 
     538            out_f.write(output) 
    545539 
    546540    def compile_file(self, path): 
     
    12171211""" 
    12181212SUM_TEMPLATE = """ 
    1219 # A sample of an experimental model function for Sum/Multiply(Pmodel1,Pmodel2) 
    1220 import os 
    1221 import sys 
    1222 import copy 
    1223 import collections 
    1224  
    1225 import numpy 
    1226  
    1227 from sas.sascalc.fit.pluginmodel import Model1DPlugin 
    1228 from sasmodels.sasview_model import find_model 
    1229  
    1230 class Model(Model1DPlugin): 
    1231     name = os.path.splitext(os.path.basename(__file__))[0] 
    1232     is_multiplicity_model = False 
    1233     def __init__(self, multiplicity=1): 
    1234         Model1DPlugin.__init__(self, name='') 
    1235         P1 = find_model('{model1}') 
    1236         P2 = find_model('{model2}') 
    1237         p_model1 = P1() 
    1238         p_model2 = P2() 
    1239         ## Setting  model name model description 
    1240         self.description = '{description}' 
    1241         if self.name.rstrip().lstrip() == '': 
    1242             self.name = self._get_name(p_model1.name, p_model2.name) 
    1243         if self.description.rstrip().lstrip() == '': 
    1244             self.description = p_model1.name 
    1245             self.description += p_model2.name 
    1246             self.fill_description(p_model1, p_model2) 
    1247  
    1248         ## Define parameters 
    1249         self.params = collections.OrderedDict() 
    1250  
    1251         ## Parameter details [units, min, max] 
    1252         self.details = {{}} 
    1253         ## Magnetic Panrameters 
    1254         self.magnetic_params = [] 
    1255         # non-fittable parameters 
    1256         self.non_fittable = p_model1.non_fittable 
    1257         self.non_fittable += p_model2.non_fittable 
    1258  
    1259         ##models 
    1260         self.p_model1= p_model1 
    1261         self.p_model2= p_model2 
    1262  
    1263  
    1264         ## dispersion 
    1265         self._set_dispersion() 
    1266         ## Define parameters 
    1267         self._set_params() 
    1268         ## New parameter:scaling_factor 
    1269         self.params['scale_factor'] = {scale_factor_default} 
    1270         # Set each model's background to 0, and define our own background param 
    1271         if 'background' in self.p_model1.params: 
    1272             self.p_model1.setParam('background', 0.0) 
    1273         if 'background' in self.p_model2.params: 
    1274             self.p_model2.setParam('background', 0.0) 
    1275         self.params['background'] = {background_default} 
    1276  
    1277         ## Parameter details [units, min, max] 
    1278         self._set_details() 
    1279         self.details['scale_factor'] = ['', 0.0, numpy.inf] 
    1280         self.details['background'] = ['1/cm', 0.0, numpy.inf] 
    1281  
    1282         #list of parameter that can be fitted 
    1283         self._set_fixed_params() 
    1284  
    1285         ## parameters with orientation 
    1286         self.orientation_params = [] 
    1287         for item in self.p_model1.orientation_params: 
    1288             new_item = "p1_" + item 
    1289             if not new_item in self.orientation_params: 
    1290                 self.orientation_params.append(new_item) 
    1291  
    1292         for item in self.p_model2.orientation_params: 
    1293             new_item = "p2_" + item 
    1294             if not new_item in self.orientation_params: 
    1295                 self.orientation_params.append(new_item) 
    1296         ## magnetic params 
    1297         self.magnetic_params = [] 
    1298         for item in self.p_model1.magnetic_params: 
    1299             new_item = "p1_" + item 
    1300             if not new_item in self.magnetic_params: 
    1301                 self.magnetic_params.append(new_item) 
    1302  
    1303         for item in self.p_model2.magnetic_params: 
    1304             new_item = "p2_" + item 
    1305             if not new_item in self.magnetic_params: 
    1306                 self.magnetic_params.append(new_item) 
    1307         # get multiplicity if model provide it, else 1. 
    1308         try: 
    1309             multiplicity1 = p_model1.multiplicity 
    1310             try: 
    1311                 multiplicity2 = p_model2.multiplicity 
    1312             except: 
    1313                 multiplicity2 = 1 
    1314         except: 
    1315             multiplicity1 = 1 
    1316             multiplicity2 = 1 
    1317         ## functional multiplicity of the model 
    1318         self.multiplicity1 = multiplicity1 
    1319         self.multiplicity2 = multiplicity2 
    1320         self.multiplicity_info = [] 
    1321  
    1322     def _clone(self, obj): 
    1323         import copy 
    1324         obj.params     = copy.deepcopy(self.params) 
    1325         obj.description     = copy.deepcopy(self.description) 
    1326         obj.details    = copy.deepcopy(self.details) 
    1327         obj.dispersion = copy.deepcopy(self.dispersion) 
    1328         obj.p_model1  = self.p_model1.clone() 
    1329         obj.p_model2  = self.p_model2.clone() 
    1330         #obj = copy.deepcopy(self) 
    1331         return obj 
    1332  
    1333     def _get_name(self, name1, name2): 
    1334         p1_name = self._get_upper_name(name1) 
    1335         if not p1_name: 
    1336             p1_name = name1 
    1337         name = p1_name 
    1338         name += "_and_" 
    1339         p2_name = self._get_upper_name(name2) 
    1340         if not p2_name: 
    1341             p2_name = name2 
    1342         name += p2_name 
    1343         return name 
    1344  
    1345     def _get_upper_name(self, name=None): 
    1346         if name is None: 
    1347             return "" 
    1348         upper_name = "" 
    1349         str_name = str(name) 
    1350         for index in range(len(str_name)): 
    1351             if str_name[index].isupper(): 
    1352                 upper_name += str_name[index] 
    1353         return upper_name 
    1354  
    1355     def _set_dispersion(self): 
    1356         self.dispersion = collections.OrderedDict() 
    1357         ##set dispersion only from p_model 
    1358         for name , value in self.p_model1.dispersion.iteritems(): 
    1359             #if name.lower() not in self.p_model1.orientation_params: 
    1360             new_name = "p1_" + name 
    1361             self.dispersion[new_name]= value 
    1362         for name , value in self.p_model2.dispersion.iteritems(): 
    1363             #if name.lower() not in self.p_model2.orientation_params: 
    1364             new_name = "p2_" + name 
    1365             self.dispersion[new_name]= value 
    1366  
    1367     def function(self, x=0.0): 
    1368         return 0 
    1369  
    1370     def getProfile(self): 
    1371         try: 
    1372             x,y = self.p_model1.getProfile() 
    1373         except: 
    1374             x = None 
    1375             y = None 
    1376  
    1377         return x, y 
    1378  
    1379     def _set_params(self): 
    1380         for name , value in self.p_model1.params.iteritems(): 
    1381             # Don't use the model's background param - we've defined our own 
    1382             if name == 'background': 
    1383                 continue 
    1384             new_name = "p1_" + name 
    1385             self.params[new_name] = value 
    1386  
    1387         for name , value in self.p_model2.params.iteritems(): 
    1388             # Don't use the model's background param - we've defined our own 
    1389             if name == 'background': 
    1390                 continue 
    1391             new_name = "p2_" + name 
    1392             self.params[new_name] = value 
    1393  
    1394         # Set "scale" as initializing 
    1395         self._set_scale_factor() 
    1396  
    1397  
    1398     def _set_details(self): 
    1399         for name ,detail in self.p_model1.details.iteritems(): 
    1400             if name == 'background': 
    1401                 continue 
    1402             new_name = "p1_" + name 
    1403             #if new_name not in self.orientation_params: 
    1404             self.details[new_name]= detail 
    1405  
    1406         for name ,detail in self.p_model2.details.iteritems(): 
    1407             if name == 'background': 
    1408                 continue 
    1409             new_name = "p2_" + name 
    1410             #if new_name not in self.orientation_params: 
    1411             self.details[new_name]= detail 
    1412  
    1413     def _set_scale_factor(self): 
    1414         pass 
    1415  
    1416  
    1417     def setParam(self, name, value): 
    1418         # set param to this (p1, p2) model 
    1419         self._setParamHelper(name, value) 
    1420  
    1421         ## setParam to p model 
    1422         model_pre = '' 
    1423         new_name = '' 
    1424         name_split = name.split('_', 1) 
    1425         if len(name_split) == 2: 
    1426             model_pre = name.split('_', 1)[0] 
    1427             new_name = name.split('_', 1)[1] 
    1428         if model_pre == "p1": 
    1429             if new_name in self.p_model1.getParamList(): 
    1430                 self.p_model1.setParam(new_name, value) 
    1431         elif model_pre == "p2": 
    1432              if new_name in self.p_model2.getParamList(): 
    1433                 self.p_model2.setParam(new_name, value) 
    1434         elif name == 'scale_factor' or name == 'background': 
    1435             self.params[name] = value 
    1436         else: 
    1437             raise ValueError, "Model does not contain parameter %s" % name 
    1438  
    1439     def getParam(self, name): 
    1440         # Look for dispersion parameters 
    1441         toks = name.split('.') 
    1442         if len(toks)==2: 
    1443             for item in self.dispersion.keys(): 
    1444                 # 2D not supported 
    1445                 if item.lower()==toks[0].lower(): 
    1446                     for par in self.dispersion[item]: 
    1447                         if par.lower() == toks[1].lower(): 
    1448                             return self.dispersion[item][par] 
    1449         else: 
    1450             # Look for standard parameter 
    1451             for item in self.params.keys(): 
    1452                 if item.lower()==name.lower(): 
    1453                     return self.params[item] 
    1454         return 
    1455         #raise ValueError, "Model does not contain parameter %s" % name 
    1456  
    1457     def _setParamHelper(self, name, value): 
    1458         # Look for dispersion parameters 
    1459         toks = name.split('.') 
    1460         if len(toks)== 2: 
    1461             for item in self.dispersion.keys(): 
    1462                 if item.lower()== toks[0].lower(): 
    1463                     for par in self.dispersion[item]: 
    1464                         if par.lower() == toks[1].lower(): 
    1465                             self.dispersion[item][par] = value 
    1466                             return 
    1467         else: 
    1468             # Look for standard parameter 
    1469             for item in self.params.keys(): 
    1470                 if item.lower()== name.lower(): 
    1471                     self.params[item] = value 
    1472                     return 
    1473  
    1474         raise ValueError, "Model does not contain parameter %s" % name 
    1475  
    1476  
    1477     def _set_fixed_params(self): 
    1478         self.fixed = [] 
    1479         for item in self.p_model1.fixed: 
    1480             new_item = "p1" + item 
    1481             self.fixed.append(new_item) 
    1482         for item in self.p_model2.fixed: 
    1483             new_item = "p2" + item 
    1484             self.fixed.append(new_item) 
    1485  
    1486         self.fixed.sort() 
    1487  
    1488  
    1489     def run(self, x = 0.0): 
    1490         self._set_scale_factor() 
    1491         return self.params['scale_factor'] {factor_operator} \ 
    1492 (self.p_model1.run(x) {operator} self.p_model2.run(x)) + self.params['background'] 
    1493  
    1494     def runXY(self, x = 0.0): 
    1495         self._set_scale_factor() 
    1496         return self.params['scale_factor'] {factor_operator} \ 
    1497 (self.p_model1.runXY(x) {operator} self.p_model2.runXY(x)) + self.params['background'] 
    1498  
    1499     ## Now (May27,10) directly uses the model eval function 
    1500     ## instead of the for-loop in Base Component. 
    1501     def evalDistribution(self, x = []): 
    1502         self._set_scale_factor() 
    1503         return self.params['scale_factor'] {factor_operator} \ 
    1504 (self.p_model1.evalDistribution(x) {operator} \ 
    1505 self.p_model2.evalDistribution(x)) + self.params['background'] 
    1506  
    1507     def set_dispersion(self, parameter, dispersion): 
    1508         value= None 
    1509         new_pre = parameter.split("_", 1)[0] 
    1510         new_parameter = parameter.split("_", 1)[1] 
    1511         try: 
    1512             if new_pre == 'p1' and \ 
    1513 new_parameter in self.p_model1.dispersion.keys(): 
    1514                 value= self.p_model1.set_dispersion(new_parameter, dispersion) 
    1515             if new_pre == 'p2' and \ 
    1516 new_parameter in self.p_model2.dispersion.keys(): 
    1517                 value= self.p_model2.set_dispersion(new_parameter, dispersion) 
    1518             self._set_dispersion() 
    1519             return value 
    1520         except: 
    1521             raise 
    1522  
    1523     def fill_description(self, p_model1, p_model2): 
    1524         description = "" 
    1525         description += "This model gives the summation or multiplication of" 
    1526         description += "%s and %s. "% ( p_model1.name, p_model2.name ) 
    1527         self.description += description 
    1528  
    1529 if __name__ == "__main__": 
    1530     m1= Model() 
    1531     #m1.setParam("p1_scale", 25) 
    1532     #m1.setParam("p1_length", 1000) 
    1533     #m1.setParam("p2_scale", 100) 
    1534     #m1.setParam("p2_rg", 100) 
    1535     out1 = m1.runXY(0.01) 
    1536  
    1537     m2= Model() 
    1538     #m2.p_model1.setParam("scale", 25) 
    1539     #m2.p_model1.setParam("length", 1000) 
    1540     #m2.p_model2.setParam("scale", 100) 
    1541     #m2.p_model2.setParam("rg", 100) 
    1542     out2 = m2.p_model1.runXY(0.01) {operator} m2.p_model2.runXY(0.01)\n 
    1543     print "My name is %s."% m1.name 
    1544     print out1, " = ", out2 
    1545     if out1 == out2: 
    1546         print "===> Simple Test: Passed!" 
    1547     else: 
    1548         print "===> Simple Test: Failed!" 
     1213from sasmodels.core import load_model_info 
     1214from sasmodels.sasview_model import make_model_from_info 
     1215 
     1216model_info = load_model_info('{model1}{operator}{model2}', force_mixture=True) 
     1217model_info.name = '{name}'{desc_line} 
     1218Model = make_model_from_info(model_info) 
    15491219""" 
    1550  
    15511220if __name__ == "__main__": 
    15521221#    app = wx.PySimpleApp() 
Note: See TracChangeset for help on using the changeset viewer.