- Timestamp:
- Apr 12, 2020 8:46:57 PM (3 years ago)
- Location:
- trunk
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/GSASIIIO.py
r4374 r4399 2229 2229 def postURL(URL,postdict): 2230 2230 '''Posts a set of values as from a web form. If access fails to an https 2231 site the access is retried with http 2231 site the access is retried with http. 2232 2232 2233 :param str URL: the URL to post; typically something 2233 2234 like 'http://www.../dir/page?' -
trunk/GSASIIconstrGUI.py
r4379 r4399 17 17 from __future__ import division, print_function 18 18 import sys 19 import copy 20 import os.path 19 21 import wx 20 22 import wx.grid as wg 23 import wx.lib.scrolledpanel as wxscroll 21 24 import random as ran 22 25 import numpy as np 23 26 import numpy.ma as ma 24 27 import numpy.linalg as nl 25 import os.path26 28 import GSASIIpath 27 29 GSASIIpath.SetVersionNumber("$Revision$") … … 37 39 import GSASIIobj as G2obj 38 40 import GSASIIspc as G2spc 41 import GSASIIpy3 as G2py3 39 42 VERY_LIGHT_GREY = wx.Colour(235,235,235) 40 43 … … 822 825 varMean = G2obj.fmtVarDescr(var) 823 826 helptext += "\n" + var + " ("+ varMean + ")" 827 # Add ISODISTORT help items 824 828 if '_Explain' in data: 825 if data['_Explain'].get(item[-3]): 829 # this ignores the phase number. TODO: refactor that in 830 hlptxt = None 831 try: 832 hlptxt = data['_Explain'].get(item[-3]) 833 except TypeError: 834 # note that phase RanId is item[-3].phase 835 hlptxt = data['_Explain'].get(str(item[-3].phase)+item[-3].name) 836 if hlptxt: 826 837 helptext += '\n\n' 827 helptext += data['_Explain'][item[-3]]838 helptext += hlptxt 828 839 # typeString = 'NEWVAR' 829 840 # if item[-3]: … … 832 843 # eqString[-1] += ' = New Variable' 833 844 if item[-3]: 834 typeString = item[-3]+ ' = '845 typeString = str(item[-3]) + ' = ' 835 846 else: 836 847 typeString = 'New Variable = ' … … 937 948 constType = 'New Variable' 938 949 if data[name][Id][-3]: 939 varname = data[name][Id][-3]950 varname = str(data[name][Id][-3]) 940 951 else: 941 952 varname = "" … … 945 956 elif data[name][Id][-1] == 'c': 946 957 items = data[name][Id][:-3]+[ 947 [ data[name][Id][-3],'fixed value =']]958 [str(data[name][Id][-3]),'fixed value =']] 948 959 constType = 'Constraint' 949 960 lbl = 'Edit value for each term in constant constraint sum' … … 957 968 return 958 969 try: 959 prev = data[name][Id][:]970 prev = copy.deepcopy(data[name][Id]) 960 971 if dlg.ShowModal() == wx.ID_OK: 961 972 result = dlg.GetData() … … 967 978 data[name][Id][-3] = str(result[-1][0]) 968 979 elif data[name][Id][-1] == 'f': 969 # process the variable name to put in global form (::var)970 varname = str(dlg.newvar[0]).strip().replace(' ','_')971 if varname.startswith('::'):972 varname = varname[2:]973 varname = varname.replace(':',';')974 if varname:975 data[name][Id][-3] = varname976 else:977 data[name][Id][-3] = ''978 980 data[name][Id][-2] = dlg.newvar[1] 981 if type(data[name][Id][-3]) is str: 982 # process the variable name to put in global form (::var) 983 varname = str(dlg.newvar[0]).strip().replace(' ','_') 984 if varname.startswith('::'): 985 varname = varname[2:] 986 varname = varname.replace(':',';') 987 if varname: 988 data[name][Id][-3] = varname 989 else: 990 data[name][Id][-3] = '' 979 991 if not CheckChangedConstraint(): 980 992 data[name][Id] = prev 993 else: 994 data[name][Id] = prev 981 995 except: 982 996 import traceback … … 1086 1100 return 1087 1101 G2obj.IndexAllIds(Histograms,Phases) 1102 for p in Phases: 1103 if 'ISODISTORT' in Phases[p]: 1104 G2frame.dataWindow.ConstraintEdit.Enable(G2G.wxID_SHOWISO,True) 1105 break 1088 1106 ################################################################################## 1089 1107 # patch: convert old-style (str) variables in constraints to G2VarObj objects … … 1177 1195 G2frame.Bind(wx.EVT_MENU, OnAddAtomEquiv, id=G2G.wxID_EQUIVALANCEATOMS) 1178 1196 # G2frame.Bind(wx.EVT_MENU, OnAddRiding, id=G2G.wxID_ADDRIDING) 1197 def OnShowISODISTORT(event): 1198 ShowIsoDistortCalc(G2frame) 1199 G2frame.Bind(wx.EVT_MENU, OnShowISODISTORT, id=G2G.wxID_SHOWISO) 1179 1200 # tab commands 1180 1201 for id in (G2G.wxID_CONSPHASE, … … 2378 2399 G2frame.rbBook.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, OnPageChanged) 2379 2400 wx.CallAfter(OnPageChanged,None) 2401 2402 def ShowIsoDistortCalc(G2frame,phase=None): 2403 '''Compute the ISODISTORT mode values from the current coordinates. 2404 Called in response to the (Phase/Atoms tab) AtomCompute or 2405 Constraints/Edit Constr. "Show ISODISTORT modes" menu item, which 2406 should be enabled only when Phase['ISODISTORT'] is defined. 2407 ''' 2408 def _onClose(event): 2409 dlg.EndModal(wx.ID_CANCEL) 2410 def fmtHelp(item,fullname): 2411 helptext = "A new variable" 2412 if item[-3]: 2413 helptext += " named "+str(item[-3]) 2414 helptext += " is a linear combination of the following parameters:\n" 2415 first = True 2416 for term in item[:-3]: 2417 line = '' 2418 var = str(term[1]) 2419 m = term[0] 2420 if first: 2421 first = False 2422 line += ' = ' 2423 else: 2424 if m >= 0: 2425 line += ' + ' 2426 else: 2427 line += ' - ' 2428 m = abs(m) 2429 line += '%.3f*%s '%(m,var) 2430 varMean = G2obj.fmtVarDescr(var) 2431 helptext += "\n" + line + " ("+ varMean + ")" 2432 helptext += '\n\nISODISTORT full name: '+str(fullname) 2433 return helptext 2434 2435 Histograms,Phases = G2frame.GetUsedHistogramsAndPhasesfromTree() # init for constraint 2436 isophases = [p for p in Phases if 'ISODISTORT' in Phases[p]] 2437 2438 if not isophases: 2439 G2frame.ErrorDialog('no ISODISTORT phases', 2440 'Unexpected error: no ISODISTORT phases') 2441 return 2442 if phase and phase not in isophases: 2443 G2frame.ErrorDialog('not ISODISTORT phase', 2444 'Unexpected error: selected phase is not an ISODISTORT phase') 2445 print('Unexpected error: selected phase is not an ISODISTORT phase', 2446 phase,isophases) 2447 elif not phase and len(isophases) == 1: 2448 phase = isophases[0] 2449 elif not phase: 2450 dlg = wx.SingleChoiceDialog(G2frame,'Select phase from ISODISTORT phases', 2451 'Select Phase',isophases) 2452 if dlg.ShowModal() == wx.ID_OK: 2453 sel = dlg.GetSelection() 2454 phase = isophases[sel] 2455 else: 2456 return 2457 # if len(data.get('Histograms',[])) == 0: 2458 # G2frame.ErrorDialog( 2459 # 'No data', 2460 # 'Sorry, this computation requires that a histogram first be added to the phase' 2461 # ) 2462 # return 2463 2464 covdata = G2frame.GPXtree.GetItemPyData( 2465 G2gd.GetGPXtreeItemId(G2frame,G2frame.root,'Covariance')) 2466 # make a lookup table for named NewVar Phase constraints 2467 sub = G2gd.GetGPXtreeItemId(G2frame,G2frame.root,'Constraints') 2468 Constraints = G2frame.GPXtree.GetItemPyData(sub) 2469 constDict = {} 2470 for c in Constraints['Phase']: 2471 if c[-1] != 'f' or not c[-3]: continue 2472 constDict[str(c[-3])] = c 2473 2474 parmDict,varyList = G2frame.MakeLSParmDict() 2475 2476 dlg = wx.Dialog(G2frame,wx.ID_ANY,'ISODISTORT mode values',#size=(630,400), 2477 style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER) 2478 mainSizer = wx.BoxSizer(wx.VERTICAL) 2479 if 'ISODISTORT' not in Phases[phase]: 2480 G2frame.ErrorDialog('not ISODISTORT phase', 2481 'Unexpected error: selected phase is not an ISODISTORT phase') 2482 return 2483 data = Phases[phase] 2484 ISO = data['ISODISTORT'] 2485 mainSizer.Add(wx.StaticText(dlg,wx.ID_ANY, 2486 'ISODISTORT mode computation for cordinates in phase '+ 2487 str(data['General'].get('Name')))) 2488 aSizer = wx.BoxSizer(wx.HORIZONTAL) 2489 panel1 = wxscroll.ScrolledPanel( 2490 dlg, wx.ID_ANY,#size=(100,200), 2491 style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER) 2492 subSizer1 = wx.FlexGridSizer(cols=2,hgap=5,vgap=2) 2493 panel2 = wxscroll.ScrolledPanel( 2494 dlg, wx.ID_ANY,#size=(100,200), 2495 style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER) 2496 subSizer2 = wx.FlexGridSizer(cols=3,hgap=5,vgap=2) 2497 subSizer1.Add(wx.StaticText(panel1,wx.ID_ANY,'Parameter name ')) 2498 subSizer1.Add(wx.StaticText(panel1,wx.ID_ANY,' value'),0,wx.ALIGN_RIGHT) 2499 subSizer2.Add((-1,-1)) 2500 subSizer2.Add(wx.StaticText(panel2,wx.ID_ANY,'Mode name ')) 2501 subSizer2.Add(wx.StaticText(panel2,wx.ID_ANY,' value'),0,wx.ALIGN_RIGHT) 2502 # ISODISTORT displacive modes 2503 if 'G2VarList' in ISO: 2504 deltaList = [] 2505 for gv,Ilbl in zip(ISO['G2VarList'],ISO['IsoVarList']): 2506 dvar = gv.varname() 2507 var = dvar.replace('::dA','::A') 2508 albl = Ilbl[:Ilbl.rfind('_')] 2509 v = Ilbl[Ilbl.rfind('_')+1:] 2510 pval = ISO['ParentStructure'][albl][['dx','dy','dz'].index(v)] 2511 if var in parmDict: 2512 cval = parmDict[var][0] 2513 else: 2514 dlg.EndModal(wx.ID_CANCEL) 2515 G2frame.ErrorDialog('Atom not found',"No value found for parameter "+str(var)) 2516 return 2517 deltaList.append(cval-pval) 2518 modeVals = np.inner(ISO['Var2ModeMatrix'],deltaList) 2519 for lbl,xyz,var,val,norm,G2mode in zip( 2520 ISO['IsoVarList'],deltaList, 2521 ISO['IsoModeList'],modeVals,ISO['NormList'],ISO['G2ModeList'] ): 2522 #GSASIIpath.IPyBreak() 2523 if str(G2mode) in constDict: 2524 ch = G2G.HelpButton(panel2,fmtHelp(constDict[str(G2mode)],var)) 2525 subSizer2.Add(ch,0,wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER,1) 2526 else: 2527 subSizer2.Add((-1,-1)) 2528 subSizer1.Add(wx.StaticText(panel1,wx.ID_ANY,str(lbl))) 2529 try: 2530 value = G2py3.FormatSigFigs(xyz) 2531 except TypeError: 2532 value = str(xyz) 2533 subSizer1.Add(wx.StaticText(panel1,wx.ID_ANY,value),0,wx.ALIGN_RIGHT) 2534 subSizer2.Add(wx.StaticText(panel2,wx.ID_ANY,str(var))) 2535 try: 2536 value = G2py3.FormatSigFigs(val/norm) 2537 if 'varyList' in covdata: 2538 if str(G2mode) in covdata['varyList']: 2539 sig = covdata['sig'][covdata['varyList'].index(str(G2mode))] 2540 value = G2mth.ValEsd(val/norm,sig/norm) 2541 except TypeError: 2542 value = '?' 2543 subSizer2.Add(wx.StaticText(panel2,wx.ID_ANY,value),0,wx.ALIGN_RIGHT) 2544 #GSASIIpath.IPyBreak() 2545 # ISODISTORT occupancy modes 2546 if 'G2OccVarList' in ISO: 2547 deltaList = [] 2548 for gv,Ilbl in zip(ISO['G2OccVarList'],ISO['OccVarList']): 2549 var = gv.varname() 2550 albl = Ilbl[:Ilbl.rfind('_')] 2551 pval = ISO['BaseOcc'][albl] 2552 if var in parmDict: 2553 cval = parmDict[var][0] 2554 else: 2555 dlg.EndModal(wx.ID_CANCEL) 2556 G2frame.ErrorDialog('Atom not found',"No value found for parameter "+str(var)) 2557 return 2558 deltaList.append(cval-pval) 2559 modeVals = np.inner(ISO['Var2OccMatrix'],deltaList) 2560 for lbl,delocc,var,val,norm,G2mode in zip( 2561 ISO['OccVarList'],deltaList, 2562 ISO['OccModeList'],modeVals,ISO['OccNormList'],ISO['G2OccModeList']): 2563 if str(G2mode) in constDict: 2564 ch = G2G.HelpButton(panel2,fmtHelp(constDict[str(G2mode)],var)) 2565 subSizer2.Add(ch,0,wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER,1) 2566 else: 2567 subSizer2.Add((-1,-1)) 2568 subSizer1.Add(wx.StaticText(panel1,wx.ID_ANY,str(lbl))) 2569 try: 2570 value = G2py3.FormatSigFigs(delocc) 2571 except TypeError: 2572 value = str(delocc) 2573 subSizer1.Add(wx.StaticText(panel1,wx.ID_ANY,value),0,wx.ALIGN_RIGHT) 2574 #subSizer.Add((10,-1)) 2575 subSizer2.Add(wx.StaticText(panel2,wx.ID_ANY,str(var))) 2576 try: 2577 value = G2py3.FormatSigFigs(val/norm) 2578 if 'varyList' in covdata: 2579 if str(G2mode) in covdata['varyList']: 2580 sig = covdata['sig'][covdata['varyList'].index(str(G2mode))] 2581 value = G2mth.ValEsd(val/norm,sig/norm) 2582 except TypeError: 2583 value = '?' 2584 subSizer2.Add(wx.StaticText(panel2,wx.ID_ANY,value),0,wx.ALIGN_RIGHT) 2585 2586 # finish up ScrolledPanel 2587 panel1.SetSizer(subSizer1) 2588 panel2.SetSizer(subSizer2) 2589 panel1.SetAutoLayout(1) 2590 panel1.SetupScrolling() 2591 panel2.SetAutoLayout(1) 2592 panel2.SetupScrolling() 2593 # Allow window to be enlarged but not made smaller 2594 dlg.SetSizer(mainSizer) 2595 w1,l1 = subSizer1.GetSize() 2596 w2,l2 = subSizer2.GetSize() 2597 panel1.SetMinSize((w1+10,200)) 2598 panel2.SetMinSize((w2+20,200)) 2599 aSizer.Add(panel1,1, wx.ALL|wx.EXPAND,1) 2600 aSizer.Add(panel2,2, wx.ALL|wx.EXPAND,1) 2601 mainSizer.Add(aSizer,1, wx.ALL|wx.EXPAND,1) 2602 2603 # make OK button 2604 btnsizer = wx.BoxSizer(wx.HORIZONTAL) 2605 btn = wx.Button(dlg, wx.ID_CLOSE) 2606 btn.Bind(wx.EVT_BUTTON,_onClose) 2607 btnsizer.Add(btn) 2608 mainSizer.Add(btnsizer, 0, wx.ALIGN_CENTER|wx.ALL, 5) 2609 2610 mainSizer.Fit(dlg) 2611 dlg.SetMinSize(dlg.GetSize()) 2612 dlg.ShowModal() 2613 dlg.Destroy() -
trunk/GSASIIdataGUI.py
r4396 r4399 1041 1041 sub = GetGPXtreeItemId(self,self.root,'Constraints') # was created in CheckNotebook if needed 1042 1042 Constraints = self.GPXtree.GetItemPyData(sub) 1043 # TODO: make sure that NEWVAR names are unique here?1044 1043 for i in rd.Constraints: 1045 1044 if type(i) is dict: 1046 #for j in i: print j,' --> ',i[j]1047 1045 if '_Explain' not in Constraints: Constraints['_Explain'] = {} 1048 1046 Constraints['_Explain'].update(i) … … 5309 5307 # help='Add H atom riding constraints between atom parameter values') 5310 5308 # self.ConstraintEdit.Enable(G2G.wxID_ADDRIDING,False) 5309 G2G.Define_wxId('wxID_SHOWISO') 5310 self.ConstraintEdit.Append(G2G.wxID_SHOWISO,'Show ISODISTORT modes', 5311 'Show ISODISTORT mode values for all phases') 5312 self.ConstraintEdit.Enable(G2G.wxID_SHOWISO,False) 5313 # for DEBUG only 5314 #def OnShowISODISTORT(event): 5315 # import imp 5316 # imp.reload(G2cnstG) # for testing changes to GSASIIconstrGUI 5317 # G2cnstG.ShowIsoDistortCalc(G2frame) 5318 #G2frame.Bind(wx.EVT_MENU, OnShowISODISTORT, id=G2G.wxID_SHOWISO) 5319 # end DEBUG 5320 5311 5321 self.PostfillDataMenu() 5312 5322 -
trunk/GSASIImapvars.py
r4379 r4399 162 162 A "Hold" constraint is stored as described for type "h" in the 163 163 :ref:`constraint definitions table <Constraint_definitions_table>`. 164 165 .. _Constraints_processing: 164 166 165 167 Constraint Processing … … 1445 1447 s3 = ' sig :' 1446 1448 s1 += '%15s' % (name) 1447 s2 += '%15. 4f' % (val)1449 s2 += '%15.5f' % (val) 1448 1450 if esd is None: 1449 1451 s3 += '%15s' % ('n/a') 1450 else: 1451 s3 += '%15. 4f' % (esd)1452 else: 1453 s3 += '%15.5f' % (esd) 1452 1454 1453 1455 def ComputeDepESD(covMatrix,varyList,parmDict): -
trunk/GSASIIobj.py
r4370 r4399 1000 1000 letter or string flag value (such as I or A for iso/anisotropic). 1001 1001 1002 ISODISTORT implementation 1003 ------------------------------ 1004 1005 CIFs prepared with the ISODISTORT web site 1006 https://stokes.byu.edu/iso/isodistort_version5.6.1/isodistort.php 1007 [B. J. Campbell, H. T. Stokes, D. E. Tanner, and D. M. Hatch, "ISODISPLACE: An Internet Tool for Exploring Structural Distortions." J. Appl. Cryst. 39, 607-614 (2006).] 1008 can be read into GSAS-II using import CIF. This will cause constraints to be established for structural distortion modes read from the CIF. 1009 At present, of the five types of modes only displacive(``_iso_displacivemode``...) and occupancy (``_iso_occupancymode``...) are processed. Not yet processed: ``_iso_magneticmode``..., ``_iso_rotationalmode``... & ``_iso_strainmode``... 1010 1011 The CIF importer :mod:`G2phase_CIF` implements class :class:`G2phase_CIF.CIFPhaseReader` which offers two methods associated with ISODISTORT (ID) input. Method :meth:`G2phase_CIF.CIFPhaseReader.ISODISTORT_test` 1012 checks to see if a CIF block contains the loops with ``_iso_displacivemode_label`` or ``_iso_occupancymode_label`` items. 1013 If so, method :meth:`G2phase_CIF.CIFPhaseReader.ISODISTORT_proc` is called to read and interpret them. 1014 The results are placed into the reader object's ``.Phase`` class variable as a dict item with key ``'ISODISTORT'``. 1015 1016 Note that each mode ID has a long label with a name such as Pm-3m[1/2,1/2,1/2]R5+(a,a,0)[La:b:dsp]T1u(a). Function :func:`G2phase_CIF.ISODISTORT_shortLbl` is used to create a short name for this, 1017 such as R5_T1u(a) which is made unique by addition of _n if the short name is duplicated. 1018 As each mode is processed, a constraint corresponding to that mode is 1019 created and is added to list in the reader object's ``.Constraints`` class variable. Items placed into that list can either be a list, which corresponds to a function (new var) type :ref:`constraint definition <Constraints_table>` entry, or an item can be a dict, which provides help information for each constraint. 1020 1021 ------------------------------ 1022 Displacive modes 1023 ------------------------------ 1024 1025 The coordinate variables, as named by ISODISTORT, are placed in 1026 ``.Phase['ISODISTORT']['IsoVarList']`` and the corresponding :class:`GSASIIobj.G2VarObj` objects for each are placed in ``.Phase['ISODISTORT']['G2VarList']``. The mode variables, 1027 as named by ISODISTORT, are placed in ``.Phase['ISODISTORT']['IsoModeList']`` and the corresponding :class:`GSASIIobj.G2VarObj` objects for each are placed in ``.Phase['ISODISTORT']['G2ModeList']``. 1028 [Use ``str(G2VarObj)`` to get the variable name from the G2VarObj object, but note that the phase number, *n*, for the prefix "*n*::" cannot be determined as the phase number is not yet assigned.] 1029 1030 Displacive modes are a bit complex in that they relate to delta displacements, relative to an offset value for each coordinate, and because the modes are normalized, while GSAS-II also uses displacements, but these are added to the coordinates after each refinement cycle and the delta values are set to zero. ISODISTORT uses fixed offsets (subtracted from the actual position to obtain the delta values) that are taken from ``_iso_coordinate_formula`` and these are placed in ``.Phase['ISODISTORT']['ParentStructure]`` (keyed by atom label). The normalization factors (which the delta values are divided by) are taken from ``_iso_displacivemodenorm_value`` and are placed in ``.Phase['ISODISTORT']['NormList']`` in the same order as as ``...['IsoModeList']`` and 1031 ``...['G2ModeList']``. 1032 1033 The CIF contains a sparse matrix, from the ``loop_`` containing 1034 ``_iso_displacivemodematrix_value`` which provides the equations for determining the mode values from the coordinates, that matrix is placed in ``.Phase['ISODISTORT']['Mode2VarMatrix']``. The matrix is inverted to produce 1035 ``.Phase['ISODISTORT']['Var2ModeMatrix']``, which determines how to compute the 1036 mode values from the delta coordinate values. These values are used for the 1037 in :func:`GSASIIconstrGUI.ShowIsoDistortCalc` which shows coordinate and mode 1038 values, the latter with s.u. values. 1039 1040 1041 ------------------------------ 1042 Occupancy modes 1043 ------------------------------ 1044 1045 1046 The delta occupancy variables, as named by ISODISTORT, are placed in 1047 ``.Phase['ISODISTORT']['OccVarList']`` and the corresponding :class:`GSASIIobj.G2VarObj` objects for each are placed in ``.Phase['ISODISTORT']['G2OccVarList']``. The mode variables, as named by ISODISTORT, are placed in ``.Phase['ISODISTORT']['OccModeList']`` and the corresponding :class:`GSASIIobj.G2VarObj` objects for each are placed in ``.Phase['ISODISTORT']['G2OccModeList']``. 1048 1049 Occupancy modes, like Displacive modes, are also refined as delta values. However, GSAS-II directly refines the fractional occupancies. 1050 Offset values for each atom, are taken from ``_iso_occupancy_formula`` and are placed in 1051 ``.Phase['ISODISTORT']['ParentOcc]``. 1052 (Offset values are subtracted from the actual position to obtain the delta values.) 1053 Modes are normalized (where the mode values are divided by the normalization factor) 1054 are taken from ``_iso_occupancymodenorm_value`` and are placed in ``.Phase['ISODISTORT']['OccNormList']`` in the same order as as ``...['OccModeList']`` and 1055 ``...['G2OccModeList']``. 1056 1057 The CIF contains a sparse matrix, from the ``loop_`` containing 1058 ``_iso_occupancymodematrix_value``, which provides the equations for determining the mode values from the coordinates. That matrix is placed in ``.Phase['ISODISTORT']['Occ2VarMatrix']``. The matrix is inverted to produce 1059 ``.Phase['ISODISTORT']['Var2OccMatrix']``, which determines how to compute the 1060 mode values from the delta coordinate values. 1061 1062 1063 ------------------------------ 1064 Mode Computations 1065 ------------------------------ 1066 1067 Constraints are processed after the CIF has been read in 1068 :meth:`GSASIIdataGUI.GSASII.OnImportPhase` or 1069 :meth:`GSASIIscriptable.G2Project.add_phase` by moving them from the reader 1070 object's ``.Constraints`` class variable to 1071 the Constraints tree entry's ['Phase'] list (for list items defining constraints) or 1072 the Constraints tree entry's ['_Explain'] dict (for dict items defining constraint help information) 1073 1074 The information in ``.Phase['ISODISTORT']`` is used 1075 in :func:`GSASIIconstrGUI.ShowIsoDistortCalc` which shows coordinate and mode 1076 values, the latter with s.u. values. This can be called from the Constraints and Phase/Atoms tree items. 1077 1078 Before each refinement, constraints are processed as 1079 :ref:`described elsewhere <Constraints_processing>`. After a refinement 1080 is complete, :func:`GSASIImapvars.PrintIndependentVars` shows the 1081 shifts and s.u.'s on the refined modes, using GSAS-II values, but 1082 :func:`GSASIIstrIO.PrintISOmodes` prints the ISODISTORT modes as computed 1083 in the web site. 1084 1002 1085 1003 1086 *Classes and routines* -
trunk/GSASIIphsGUI.py
r4398 r4399 58 58 import GSASIImath as G2mth 59 59 import GSASIIpwd as G2pwd 60 import GSASIIpy3 as G2py361 60 import GSASIIobj as G2obj 62 61 import GSASIIctrlGUI as G2G … … 4093 4092 4094 4093 def OnIsoDistortCalc(event): 4095 '''Compute the ISODISTORT mode values from the current coordinates. 4096 Called in response to the (Phase/Atoms tab) AtomCompute 4097 "Compute ISODISTORT mode values" menu item, which should be enabled 4098 only when Phase['ISODISTORT'] is defined. 4099 ''' 4100 def _onClose(event): 4101 dlg.EndModal(wx.ID_CANCEL) 4102 def fmtHelp(item,fullname): 4103 helptext = "A new variable" 4104 if item[-3]: 4105 helptext += " named "+str(item[-3]) 4106 helptext += " is a linear combination of the following parameters:\n" 4107 first = True 4108 for term in item[:-3]: 4109 line = '' 4110 var = str(term[1]) 4111 m = term[0] 4112 if first: 4113 first = False 4114 line += ' = ' 4115 else: 4116 if m >= 0: 4117 line += ' + ' 4118 else: 4119 line += ' - ' 4120 m = abs(m) 4121 line += '%.3f*%s '%(m,var) 4122 varMean = G2obj.fmtVarDescr(var) 4123 helptext += "\n" + line + " ("+ varMean + ")" 4124 helptext += '\n\nISODISTORT full name: '+str(fullname) 4125 return helptext 4126 4127 if 'ISODISTORT' not in data: 4128 raise Exception("Should not happen: 'ISODISTORT' not in data") 4129 if len(data.get('Histograms',[])) == 0: 4130 G2frame.ErrorDialog( 4131 'No data', 4132 'Sorry, this computation requires that a histogram first be added to the phase' 4133 ) 4134 return 4135 Histograms,Phases = G2frame.GetUsedHistogramsAndPhasesfromTree() # init for constraint 4136 # make a lookup table for constraints 4137 sub = G2gd.GetGPXtreeItemId(G2frame,G2frame.root,'Constraints') 4138 Constraints = G2frame.GPXtree.GetItemPyData(sub) 4139 constDict = {} 4140 for item in Constraints: 4141 if item.startswith('_'): continue 4142 for c in Constraints[item]: 4143 if c[-1] != 'f' or not c[-3]: continue 4144 constDict[c[-3]] = c 4145 4146 ISO = data['ISODISTORT'] 4147 parmDict,varyList = G2frame.MakeLSParmDict() 4148 4149 dlg = wx.Dialog(G2frame,wx.ID_ANY,'ISODISTORT mode values',#size=(630,400), 4150 style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER) 4151 mainSizer = wx.BoxSizer(wx.VERTICAL) 4152 mainSizer.Add(wx.StaticText(dlg,wx.ID_ANY, 4153 'ISODISTORT mode computation for cordinates in phase '+ 4154 str(data['General'].get('Name')))) 4155 aSizer = wx.BoxSizer(wx.HORIZONTAL) 4156 panel1 = wxscroll.ScrolledPanel( 4157 dlg, wx.ID_ANY,#size=(100,200), 4158 style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER) 4159 subSizer1 = wx.FlexGridSizer(cols=2,hgap=5,vgap=2) 4160 panel2 = wxscroll.ScrolledPanel( 4161 dlg, wx.ID_ANY,#size=(100,200), 4162 style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER) 4163 subSizer2 = wx.FlexGridSizer(cols=3,hgap=5,vgap=2) 4164 subSizer1.Add(wx.StaticText(panel1,wx.ID_ANY,'Parameter name ')) 4165 subSizer1.Add(wx.StaticText(panel1,wx.ID_ANY,' value'),0,wx.ALIGN_RIGHT) 4166 subSizer2.Add((-1,-1)) 4167 subSizer2.Add(wx.StaticText(panel2,wx.ID_ANY,'Mode name ')) 4168 subSizer2.Add(wx.StaticText(panel2,wx.ID_ANY,' value'),0,wx.ALIGN_RIGHT) 4169 if 'G2VarList' in ISO: 4170 deltaList = [] 4171 for gv,Ilbl in zip(ISO['G2VarList'],ISO['IsoVarList']): 4172 dvar = gv.varname() 4173 var = dvar.replace('::dA','::A') 4174 albl = Ilbl[:Ilbl.rfind('_')] 4175 v = Ilbl[Ilbl.rfind('_')+1:] 4176 pval = ISO['ParentStructure'][albl][['dx','dy','dz'].index(v)] 4177 if var in parmDict: 4178 cval = parmDict[var][0] 4179 else: 4180 dlg.EndModal(wx.ID_CANCEL) 4181 G2frame.ErrorDialog('Atom not found',"No value found for parameter "+str(var)) 4182 return 4183 deltaList.append(cval-pval) 4184 modeVals = np.inner(ISO['Var2ModeMatrix'],deltaList) 4185 for lbl,xyz,var,val,G2var in zip(ISO['IsoVarList'],deltaList, 4186 ISO['IsoModeList'],modeVals,ISO['G2ModeList']): 4187 if G2var in constDict: 4188 ch = G2G.HelpButton(panel2,fmtHelp(constDict[G2var],var)) 4189 subSizer2.Add(ch,0,wx.LEFT|wx.RIGHT|WACV|wx.ALIGN_CENTER,1) 4190 else: 4191 subSizer2.Add((-1,-1)) 4192 subSizer1.Add(wx.StaticText(panel1,wx.ID_ANY,str(lbl))) 4193 try: 4194 value = G2py3.FormatSigFigs(xyz) 4195 except TypeError: 4196 value = str(xyz) 4197 subSizer1.Add(wx.StaticText(panel1,wx.ID_ANY,value),0,wx.ALIGN_RIGHT) 4198 subSizer2.Add(wx.StaticText(panel2,wx.ID_ANY,str(var))) 4199 try: 4200 value = G2py3.FormatSigFigs(val) 4201 except TypeError: 4202 value = str(val) 4203 subSizer2.Add(wx.StaticText(panel2,wx.ID_ANY,value),0,wx.ALIGN_RIGHT) 4204 if 'G2OccVarList' in ISO: 4205 deltaList = [] 4206 for gv,Ilbl in zip(ISO['G2OccVarList'],ISO['OccVarList']): 4207 var = gv.varname() 4208 albl = Ilbl[:Ilbl.rfind('_')] 4209 #v = Ilbl[Ilbl.rfind('_')+1:] 4210 pval = ISO['BaseOcc'][albl] 4211 if var in parmDict: 4212 cval = parmDict[var][0] 4213 else: 4214 dlg.EndModal(wx.ID_CANCEL) 4215 G2frame.ErrorDialog('Atom not found',"No value found for parameter "+str(var)) 4216 return 4217 deltaList.append(cval-pval) 4218 modeVals = np.inner(ISO['Var2OccMatrix'],deltaList) 4219 for lbl,xyz,var,val,G2var in zip(ISO['OccVarList'],deltaList, 4220 ISO['OccModeList'],modeVals,ISO['G2OccModeList']): 4221 if G2var in constDict: 4222 ch = G2G.HelpButton(panel2,fmtHelp(constDict[G2var],var)) 4223 subSizer2.Add(ch,0,wx.LEFT|wx.RIGHT|WACV|wx.ALIGN_CENTER,1) 4224 else: 4225 subSizer2.Add((-1,-1)) 4226 subSizer1.Add(wx.StaticText(panel1,wx.ID_ANY,str(lbl))) 4227 try: 4228 value = G2py3.FormatSigFigs(xyz) 4229 except TypeError: 4230 value = str(xyz) 4231 subSizer1.Add(wx.StaticText(panel1,wx.ID_ANY,value),0,wx.ALIGN_RIGHT) 4232 #subSizer.Add((10,-1)) 4233 subSizer2.Add(wx.StaticText(panel2,wx.ID_ANY,str(var))) 4234 try: 4235 value = G2py3.FormatSigFigs(val) 4236 except TypeError: 4237 value = str(val) 4238 subSizer2.Add(wx.StaticText(panel2,wx.ID_ANY,value),0,wx.ALIGN_RIGHT) 4239 4240 # finish up ScrolledPanel 4241 panel1.SetSizer(subSizer1) 4242 panel2.SetSizer(subSizer2) 4243 panel1.SetAutoLayout(1) 4244 panel1.SetupScrolling() 4245 panel2.SetAutoLayout(1) 4246 panel2.SetupScrolling() 4247 # Allow window to be enlarged but not made smaller 4248 dlg.SetSizer(mainSizer) 4249 w1,l1 = subSizer1.GetSize() 4250 w2,l2 = subSizer2.GetSize() 4251 panel1.SetMinSize((w1+10,200)) 4252 panel2.SetMinSize((w2+20,200)) 4253 aSizer.Add(panel1,1, wx.ALL|wx.EXPAND,1) 4254 aSizer.Add(panel2,2, wx.ALL|wx.EXPAND,1) 4255 mainSizer.Add(aSizer,1, wx.ALL|wx.EXPAND,1) 4256 4257 # make OK button 4258 btnsizer = wx.BoxSizer(wx.HORIZONTAL) 4259 btn = wx.Button(dlg, wx.ID_CLOSE) 4260 btn.Bind(wx.EVT_BUTTON,_onClose) 4261 btnsizer.Add(btn) 4262 mainSizer.Add(btnsizer, 0, wx.ALIGN_CENTER|wx.ALL, 5) 4263 4264 mainSizer.Fit(dlg) 4265 dlg.SetMinSize(dlg.GetSize()) 4266 dlg.ShowModal() 4267 dlg.Destroy() 4268 4094 G2cnstG.ShowIsoDistortCalc(G2frame,data['General']['Name']) 4095 4269 4096 def OnReImport(event): 4270 4097 generalData = data['General'] -
trunk/GSASIIscriptable.py
r4334 r4399 2240 2240 self.data['Phases'][phasename] = phasereader.Phase 2241 2241 2242 # process constraints, currently generated only from ISODISTORT CIFs 2242 2243 if phasereader.Constraints: 2243 2244 Constraints = self.data['Constraints'] -
trunk/GSASIIstrIO.py
r4371 r4399 40 40 import GSASIImath as G2mth 41 41 import GSASIIfiles as G2fil 42 import GSASIIpy3 as G2py3 42 43 43 44 sind = lambda x: np.sin(x*np.pi/180.) … … 211 212 if len(D) > 1: 212 213 # add extra dict terms for input variable name and vary flag 213 if varname is not None: 214 if varname.startswith('::'): 215 varname = varname[2:].replace(':',';') 214 if varname is not None: 215 varname = str(varname) # in case this is a G2VarObj 216 if ':' in varname: 217 D['_name'] = varname 216 218 else: 217 varname = varname.replace(':',';') 218 D['_name'] = '::' + varname 219 D['_name'] = '::' + varname 219 220 D['_vary'] = varyFlag == True # force to bool 220 221 constDict.append(D) … … 367 368 pFile.write(FPstr+'\n') 368 369 pFile.write(FPPstr+'\n') 370 371 def PrintISOmodes(pFile,Phases,parmDict,sigDict): 372 '''Prints the values for the ISODISTORT modes into the project's 373 .lst file after a refinement. 374 ''' 375 for phase in Phases: 376 if 'ISODISTORT' not in Phases[phase]: continue 377 data = Phases[phase] 378 ISO = data['ISODISTORT'] 379 if 'G2VarList' in ISO: 380 deltaList = [] 381 for gv,Ilbl in zip(ISO['G2VarList'],ISO['IsoVarList']): 382 dvar = gv.varname() 383 var = dvar.replace('::dA','::A') 384 albl = Ilbl[:Ilbl.rfind('_')] 385 v = Ilbl[Ilbl.rfind('_')+1:] 386 pval = ISO['ParentStructure'][albl][['dx','dy','dz'].index(v)] 387 if var in parmDict: 388 cval = parmDict[var] 389 else: 390 print('PrintISOmodes Error: Atom not found',"No value found for parameter "+str(var)) 391 return 392 deltaList.append(cval-pval) 393 modeVals = np.inner(ISO['Var2ModeMatrix'],deltaList) 369 394 395 if 'G2OccVarList' in ISO: 396 deltaOccList = [] 397 for gv,Ilbl in zip(ISO['G2OccVarList'],ISO['OccVarList']): 398 var = gv.varname() 399 albl = Ilbl[:Ilbl.rfind('_')] 400 pval = ISO['BaseOcc'][albl] 401 if var in parmDict: 402 cval = parmDict[var] 403 else: 404 print('PrintISOmodes Error: Atom not found',"No value found for parameter "+str(var)) 405 return 406 deltaOccList.append(cval-pval) 407 modeOccVals = np.inner(ISO['Var2OccMatrix'],deltaOccList) 408 409 if 'G2VarList' in ISO: 410 pFile.write('\n ISODISTORT Displacive Modes for phase {}\n'.format(data['General'].get('Name',''))) 411 l = str(max([len(i) for i in ISO['IsoModeList']])+3) 412 fmt = ' {:'+l+'}{}' 413 for var,val,norm,G2mode in zip( 414 ISO['IsoModeList'],modeVals,ISO['NormList'],ISO['G2ModeList'] ): 415 try: 416 value = G2py3.FormatSigFigs(val/norm) 417 if str(G2mode) in sigDict: 418 value = G2mth.ValEsd(val/norm,sigDict[str(G2mode)]/norm) 419 except TypeError: 420 value = '?' 421 pFile.write(fmt.format(var,value)+'\n') 422 423 if 'G2OccVarList' in ISO: 424 pFile.write('\n ISODISTORT Occupancy Modes for phase {}\n'.format(data['General'].get('Name',''))) 425 l = str(max([len(i) for i in ISO['OccModeList']])+3) 426 fmt = ' {:'+l+'}{}' 427 for var,val,norm,G2mode in zip( 428 ISO['OccModeList'],modeOccVals,ISO['OccNormList'],ISO['G2OccModeList'] ): 429 try: 430 value = G2py3.FormatSigFigs(val/norm) 431 if str(G2mode) in sigDict: 432 value = G2mth.ValEsd(val/norm,sigDict[str(G2mode)]/norm) 433 except TypeError: 434 value = '?' 435 pFile.write(fmt.format(var,value)+'\n') 436 370 437 def GetPhaseNames(GPXfile): 371 438 ''' Returns a list of phase names found under 'Phases' in GSASII gpx file -
trunk/GSASIIstrMain.py
r4370 r4399 275 275 G2stIO.SetRigidBodyModels(parmDict,sigDict,rigidbodyDict,printFile) 276 276 G2stIO.SetPhaseData(parmDict,sigDict,Phases,rbIds,covData,restraintDict,printFile) 277 G2stIO.PrintISOmodes(printFile,Phases,parmDict,sigDict) 277 278 G2stIO.SetHistogramPhaseData(parmDict,sigDict,Phases,Histograms,calcControls['FFtables'],pFile=printFile) 278 279 G2stIO.SetHistogramData(parmDict,sigDict,Histograms,calcControls['FFtables'],pFile=printFile) -
trunk/imports/G2phase_CIF.py
r4379 r4399 34 34 GSASIIpath.SetVersionNumber("$Revision$") 35 35 import CifFile as cif # PyCifRW from James Hester 36 #debug = GSASIIpath.GetConfigValue('debug')37 debug = False36 debug = GSASIIpath.GetConfigValue('debug') 37 #debug = False 38 38 39 39 class CIFPhaseReader(G2obj.ImportPhase): … … 648 648 '''Process ISODISTORT items to create constraints etc. 649 649 Constraints are generated from information extracted from 650 loop _'s beginning with _iso_ and are placed into650 loops beginning with _iso_ and are placed into 651 651 self.Constraints, which contains a list of 652 652 :ref:`constraints tree items <Constraint_definitions_table>` … … 660 660 varLookup = {'dx':'dAx','dy':'dAy','dz':'dAz','do':'Afrac'} 661 661 'Maps ISODISTORT parm names to GSAS-II names' 662 # used for all types of modes 663 self.Constraints = [] 664 explaination = {} 662 665 #---------------------------------------------------------------------- 663 666 # read in the ISODISTORT displacement modes 664 667 #---------------------------------------------------------------------- 665 self.Constraints = []666 explaination = {}667 668 if blk.get('_iso_displacivemode_label'): 668 669 modelist = [] 669 670 shortmodelist = [] 670 for lbl in blk.get('_iso_displacivemode_label'): 671 idlist = [] 672 for id,lbl in zip( 673 blk.get('_iso_displacivemode_ID'), 674 blk.get('_iso_displacivemode_label')): 675 idlist.append(int(id)) 671 676 modelist.append(lbl) 672 677 ISODISTORT_shortLbl(lbl,shortmodelist) # shorten & make unique 678 # just in case the items are not ordered increasing by id, sort them here 679 modelist = [i for i,j in sorted(zip(modelist,idlist),key=lambda k:k[1])] 680 shortmodelist = [i for i,j in sorted(zip(shortmodelist,idlist),key=lambda k:k[1])] 673 681 # read in the coordinate offset variables names and map them to G2 names/objects 674 682 coordVarLbl = [] 675 G2varLbl = []676 683 G2varObj = [] 684 idlist = [] 677 685 error = False 678 for lbl in blk.get('_iso_deltacoordinate_label'): 686 for id,lbl in zip( 687 blk.get('_iso_deltacoordinate_ID'), 688 blk.get('_iso_deltacoordinate_label') ): 689 idlist.append(int(id)) 679 690 coordVarLbl.append(lbl) 680 691 if '_' in lbl: … … 696 707 error = True 697 708 continue 698 G2varLbl.append('::'+var+':'+str(anum)) # variable name, less phase ID699 709 G2varObj.append(G2obj.G2VarObj( 700 710 (self.Phase['ranId'],None,var,ranIdlookup[albl]) … … 702 712 if error: 703 713 raise Exception("Error decoding variable labels") 714 # just in case the items are not ordered increasing by id, sort them here 715 coordVarLbl = [i for i,j in sorted(zip(coordVarLbl,idlist),key=lambda k:k[1])] 716 G2varObj = [i for i,j in sorted(zip(G2varObj,idlist),key=lambda k:k[1])] 704 717 705 718 if len(G2varObj) != len(modelist): … … 711 724 for lbl,exp in zip( 712 725 blk.get('_iso_coordinate_label'), 713 blk.get('_iso_coordinate_formula'), 714 ): 726 blk.get('_iso_coordinate_formula') ): 715 727 if '_' in lbl: 716 728 albl = lbl[:lbl.rfind('_')] … … 750 762 displacivemodeInvmatrix = np.linalg.inv(displacivemodematrix) 751 763 # create the constraints 764 modeVarList = [] 752 765 for i,row in enumerate(displacivemodeInvmatrix): 753 766 constraint = [] … … 755 768 if k == 0: continue 756 769 constraint.append([k,G2varObj[j]]) 757 constraint += [shortmodelist[i],False,'f'] 770 modeVar = G2obj.G2VarObj( 771 (self.Phase['ranId'],None,shortmodelist[i],None)) 772 modeVarList.append(modeVar) 773 constraint += [modeVar,False,'f'] 758 774 self.Constraints.append(constraint) 775 # normilization constants 776 normlist = [] 777 idlist = [] 778 for id,exp in zip( 779 blk.get('_iso_displacivemodenorm_ID'), 780 blk.get('_iso_displacivemodenorm_value'), 781 ): 782 idlist.append(int(id)) 783 normlist.append(float(exp)) 784 normlist = [i for i,j in sorted(zip(normlist,idlist),key=lambda k:k[1])] 759 785 #---------------------------------------------------------------------- 760 786 # save the ISODISTORT info for "mode analysis" 761 787 if 'ISODISTORT' not in self.Phase: self.Phase['ISODISTORT'] = {} 762 788 self.Phase['ISODISTORT'].update({ 763 'IsoModeList' : modelist, 764 'G2ModeList' : shortmodelist, 789 # coordinate items 765 790 'IsoVarList' : coordVarLbl, 766 791 'G2VarList' : G2varObj, 767 792 'ParentStructure' : ParentCoordinates, 793 # mode items 794 'IsoModeList' : modelist, 795 'G2ModeList' : modeVarList, 796 'NormList' : normlist, 797 # transform matrices 768 798 'Var2ModeMatrix' : displacivemodeInvmatrix, 769 799 'Mode2VarMatrix' : displacivemodematrix, … … 771 801 # make explaination dictionary 772 802 for mode,shortmode in zip(modelist,shortmodelist): 773 explaination[shortmode] = "ISODISTORT full name "+str(mode) 803 explaination[str(self.Phase['ranId'])+shortmode] = ( 804 "ISODISTORT full name "+str(mode)) 774 805 #---------------------------------------------------------------------- 775 806 # now read in the ISODISTORT occupancy modes … … 778 809 modelist = [] 779 810 shortmodelist = [] 780 for lbl in blk.get('_iso_occupancymode_label'): 811 idlist = [] 812 for id,lbl in zip( 813 blk.get('_iso_occupancymode_ID'), 814 blk.get('_iso_occupancymode_label')): 815 idlist.append(int(id)) 781 816 modelist.append(lbl) 782 817 ISODISTORT_shortLbl(lbl,shortmodelist) # shorten & make unique 818 # just in case the items are not ordered increasing by id, sort them here 819 modelist = [i for i,j in sorted(zip(modelist,idlist),key=lambda k:k[1])] 820 shortmodelist = [i for i,j in sorted(zip(shortmodelist,idlist),key=lambda k:k[1])] 783 821 # read in the coordinate offset variables names and map them to G2 names/objects 784 822 occVarLbl = [] 785 G2varLbl = []786 823 G2varObj = [] 824 idlist = [] 787 825 error = False 788 for lbl in blk.get('_iso_deltaoccupancy_label'): 826 for id,lbl in zip( 827 blk.get('_iso_deltaoccupancy_ID'), 828 blk.get('_iso_deltaoccupancy_label') ): 829 idlist.append(int(id)) 789 830 occVarLbl.append(lbl) 790 831 if '_' in lbl: … … 806 847 error = True 807 848 continue 808 G2varLbl.append('::'+var+':'+str(anum)) # variable name, less phase ID809 849 G2varObj.append(G2obj.G2VarObj( 810 850 (self.Phase['ranId'],None,var,ranIdlookup[albl]) … … 812 852 if error: 813 853 raise Exception("Error decoding variable labels") 854 # just in case the items are not ordered increasing by id, sort them here 855 occVarLbl = [i for i,j in sorted(zip(occVarLbl,idlist),key=lambda k:k[1])] 856 G2varObj = [i for i,j in sorted(zip(G2varObj,idlist),key=lambda k:k[1])] 814 857 815 858 if len(G2varObj) != len(modelist): … … 818 861 819 862 error = False 820 Parent Coordinates= {}863 ParentOcc = {} 821 864 for lbl,exp in zip( 822 865 blk.get('_iso_occupancy_label'), 823 blk.get('_iso_occupancy_formula'), 824 ): 866 blk.get('_iso_occupancy_formula') ): 825 867 if '_' in lbl: 826 868 albl = lbl[:lbl.rfind('_')] … … 841 883 error = True 842 884 continue 843 Parent Coordinates[albl] = val885 ParentOcc[albl] = val 844 886 if error: 845 887 raise Exception("Error decoding occupancy labels") … … 854 896 occupancymodeInvmatrix = np.linalg.inv(occupancymodematrix) 855 897 # create the constraints 898 modeVarList = [] 856 899 for i,row in enumerate(occupancymodeInvmatrix): 857 900 constraint = [] … … 859 902 if k == 0: continue 860 903 constraint.append([k,G2varObj[j]]) 861 constraint += [shortmodelist[i],False,'f'] 904 modeVar = G2obj.G2VarObj( 905 (self.Phase['ranId'],None,shortmodelist[i],None)) 906 modeVarList.append(modeVar) 907 constraint += [modeVar,False,'f'] 862 908 self.Constraints.append(constraint) 909 # normilization constants 910 normlist = [] 911 idlist = [] 912 for id,exp in zip( 913 blk.get('_iso_occupancymodenorm_ID'), 914 blk.get('_iso_occupancymodenorm_value'), 915 ): 916 idlist.append(int(id)) 917 normlist.append(float(exp)) 918 normlist = [i for i,j in sorted(zip(normlist,idlist),key=lambda k:k[1])] 863 919 #---------------------------------------------------------------------- 864 920 # save the ISODISTORT info for "mode analysis" 865 921 if 'ISODISTORT' not in self.Phase: self.Phase['ISODISTORT'] = {} 866 922 self.Phase['ISODISTORT'].update({ 867 'OccModeList' : modelist, 868 'G2OccModeList' : shortmodelist, 923 # coordinate items 869 924 'OccVarList' : occVarLbl, 870 925 'G2OccVarList' : G2varObj, 871 'BaseOcc' : ParentCoordinates, 926 'BaseOcc' : ParentOcc, 927 # mode items 928 'OccModeList' : modelist, 929 'G2OccModeList' : modeVarList, 930 'OccNormList' : normlist, 931 # transform matrices 872 932 'Var2OccMatrix' : occupancymodeInvmatrix, 873 933 'Occ2VarMatrix' : occupancymodematrix, … … 875 935 # make explaination dictionary 876 936 for mode,shortmode in zip(modelist,shortmodelist): 877 explaination[shortmode] = "ISODISTORT full name "+str(mode) 937 explaination[str(self.Phase['ranId'])+shortmode] = ( 938 "ISODISTORT full name "+str(mode)) 878 939 #---------------------------------------------------------------------- 879 940 # done with read … … 883 944 if not debug: return 884 945 885 # debug: show the mode var to mode relations 886 print("shortname ==> ISODISTORT full name") 887 for mode,shortmode in zip(modelist,shortmodelist): 888 print(shortmode,' ==>', mode) 889 print() 890 for i,row in enumerate(displacivemodeInvmatrix): 891 l = '' 892 for j,(lbl,k) in enumerate(zip(coordVarLbl,row)): 893 if k == 0: continue 894 if l: l += ' + ' 895 #l += lbl+' * '+str(k) 896 l += G2varLbl[j]+' * '+str(k) 897 print( str(i) + ': '+shortmodelist[i]+' = '+l) 898 print( 70*'=') 899 900 # debug: Get the ISODISTORT offset values 901 coordVarDelta = {} 902 for lbl,val in zip( 903 blk.get('_iso_deltacoordinate_label'), 904 blk.get('_iso_deltacoordinate_value'),): 905 coordVarDelta[lbl] = float(val) 906 modeVarDelta = {} 907 for lbl,val in zip( 908 blk.get('_iso_displacivemode_label'), 909 blk.get('_iso_displacivemode_value'),): 910 modeVarDelta[lbl] = cif.get_number_with_esd(val)[0] 911 912 print( 70*'=') 913 # compute the mode values from the reported coordinate deltas 914 for i,row in enumerate(displacivemodeInvmatrix): 915 l = '' 916 sl = '' 917 s = 0. 918 for lbl,k in zip(coordVarLbl,row): 919 if k == 0: continue 920 if l: l += ' + ' 921 l += lbl+' * '+str(k) 922 if sl: sl += ' + ' 923 sl += str(coordVarDelta[lbl])+' * '+str(k) 924 s += coordVarDelta[lbl] * k 925 print('a'+str(i)+' = '+l) 926 print('\t= '+sl) 927 print(modelist[i],shortmodelist[i],modeVarDelta[modelist[i]],s) 928 print() 929 930 print( 70*'=') 931 # compute the coordinate displacements from the reported mode values 932 for i,lbl,row in zip(range(len(coordVarLbl)),coordVarLbl,displacivemodematrix): 933 l = '' 934 sl = '' 935 s = 0.0 936 for j,k in enumerate(row): 937 if k == 0: continue 938 if l: l += ' + ' 939 l += 'a'+str(j+1)+' * '+str(k) 940 if sl: sl += ' + ' 941 sl += str(shortmodelist[j]) +' = '+ str(modeVarDelta[modelist[j]]) + ' * '+str(k) 942 s += modeVarDelta[modelist[j]] * k 943 print( lbl+' = '+l) 944 print( '\t= '+sl) 945 print( lbl,G2varLbl[i],coordVarDelta[lbl],s) 946 print() 947 948 # determine the coordinate delta values from deviations from the parent structure 949 for atmline in self.Phase['Atoms']: 950 lbl = atmline[0] 951 x,y,z = atmline[3:6] 952 if lbl not in ParentCoordinates: 946 # debug: show displacive mode var to mode relations 947 if 'IsoVarList' in self.Phase['ISODISTORT']: 948 # coordinate items 949 #coordVarLbl = self.Phase['ISODISTORT']['IsoVarList'] 950 G2varObj = self.Phase['ISODISTORT']['G2VarList'] 951 #ParentCoordinates = self.Phase['ISODISTORT']['ParentStructure'] 952 # mode items 953 modelist = self.Phase['ISODISTORT']['IsoModeList'] 954 modeVarList = self.Phase['ISODISTORT']['G2ModeList'] 955 normlist = self.Phase['ISODISTORT']['NormList'] 956 # transform matrices 957 #displacivemodeInvmatrix = self.Phase['ISODISTORT']['Var2ModeMatrix'] 958 #displacivemodematrix = self.Phase['ISODISTORT']['Mode2VarMatrix'] 959 960 print( 70*'=') 961 print('\nVar2ModeMatrix' ,'IsoVarList' ) 962 for i,row in enumerate(displacivemodeInvmatrix): 963 l = '' 964 for j,(lbl,k) in enumerate(zip(coordVarLbl,row)): 965 if k == 0: continue 966 if l: l += ' + ' 967 #l += lbl+' * '+str(k) 968 l += str(G2varObj[j])+' * '+str(k) 969 print( str(i) + ': '+str(modeVarList[i])+' = '+l) 970 971 # Get the ISODISTORT offset values 972 coordVarDelta = {} 973 for lbl,val in zip( 974 blk.get('_iso_deltacoordinate_label'), 975 blk.get('_iso_deltacoordinate_value'),): 976 coordVarDelta[lbl] = float(val) 977 modeVarDelta = {} 978 for lbl,val in zip( 979 blk.get('_iso_displacivemode_label'), 980 blk.get('_iso_displacivemode_value'),): 981 modeVarDelta[lbl] = cif.get_number_with_esd(val)[0] 982 983 print( 70*'=') 984 print('\nInverse relations using Var2ModeMatrix, NormList, IsoVarList') 985 # compute the mode values from the reported coordinate deltas 986 for i,(row,n) in enumerate(zip(displacivemodeInvmatrix,normlist)): 987 l = '' 988 for lbl,k in zip(coordVarLbl,row): 989 if k == 0: continue 990 if l: l += ' + ' 991 l += lbl+' * '+str(k) 992 print('a'+str(i)+' = '+str(modeVarList[i])+' = ('+l+')/'+str(n)) 993 print('\nCalculation checks\n') 994 for i,(row,n) in enumerate(zip(displacivemodeInvmatrix,normlist)): 995 #l = '' 996 sl = '' 997 s = 0. 998 for lbl,k in zip(coordVarLbl,row): 999 if k == 0: continue 1000 #if l: l += ' + ' 1001 #l += lbl+' * '+str(k) 1002 if sl: sl += ' + ' 1003 sl += str(coordVarDelta[lbl])+' * '+str(k) 1004 s += coordVarDelta[lbl] * k 1005 print(str(modeVarList[i]),'=','('+sl+') / ',n,'=',s/n) 1006 print(' ?= ',modeVarDelta[modelist[i]]) 1007 print() 1008 1009 print( 70*'=') 1010 print('\nDirect relations using Mode2VarMatrix, NormList, IsoVarList') 1011 # compute the coordinate displacements from the reported mode values 1012 DeltaCoords = {} 1013 for i,lbl,row in zip(range(len(coordVarLbl)),coordVarLbl,displacivemodematrix): 1014 l = '' 1015 s = 0.0 1016 at,d = lbl.split('_') 1017 if at not in DeltaCoords: 1018 DeltaCoords[at] = [0,0,0] 1019 for j,(k,n) in enumerate(zip(row,normlist)): 1020 if k == 0: continue 1021 if l: l += ' + ' 1022 l += str(n)+' * '+str(modeVarList[j])+' * '+str(k) 1023 s += n * modeVarDelta[modelist[j]] * k 1024 print( lbl,'=',str(G2varObj[i]),'=',l,'=',s,'\n') 1025 if d == 'dx': 1026 DeltaCoords[at][0] = s 1027 elif d == 'dy': 1028 DeltaCoords[at][1] = s 1029 elif d == 'dz': 1030 DeltaCoords[at][2] = s 1031 else: 1032 print('unexpected',d) 1033 1034 print( 70*'=') 1035 print('\nCoordinate checks') 1036 print('\nComputed') 1037 for at in sorted(DeltaCoords): 1038 s = at 1039 for i in range(3): 1040 s += ' ' 1041 s += str(ParentCoordinates[at][i]+DeltaCoords[at][i]) 1042 print(s) 1043 1044 # determine the coordinate delta values from deviations from the parent structure 1045 print('\nFrom CIF') 1046 for atmline in self.Phase['Atoms']: 1047 lbl = atmline[0] 1048 x,y,z = atmline[3:6] 953 1049 print( lbl,x,y,z) 954 continue 955 px,py,pz = ParentCoordinates[lbl] 956 print( lbl,x,y,z,x-px,y-py,z-pz) 957 print('\nGenerated constraints') 958 for i in self.Constraints: 959 if type(i) is dict: 960 print('\n constraint help') 961 for key in i: 962 print('\t',key,i[key]) 963 elif i[-1] == 'f': 964 print('\n\tNewvar',i[-3],' =') 965 for m,j in i[:-3]: 966 print('\t\t+',m,' * ',j) 967 else: 968 print(' unexpected: ',repr(i)) 969 1050 1051 print( 70*'=') 1052 print('\nGenerated constraints') 1053 for i in self.Constraints: 1054 if type(i) is dict: 1055 print('\nconstraint help dict') 1056 for key in i: 1057 print('\t',key,':',i[key]) 1058 elif i[-1] == 'f': 1059 print('\n\t',i[-3],' =') 1060 for m,j in i[:-3]: 1061 print('\t\t+',m,' * ',j,' ',repr(j)) 1062 else: 1063 print(' unexpected: ',repr(i)) 1064 print("\nG2name ==> ISODISTORT full name", 1065 ".Phase['ISODISTORT']['IsoModeList']", 1066 ".Phase['ISODISTORT']['G2ModeList']") 1067 for mode,G2mode in zip(modelist,modeVarList): 1068 print(" ?::"+str(G2mode),' ==>', mode) 1069 1070 #====================================================================== 1071 # debug: show occupancy mode var to mode relations 1072 if 'G2OccVarList' in self.Phase['ISODISTORT']: 1073 # coordinate items 1074 #occVarLbl = self.Phase['ISODISTORT']['OccVarList'] 1075 G2varObj = self.Phase['ISODISTORT']['G2OccVarList'] 1076 #ParentOcc = self.Phase['ISODISTORT']['BaseOcc'] 1077 # mode items 1078 modelist = self.Phase['ISODISTORT']['OccModeList'] 1079 modeVarList = self.Phase['ISODISTORT']['G2OccModeList'] 1080 normlist = self.Phase['ISODISTORT']['OccNormList'] 1081 # transform matrices 1082 #occupancymodeInvmatrix = self.Phase['ISODISTORT']['Var2OccMatrix'] 1083 #occupancymodematrix = self.Phase['ISODISTORT']['Occ2VarMatrix'] 1084 1085 print( 70*'=') 1086 print('\nVar2OccMatrix' ,'OccVarList' ) 1087 for i,row in enumerate(occupancymodeInvmatrix): 1088 l = '' 1089 for j,(lbl,k) in enumerate(zip(occVarLbl,row)): 1090 if k == 0: continue 1091 if l: l += ' + ' 1092 #l += lbl+' * '+str(k) 1093 l += str(G2varObj[j])+' * '+str(k) 1094 print( str(i) + ': '+str(modeVarList[i])+' = '+l) 1095 1096 # Get the ISODISTORT offset values 1097 occVarDelta = {} 1098 for lbl,val in zip( 1099 blk.get('_iso_deltaoccupancy_label'), 1100 blk.get('_iso_deltaoccupancy_value'),): 1101 occVarDelta[lbl] = float(val) 1102 modeVarDelta = {} 1103 for lbl,val in zip( 1104 blk.get('_iso_occupancymode_label'), 1105 blk.get('_iso_occupancymode_value'),): 1106 modeVarDelta[lbl] = cif.get_number_with_esd(val)[0] 1107 1108 print( 70*'=') 1109 print('\nInverse relations using Var2OccModeMatrix, OccNormList, OccVarList') 1110 # compute the mode values from the reported coordinate deltas 1111 for i,(row,n) in enumerate(zip(occupancymodeInvmatrix,normlist)): 1112 l = '' 1113 for lbl,k in zip(occVarLbl,row): 1114 if k == 0: continue 1115 if l: l += ' + ' 1116 l += lbl+' * '+str(k) 1117 print('a'+str(i)+' = '+str(modeVarList[i])+' = ('+l+')/'+str(n)) 1118 print('\nCalculation checks\n') 1119 for i,(row,n) in enumerate(zip(occupancymodeInvmatrix,normlist)): 1120 #l = '' 1121 sl = '' 1122 s = 0. 1123 for lbl,k in zip(occVarLbl,row): 1124 if k == 0: continue 1125 #if l: l += ' + ' 1126 #l += lbl+' * '+str(k) 1127 if sl: sl += ' + ' 1128 sl += str(occVarDelta[lbl])+' * '+str(k) 1129 s += occVarDelta[lbl] * k 1130 print(str(modeVarList[i]),'=','('+sl+') / ',n,'=',s/n) 1131 print(' ?= ',modeVarDelta[modelist[i]]) 1132 print() 1133 1134 print( 70*'=') 1135 print('\nDirect relations using Occ2VarMatrix, OccNormList, OccVarList') 1136 # compute the coordinate displacements from the reported mode values 1137 Occ = {} 1138 for i,lbl,row in zip(range(len(occVarLbl)),occVarLbl,occupancymodematrix): 1139 l = '' 1140 s = 0.0 1141 for j,(k,n) in enumerate(zip(row,normlist)): 1142 if k == 0: continue 1143 if l: l += ' + ' 1144 l += str(n)+' * '+str(modeVarList[j])+' * '+str(k) 1145 s += n * modeVarDelta[modelist[j]] * k 1146 print( lbl,'=',str(G2varObj[i]),'=',l,'=',s,'\n') 1147 j = lbl.split('_')[0] 1148 Occ[j] = ParentOcc[j]+s 1149 1150 # determine the coordinate delta values from deviations from the parent structure 1151 print('\nOccupancy from CIF vs computed') 1152 for atmline in self.Phase['Atoms']: 1153 lbl = atmline[0] 1154 print( lbl,atmline[6],Occ[lbl]) 1155 1156 print( 70*'=') 1157 print('\nGenerated constraints') 1158 for i in self.Constraints: 1159 if type(i) is dict: 1160 print('\nconstraint help dict') 1161 for key in i: 1162 print('\t',key,':',i[key]) 1163 elif i[-1] == 'f': 1164 print('\n\t',i[-3],' =') 1165 for m,j in i[:-3]: 1166 print('\t\t+',m,' * ',j,' ',repr(j)) 1167 else: 1168 print(' unexpected: ',repr(i)) 1169 print("\nG2name ==> ISODISTORT full name", 1170 ".Phase['ISODISTORT']['OccModeList']", 1171 ".Phase['ISODISTORT']['G2OccModeList']") 1172 for mode,G2mode in zip(modelist,modeVarList): 1173 print(" ?::"+str(G2mode),' ==>', mode) 1174 970 1175 def ISODISTORT_shortLbl(lbl,shortmodelist): 971 1176 '''Shorten model labels and remove special characters
Note: See TracChangeset
for help on using the changeset viewer.