source: trunk/GSASIIspc.py @ 1625

Last change on this file since 1625 was 1625, checked in by vondreele, 7 years ago

add a parameter to result from G2stIO.GetPhaseData?
add modulation functions to G2Math
add modulation names to G2obj
implement various wave types for modulations
plot position modulation wave function on contour plots
implement shift of modulation plot by +/-/0 keys
temporarily default G2spc.GetSSfxuinel to 1,-1 site symm.
move maxSSwave dict out of parmDict - now in controlDict
implement import of Sawtooth parms from J2K files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 121.0 KB
Line 
1# -*- coding: utf-8 -*-
2"""
3*GSASIIspc: Space group module*
4-------------------------------
5
6Space group interpretation routines. Note that space group information is
7stored in a :ref:`Space Group (SGData)<SGData_table>` object.
8
9"""
10########### SVN repository information ###################
11# $Date: 2015-01-08 22:24:32 +0000 (Thu, 08 Jan 2015) $
12# $Author: vondreele $
13# $Revision: 1625 $
14# $URL: trunk/GSASIIspc.py $
15# $Id: GSASIIspc.py 1625 2015-01-08 22:24:32Z vondreele $
16########### SVN repository information ###################
17import numpy as np
18import numpy.ma as ma
19import numpy.linalg as nl
20import scipy.optimize as so
21import math
22import sys
23import os.path as ospath
24
25import GSASIIpath
26GSASIIpath.SetVersionNumber("$Revision: 1625 $")
27import pyspg
28
29npsind = lambda x: np.sin(x*np.pi/180.)
30npcosd = lambda x: np.cos(x*np.pi/180.)
31DEBUG = True
32   
33################################################################################
34#### Space group codes
35################################################################################
36
37def SpcGroup(SGSymbol):
38    """
39    Determines cell and symmetry information from a short H-M space group name
40
41    :param SGSymbol: space group symbol (string) with spaces between axial fields
42    :returns: (SGError,SGData)
43       * SGError = 0 for no errors; >0 for errors (see SGErrors below for details)
44       * SGData - is a dict (see :ref:`Space Group object<SGData_table>`) with entries:
45       
46             * 'SpGrp': space group symbol, slightly cleaned up
47             * 'SGLaue':  one of '-1', '2/m', 'mmm', '4/m', '4/mmm', '3R',
48               '3mR', '3', '3m1', '31m', '6/m', '6/mmm', 'm3', 'm3m'
49             * 'SGInv': boolean; True if centrosymmetric, False if not
50             * 'SGLatt': one of 'P', 'A', 'B', 'C', 'I', 'F', 'R'
51             * 'SGUniq': one of 'a', 'b', 'c' if monoclinic, '' otherwise
52             * 'SGCen': cell centering vectors [0,0,0] at least
53             * 'SGOps': symmetry operations as [M,T] so that M*x+T = x'
54             * 'SGSys': one of 'triclinic', 'monoclinic', 'orthorhombic',
55               'tetragonal', 'rhombohedral', 'trigonal', 'hexagonal', 'cubic'
56             * 'SGPolax': one of '', 'x', 'y', 'x y', 'z', 'x z', 'y z',
57               'xyz', '111' for arbitrary axes
58             * 'SGPtGrp': one of 32 point group symbols (with some permutations)
59                - filled by SGPtGroup - is external (KE) part of supersymmetry point group
60             * 'SSGKl': default internal (Kl) part of supersymmetry point group; modified
61             in supersymmetry stuff depending on chosen modulation vector for Mono & Ortho
62
63    """
64    LaueSym = ('-1','2/m','mmm','4/m','4/mmm','3R','3mR','3','3m1','31m','6/m','6/mmm','m3','m3m')
65    LattSym = ('P','A','B','C','I','F','R')
66    UniqSym = ('','','a','b','c','',)
67    SysSym = ('triclinic','monoclinic','orthorhombic','tetragonal','rhombohedral','trigonal','hexagonal','cubic')
68    SGData = {}
69    SGInfo = pyspg.sgforpy(SGSymbol)
70    SGData['SpGrp'] = SGSymbol.strip().lower().capitalize()
71    SGData['SGLaue'] = LaueSym[SGInfo[0]-1]
72    SGData['SGInv'] = bool(SGInfo[1])
73    SGData['SGLatt'] = LattSym[SGInfo[2]-1]
74    SGData['SGUniq'] = UniqSym[SGInfo[3]+1]
75    if SGData['SGLatt'] == 'P':
76        SGData['SGCen'] = np.array(([0,0,0],))
77    elif SGData['SGLatt'] == 'A':
78        SGData['SGCen'] = np.array(([0,0,0],[0,.5,.5]))
79    elif SGData['SGLatt'] == 'B':
80        SGData['SGCen'] = np.array(([0,0,0],[.5,0,.5]))
81    elif SGData['SGLatt'] == 'C':
82        SGData['SGCen'] = np.array(([0,0,0],[.5,.5,0,]))
83    elif SGData['SGLatt'] == 'I':
84        SGData['SGCen'] = np.array(([0,0,0],[.5,.5,.5]))
85    elif SGData['SGLatt'] == 'F':
86        SGData['SGCen'] = np.array(([0,0,0],[0,.5,.5],[.5,0,.5],[.5,.5,0,]))
87    elif SGData['SGLatt'] == 'R':
88        SGData['SGCen'] = np.array(([0,0,0],[1./3.,2./3.,2./3.],[2./3.,1./3.,1./3.]))
89    SGData['SGOps'] = []
90    for i in range(SGInfo[5]):
91        Mat = np.array(SGInfo[6][i])
92        Trns = np.array(SGInfo[7][i])
93        SGData['SGOps'].append([Mat,Trns])
94    if SGData['SGLaue'] in '-1':
95        SGData['SGSys'] = SysSym[0]
96    elif SGData['SGLaue'] in '2/m':
97        SGData['SGSys'] = SysSym[1]
98    elif SGData['SGLaue'] in 'mmm':
99        SGData['SGSys'] = SysSym[2]
100    elif SGData['SGLaue'] in ['4/m','4/mmm']:
101        SGData['SGSys'] = SysSym[3]
102    elif SGData['SGLaue'] in ['3R','3mR']:
103        SGData['SGSys'] = SysSym[4]
104    elif SGData['SGLaue'] in ['3','3m1','31m']:
105        SGData['SGSys'] = SysSym[5]
106    elif SGData['SGLaue'] in ['6/m','6/mmm']:
107        SGData['SGSys'] = SysSym[6]
108    elif SGData['SGLaue'] in ['m3','m3m']:
109        SGData['SGSys'] = SysSym[7]
110    SGData['SGPolax'] = SGpolar(SGData)
111    SGData['SGPtGrp'],SGData['SSGKl'] = SGPtGroup(SGData)
112    return SGInfo[8],SGData
113
114def SGErrors(IErr):
115    '''
116    Interprets the error message code from SpcGroup. Used in SpaceGroup.
117   
118    :param IErr: see SGError in :func:`SpcGroup`
119    :returns:
120        ErrString - a string with the error message or "Unknown error"
121    '''
122
123    ErrString = [' ',
124        'Less than 2 operator fields were found',
125        'Illegal Lattice type, not P, A, B, C, I, F or R',
126        'Rhombohedral lattice requires a 3-axis',
127        'Minus sign does not preceed 1, 2, 3, 4 or 6',
128        'Either a 5-axis anywhere or a 3-axis in field not allowed',
129        ' ',
130        'I for COMPUTED GO TO out of range.',
131        'An a-glide mirror normal to A not allowed',
132        'A b-glide mirror normal to B not allowed',
133        'A c-glide mirror normal to C not allowed',
134        'D-glide in a primitive lattice not allowed',
135        'A 4-axis not allowed in the 2nd operator field',
136        'A 6-axis not allowed in the 2nd operator field',
137        'More than 24 matrices needed to define group',
138        ' ',
139        'Improper construction of a rotation operator',
140        'Mirror following a / not allowed',
141        'A translation conflict between operators',
142        'The 2bar operator is not allowed',
143        '3 fields are legal only in R & m3 cubic groups',
144        'Syntax error. Expected I -4 3 d at this point',
145        ' ',
146        'A or B centered tetragonal not allowed',
147        ' ','unknown error in sgroup',' ',' ',' ',
148        'Illegal character in the space group symbol',
149        ]
150    try:
151        return ErrString[IErr]
152    except:
153        return "Unknown error"
154
155def SGpolar(SGData):
156    '''
157    Determine identity of polar axes if any
158    '''
159    POL = ('','x','y','x y','z','x z','y z','xyz','111')
160    NP = [1,2,4]
161    NPZ = [0,1]
162    for M,T in SGData['SGOps']:
163        for i in range(3):
164            if M[i][i] <= 0.: NP[i] = 0
165        if M[0][2] > 0: NPZ[0] = 8
166        if M[1][2] > 0: NPZ[1] = 0
167    NPol = (NP[0]+NP[1]+NP[2]+NPZ[0]*NPZ[1])*(1-int(SGData['SGInv']))
168    return POL[NPol]
169   
170def SGPtGroup(SGData):
171    '''
172    Determine point group of the space group - done after space group symbol has
173    been evaluated by SpcGroup. Only short symbols are allowed
174   
175    :param SGData: from :func SpcGroup
176    returns SSGPtGrp & SSGKl (only defaults for Mono & Ortho)
177    '''
178    Flds = SGData['SpGrp'].split()
179    if len(Flds) < 2:
180        return '',[]
181    if SGData['SGLaue'] == '-1':    #triclinic
182        if '-' in Flds[1]:
183            return '-1',[-1,]
184        else:
185            return '1',[1,]
186    elif SGData['SGLaue'] == '2/m': #monoclinic - default for 2D modulation vector
187        if '/' in SGData['SpGrp']:
188            return '2/m',[-1,1]
189        elif '2' in SGData['SpGrp']:
190            return '2',[-1,]
191        else:
192            return 'm',[1,]
193    elif SGData['SGLaue'] == 'mmm': #orthorhombic
194        if SGData['SpGrp'].count('2') == 3:
195            return '222',[-1,-1,-1]
196        elif SGData['SpGrp'].count('2') == 1:
197            if SGData['SGPolax'] == 'x':
198                return '2mm',[-1,1,1]
199            elif SGData['SGPolax'] == 'y':
200                return 'm2m',[1,-1,1]
201            elif SGData['SGPolax'] == 'z':
202                return 'mm2',[1,1,-1]
203        else:
204            return 'mmm',[1,1,1]
205    elif SGData['SGLaue'] == '4/m': #tetragonal
206        if '/' in SGData['SpGrp']:
207            return '4/m',[1,-1]
208        elif '-' in Flds[1]:
209            return '-4',[-1,]
210        else:
211            return '4',[1,]
212    elif SGData['SGLaue'] == '4/mmm':
213        if '/' in SGData['SpGrp']:
214            return '4/mmm',[1,-1,1,1]
215        elif '-' in Flds[1]:
216            if '2' in Flds[2]:
217                return '-42m',[-1,-1,1]
218            else:
219                return '-4m2',[-1,1,-1]             
220        elif '2' in Flds[2:]:
221            return '422',[1,-1,-1]
222        else:
223            return '4mm',[1,1,1]
224    elif SGData['SGLaue'] in ['3','3R']:  #trigonal/rhombohedral
225        if '-' in Flds[1]:
226            return '-3',[-1,]
227        else:
228            return '3',[1,]
229    elif SGData['SGLaue'] == '3mR' or 'R' in Flds[0]:
230        if '2' in Flds[2]:
231            return '32',[1,-1]
232        elif '-' in Flds[1]:
233            return '-3m',[-1,1]
234        else:
235            return '3m',[1,1]
236    elif SGData['SGLaue'] == '3m1':
237        if '2' in Flds[2]:
238            return '321',[1,-1,1]
239        elif '-' in Flds[1]:
240            return '-3m1',[-1,1,1]
241        else:
242            return '3m1',[1,1,1]
243    elif SGData['SGLaue'] == '31m':
244        if '2' in Flds[3]:
245            return '312',[1,1,-1]
246        elif '-' in Flds[1]:
247            return '-31m',[-1,1,1]
248        else:
249            return '31m',[1,1,1]
250    elif SGData['SGLaue'] == '6/m': #hexagonal
251        if '/' in SGData['SpGrp']:
252            return '6/m',[1,-1]
253        elif '-' in SGData['SpGrp']:
254            return '-6',[-1,]
255        else:
256            return '6',[1,]
257    elif SGData['SGLaue'] == '6/mmm':
258        if '/' in SGData['SpGrp']:
259            return '6/mmm',[1,-1,1,1]
260        elif '-' in Flds[1]:
261            if '2' in Flds[2]:
262                return '-62m',[-1,-1,1]
263            else:
264                return '-6m2',[-1,1,-1]                 
265        elif '2' in Flds[2:]:
266            return '622',[1,-1,-1]
267        else:
268            return '6mm',[1,1,1]   
269    elif SGData['SGLaue'] == 'm3':      #cubic - no (3+1) supersymmetry
270        if '2' in Flds[1]:
271            return '23',[]
272        else: 
273            return 'm3',[]
274    elif SGData['SGLaue'] == 'm3m':
275        if '4' in Flds[1]:
276            if '-' in Flds[1]:
277                return '-43m',[]
278            else:
279                return '432',[]
280        else:
281            return 'm-3m',[]
282   
283def SGPrint(SGData):
284    '''
285    Print the output of SpcGroup in a nicely formatted way. Used in SpaceGroup
286
287    :param SGData: from :func:`SpcGroup`
288    :returns:
289        SGText - list of strings with the space group details
290        SGTable - list of strings for each of the operations
291    '''
292    Mult = len(SGData['SGCen'])*len(SGData['SGOps'])*(int(SGData['SGInv'])+1)
293    SGText = []
294    SGText.append(' Space Group: '+SGData['SpGrp'])
295    CentStr = 'centrosymmetric'
296    if not SGData['SGInv']:
297        CentStr = 'non'+CentStr
298    if SGData['SGLatt'] in 'ABCIFR':
299        SGText.append(' The lattice is '+CentStr+' '+SGData['SGLatt']+'-centered '+SGData['SGSys'].lower())
300    else:
301        SGText.append(' The lattice is '+CentStr+' '+'primitive '+SGData['SGSys'].lower()) 
302    SGText.append(' The Laue symmetry is '+SGData['SGLaue'])
303    if 'SGPtGrp' in SGData:         #patch
304        SGText.append(' The lattice point group is '+SGData['SGPtGrp'])
305    SGText.append(' Multiplicity of a general site is '+str(Mult))
306    if SGData['SGUniq'] in ['a','b','c']:
307        SGText.append(' The unique monoclinic axis is '+SGData['SGUniq'])
308    if SGData['SGInv']:
309        SGText.append(' The inversion center is located at 0,0,0')
310    if SGData['SGPolax']:
311        SGText.append(' The location of the origin is arbitrary in '+SGData['SGPolax'])
312    SGText.append(' ')
313    if SGData['SGLatt'] == 'P':
314        SGText.append(' The equivalent positions are:\n')
315    else:   
316        SGText.append(' The equivalent positions are:')
317        SGText.append(' ('+Latt2text(SGData['SGLatt'])+')+\n')
318    SGTable = []
319    for i,Opr in enumerate(SGData['SGOps']):
320        SGTable.append('(%2d) %s'%(i+1,MT2text(Opr)))
321    return SGText,SGTable
322
323def AllOps(SGData):
324    '''
325    Returns a list of all operators for a space group, including those for
326    centering and a center of symmetry
327   
328    :param SGData: from :func:`SpcGroup`
329    :returns: (SGTextList,offsetList,symOpList,G2oprList) where
330
331      * SGTextList: a list of strings with formatted and normalized
332        symmetry operators.
333      * offsetList: a tuple of (dx,dy,dz) offsets that relate the GSAS-II
334        symmetry operation to the operator in SGTextList and symOpList.
335        these dx (etc.) values are added to the GSAS-II generated
336        positions to provide the positions that are generated
337        by the normalized symmetry operators.       
338      * symOpList: a list of tuples with the normalized symmetry
339        operations as (M,T) values
340        (see ``SGOps`` in the :ref:`Space Group object<SGData_table>`)
341      * G2oprList: The GSAS-II operations for each symmetry operation as
342        a tuple with (center,mult,opnum), where center is (0,0,0), (0.5,0,0),
343        (0.5,0.5,0.5),...; where mult is 1 or -1 for the center of symmetry
344        and opnum is the number for the symmetry operation, in ``SGOps``
345        (starting with 0).
346    '''
347    SGTextList = []
348    offsetList = []
349    symOpList = []
350    G2oprList = []
351    onebar = (1,)
352    if SGData['SGInv']:
353        onebar += (-1,)
354    for cen in SGData['SGCen']:
355        for mult in onebar:
356            for j,(M,T) in enumerate(SGData['SGOps']):
357                offset = [0,0,0]
358                Tprime = (mult*T)+cen
359                for i in range(3):
360                    while Tprime[i] < 0:
361                        Tprime[i] += 1
362                        offset[i] += 1
363                    while Tprime[i] >= 1:
364                        Tprime[i] += -1
365                        offset[i] += -1
366                Opr = [mult*M,Tprime]
367                OPtxt = MT2text(Opr)
368                SGTextList.append(OPtxt.replace(' ',''))
369                offsetList.append(tuple(offset))
370                symOpList.append((mult*M,Tprime))
371                G2oprList.append((cen,mult,j))
372    return SGTextList,offsetList,symOpList,G2oprList
373   
374def MT2text(Opr):
375    "From space group matrix/translation operator returns text version"
376    XYZ = ('-Z','-Y','-X','X-Y','ERR','Y-X','X','Y','Z')
377    TRA = ('   ','ERR','1/6','1/4','1/3','ERR','1/2','ERR','2/3','3/4','5/6','ERR')
378    Fld = ''
379    M,T = Opr
380    for j in range(3):
381        IJ = int(round(2*M[j][0]+3*M[j][1]+4*M[j][2]+4))%12
382        IK = int(round(T[j]*12))%12
383        if IK:
384            if IJ < 3:
385                Fld += (TRA[IK]+XYZ[IJ]).rjust(5)
386            else:
387                Fld += (TRA[IK]+'+'+XYZ[IJ]).rjust(5)
388        else:
389            Fld += XYZ[IJ].rjust(5)
390        if j != 2: Fld += ', '
391    return Fld
392   
393def Latt2text(Latt):
394    "From lattice type ('P',A', etc.) returns ';' delimited cell centering vectors"
395    lattTxt = {'A':'0,0,0; 0,1/2,1/2','B':'0,0,0; 1/2,0,1/2',
396        'C':'0,0,0; 1/2,1/2,0','I':'0,0,0; 1/2,1/2,1/2',
397        'F':'0,0,0; 0,1/2,1/2; 1/2,0,1/2; 1/2,1/2,0',
398        'R':'0,0,0; 1/3,2/3,2/3; 2/3,1/3,1/3','P':'0,0,0'}
399    return lattTxt[Latt]   
400       
401def SpaceGroup(SGSymbol):
402    '''
403    Print the output of SpcGroup in a nicely formatted way.
404
405    :param SGSymbol: space group symbol (string) with spaces between axial fields
406    :returns: nothing
407    '''
408    E,A = SpcGroup(SGSymbol)
409    if E > 0:
410        print SGErrors(E)
411        return
412    for l in SGPrint(A):
413        print l
414       
415################################################################################
416#### Superspace group codes
417################################################################################
418       
419def SSpcGroup(SGData,SSymbol):
420    """
421    Determines supersymmetry information from superspace group name; currently only for (3+1) superlattices
422
423    :param SGData: space group data structure as defined in SpcGroup above.
424    :param SSymbol: superspace group symbol extension (string) defining modulation direction & generator info.
425    :returns: (SSGError,SSGData)
426       * SGError = 0 for no errors; >0 for errors (see SGErrors below for details)
427       * SSGData - is a dict (see :ref:`Superspace Group object<SSGData_table>`) with entries:
428       
429             * 'SSpGrp': superspace group symbol extension to space group symbol, accidental spaces removed
430             * 'SSGCen': 4D cell centering vectors [0,0,0,0] at least
431             * 'SSGOps': 4D symmetry operations as [M,T] so that M*x+T = x'
432
433    """
434   
435    def checkModSym():
436        '''
437        Checks to see if proposed modulation form is allowed for Laue group
438        '''
439        if LaueId in [0,] and LaueModId in [0,]:
440            return True
441        elif LaueId in [1,]:
442            try:
443                if modsym.index('1/2') != ['A','B','C'].index(SGData['SGLatt']):
444                    return False
445                if 'I'.index(SGData['SGLatt']) and modsym.count('1/2') not in [0,2]:
446                    return False
447            except ValueError:
448                pass
449            if SGData['SGUniq'] == 'a' and LaueModId in [5,6,7,8,9,10,]:
450                return True
451            elif SGData['SGUniq'] == 'b' and LaueModId in [3,4,13,14,15,16,]:
452                return True
453            elif SGData['SGUniq'] == 'c' and LaueModId in [1,2,19,20,21,22,]:
454                return True
455        elif LaueId in [2,] and LaueModId in [i+7 for i in range(18)]:
456            try:
457                if modsym.index('1/2') != ['A','B','C'].index(SGData['SGLatt']):
458                    return False
459                if SGData['SGLatt'] in ['I','F',] and modsym.index('1/2'):
460                    return False
461            except ValueError:
462                pass
463            return True
464        elif LaueId in [3,4,] and LaueModId in [19,22,]:
465            try:
466                if SGData['SGLatt'] == 'I' and modsym.count('1/2'):
467                    return False
468            except ValueError:
469                pass
470            return True
471        elif LaueId in [7,8,9,] and LaueModId in [19,25,]:
472            if (SGData['SGLatt'] == 'R' or SGData['SGPtGrp'] in ['3m1','-3m1']) and modsym.count('1/3'):
473                return False
474            return True
475        elif LaueId in [10,11,] and LaueModId in [19,]:
476            return True
477        return False
478       
479    def fixMonoOrtho():
480        mod = ''.join(modsym).replace('1/2','0').replace('1','0')
481        if SGData['SGPtGrp'] in ['2','m']:  #OK
482            if mod in ['a00','0b0','00g']:
483                result = [i*-1 for i in SGData['SSGKl']]
484            else:
485                result = SGData['SSGKl'][:]
486            if '/' in mod:
487                return [i*-1 for i in result]
488            else:
489                return result
490        elif SGData['SGPtGrp'] == '2/m':    #OK
491            if mod in ['a00','0b0','00g']:
492                result =  SGData['SSGKl'][:]
493            else:
494                result = [i*-1 for i in SGData['SSGKl']]
495            if '/' in mod:
496                return [i*-1 for i in result]
497            else:
498                return result
499        else:   #orthorhombic
500            return [-SSGKl[i] if mod[i] in ['a','b','g'] else SSGKl[i] for i in range(3)]
501               
502    def extendSSGOps(SSGOps):
503        nOps = len(SSGOps)
504        for OpA in SSGOps:
505            OpAtxt = SSMT2text(OpA)
506            if 't' not in OpAtxt:
507                continue
508            for OpB in SSGOps:
509                OpBtxt = SSMT2text(OpB)
510                if 't' not in OpBtxt:
511                    continue
512                OpC = list(SGProd(OpB,OpA))
513                OpC[1] %= 1.
514                OpCtxt = SSMT2text(OpC)
515#                print OpAtxt.replace(' ','')+' * '+OpBtxt.replace(' ','')+' = '+OpCtxt.replace(' ','')
516                for k,OpD in enumerate(SSGOps):
517                    OpDtxt = SSMT2text(OpD)
518                    if 't' in OpDtxt:
519                        continue
520#                    print '    ('+OpCtxt.replace(' ','')+' = ? '+OpDtxt.replace(' ','')+')'
521                    if OpCtxt == OpDtxt:
522                        continue
523                    elif OpCtxt.split(',')[:3] == OpDtxt.split(',')[:3]:
524                        if 't' not in OpDtxt:
525                            SSGOps[k] = OpC
526#                            print k,'   new:',OpCtxt.replace(' ','')
527                            break
528                        else:
529                            OpCtxt = OpCtxt.replace(' ','')
530                            OpDtxt = OpDtxt.replace(' ','')
531                            Txt = OpCtxt+' conflict with '+OpDtxt
532                            print Txt
533                            return False,Txt
534        return True,SSGOps
535       
536    def findMod(modSym):
537        for a in ['a','b','g']:
538            if a in modSym:
539                return a
540               
541    def genSSGOps():
542        SSGOps = SSGData['SSGOps'][:]
543        iFrac = {}
544        for i,frac in enumerate(SSGData['modSymb']):
545            if frac in ['1/2','1/3','1/4','1/6','1']:
546                iFrac[i] = frac+'.'
547#        print SGData['SpGrp']+SSymbol
548#        print 'SSGKl',SSGKl,'genQ',genQ,'iFrac',iFrac,'modSymb',SSGData['modSymb']
549# set identity & 1,-1; triclinic
550        SSGOps[0][0][3,3] = 1.
551## expand if centrosymmetric
552#        if SGData['SGInv']:
553#            SSGOps += [[-1*M,V] for M,V in SSGOps[:]]
554# monoclinic - all done & all checked
555        if SGData['SGPtGrp'] in ['2','m']:  #OK
556            SSGOps[1][0][3,3] = SSGKl[0]
557            SSGOps[1][1][3] = genQ[0]
558            for i in iFrac:
559                SSGOps[1][0][3,i] = -SSGKl[0]
560        elif SGData['SGPtGrp'] == '2/m':    #OK
561            SSGOps[1][0][3,3] = SSGKl[1]
562            if gensym:
563                SSGOps[1][1][3] = 0.5
564            for i in iFrac:
565                SSGOps[1][0][3,i] = SSGKl[0]
566           
567# orthorhombic - all OK not fully checked
568        elif SGData['SGPtGrp'] in ['222','mm2','m2m','2mm']:    #OK
569            if SGData['SGPtGrp'] == '222':
570                OrOps = {'g':{0:[1,3],1:[2,3]},'a':{1:[1,2],2:[1,3]},'b':{2:[3,2],0:[1,2]}} #OK
571            elif SGData['SGPtGrp'] == 'mm2':
572                OrOps = {'g':{0:[1,3],1:[2,3]},'a':{1:[2,1],2:[3,1]},'b':{0:[1,2],2:[3,2]}} #OK
573            elif SGData['SGPtGrp'] == 'm2m':
574                OrOps = {'b':{0:[1,2],2:[3,2]},'g':{0:[1,3],1:[2,3]},'a':{1:[2,1],2:[3,1]}} #OK
575            elif SGData['SGPtGrp'] == '2mm':
576                OrOps = {'a':{1:[2,1],2:[3,1]},'b':{0:[1,2],2:[3,2]},'g':{0:[1,3],1:[2,3]}} #OK
577            a = findMod(SSGData['modSymb'])
578            OrFrac = OrOps[a]
579            for j in iFrac:
580                for i in OrFrac[j]:
581                    SSGOps[i][0][3,j] = -2.*eval(iFrac[j])*SSGKl[i-1]
582            for i in [0,1,2]:
583                SSGOps[i+1][0][3,3] = SSGKl[i]
584                SSGOps[i+1][1][3] = genQ[i]
585                E,SSGOps = extendSSGOps(SSGOps)
586                if not E:
587                    return E,SSGOps
588        elif SGData['SGPtGrp'] == 'mmm':    #OK
589            OrOps = {'g':{0:[1,3],1:[2,3]},'a':{1:[2,1],2:[3,1]},'b':{0:[1,2],2:[3,2]}} 
590            a = findMod(SSGData['modSymb'])
591            if a == 'g':
592                SSkl = [1,1,1]
593            elif a == 'a':
594                SSkl = [-1,1,-1]
595            else:
596                SSkl = [1,-1,-1]
597            OrFrac = OrOps[a]
598            for j in iFrac:
599                for i in OrFrac[j]:
600                    SSGOps[i][0][3,j] = -2.*eval(iFrac[j])*SSkl[i-1]
601            for i in [0,1,2]:
602                SSGOps[i+1][0][3,3] = SSkl[i]
603                SSGOps[i+1][1][3] = genQ[i]
604                E,SSGOps = extendSSGOps(SSGOps)
605                if not E:
606                    return E,SSGOps               
607# tetragonal - all done & checked
608        elif SGData['SGPtGrp'] == '4':  #OK
609            SSGOps[1][0][3,3] = SSGKl[0]
610            SSGOps[1][1][3] = genQ[0]
611            if '1/2' in SSGData['modSymb']:
612                SSGOps[1][0][3,1] = -1
613        elif SGData['SGPtGrp'] == '-4': #OK
614            SSGOps[1][0][3,3] = SSGKl[0]
615            if '1/2' in SSGData['modSymb']:
616                SSGOps[1][0][3,1] = 1
617        elif SGData['SGPtGrp'] in ['4/m',]: #OK
618            if '1/2' in SSGData['modSymb']:
619                SSGOps[1][0][3,1] = -SSGKl[0]
620            for i,j in enumerate([1,3]):
621                SSGOps[j][0][3,3] = 1
622                if genQ[i]:
623                    SSGOps[j][1][3] = genQ[i]
624                E,SSGOps = extendSSGOps(SSGOps)
625                if not E:
626                    return E,SSGOps
627        elif SGData['SGPtGrp'] in ['422','4mm','-42m','-4m2',]: #OK
628            iGens = [1,4,5]
629            if SGData['SGPtGrp'] in ['4mm','-4m2',]:
630                iGens = [1,6,7]
631            for i,j in enumerate(iGens):
632                if '1/2' in SSGData['modSymb'] and i < 2:
633                    SSGOps[j][0][3,1] = SSGKl[i]
634                SSGOps[j][0][3,3] = SSGKl[i]
635                if genQ[i]:
636                    if 's' in gensym and j == 6:
637                        SSGOps[j][1][3] = -genQ[i]
638                    else:
639                        SSGOps[j][1][3] = genQ[i]
640                E,SSGOps = extendSSGOps(SSGOps)
641                if not E:
642                    return E,SSGOps
643        elif SGData['SGPtGrp'] in ['4/mmm',]:#OK
644            if '1/2' in SSGData['modSymb']:
645                SSGOps[1][0][3,1] = -SSGKl[0]
646                SSGOps[6][0][3,1] = SSGKl[1]
647                if modsym:
648                   SSGOps[1][1][3]  = -genQ[3]
649            for i,j in enumerate([1,2,6,7]):
650                SSGOps[j][0][3,3] = 1
651                SSGOps[j][1][3] = genQ[i]
652                E,Result = extendSSGOps(SSGOps)
653                if not E:
654                    return E,Result
655                else:
656                    SSGOps = Result
657               
658# trigonal - all done & checked
659        elif SGData['SGPtGrp'] == '3':  #OK
660            SSGOps[1][0][3,3] = SSGKl[0]
661            if '1/3' in SSGData['modSymb']:
662                SSGOps[1][0][3,1] = -1
663            SSGOps[1][1][3] = genQ[0]
664        elif SGData['SGPtGrp'] == '-3': #OK
665            SSGOps[1][0][3,3] = -SSGKl[0]
666            if '1/3' in SSGData['modSymb']:
667                SSGOps[1][0][3,1] = -1
668            SSGOps[1][1][3] = genQ[0]
669        elif SGData['SGPtGrp'] in ['312','3m','-3m','-3m1','3m1']:   #OK
670            if '1/3' in SSGData['modSymb']:
671                SSGOps[1][0][3,1] = -1
672            for i,j in enumerate([1,5]):
673                if SGData['SGPtGrp'] in ['3m','-3m']:
674                    SSGOps[j][0][3,3] = 1
675                else:                   
676                    SSGOps[j][0][3,3] = SSGKl[i+1]
677                if genQ[i]:
678                    SSGOps[j][1][3] = genQ[i]
679        elif SGData['SGPtGrp'] in ['321','32']:   #OK
680            for i,j in enumerate([1,4]):
681                SSGOps[j][0][3,3] = SSGKl[i]
682                if genQ[i]:
683                    SSGOps[j][1][3] = genQ[i]
684        elif SGData['SGPtGrp'] in ['31m','-31m']:   #OK
685            ids = [1,3]
686            if SGData['SGPtGrp'] == '-31m':
687                ids = [1,3]
688            if '1/3' in SSGData['modSymb']:
689                SSGOps[ids[0]][0][3,1] = -SSGKl[0]
690            for i,j in enumerate(ids):
691                SSGOps[j][0][3,3] = 1
692                if genQ[i+1]:
693                    SSGOps[j][1][3] = genQ[i+1]
694                     
695# hexagonal all done & checked
696        elif SGData['SGPtGrp'] == '6':  #OK
697            SSGOps[1][0][3,3] = SSGKl[0]
698            SSGOps[1][1][3] = genQ[0]
699        elif SGData['SGPtGrp'] == '-6': #OK
700            SSGOps[1][0][3,3] = SSGKl[0]
701        elif SGData['SGPtGrp'] in ['6/m',]: #OK
702            SSGOps[1][0][3,3] = -SSGKl[1]
703            SSGOps[1][1][3] = genQ[0]
704            SSGOps[2][1][3] = genQ[1]
705        elif SGData['SGPtGrp'] in ['622',]: #OK
706            for i,j in enumerate([1,8,9]):
707                SSGOps[j][0][3,3] = SSGKl[i]
708                if genQ[i]:
709                    SSGOps[j][1][3] = genQ[i]
710                E,SSGOps = extendSSGOps(SSGOps)
711           
712        elif SGData['SGPtGrp'] in ['6mm','-62m','-6m2',]: #OK
713            for i,j in enumerate([1,6,7]):
714                SSGOps[j][0][3,3] = SSGKl[i]
715                if genQ[i]:
716                    SSGOps[j][1][3] = genQ[i]
717                E,SSGOps = extendSSGOps(SSGOps)
718        elif SGData['SGPtGrp'] in ['6/mmm',]: # OK
719            for i,j in enumerate([1,2,10,11]):
720                SSGOps[j][0][3,3] = 1
721                if genQ[i]:
722                    SSGOps[j][1][3] = genQ[i]
723                E,SSGOps = extendSSGOps(SSGOps)
724        elif SGData['SGPtGrp'] in ['1','-1']: #triclinic - done
725            return True,SSGOps
726        E,SSGOps = extendSSGOps(SSGOps)
727        return E,SSGOps
728       
729    def specialGen(gensym,modsym):
730        sym = ''.join(gensym)
731        if SGData['SGPtGrp'] in ['2/m',] and 'n' in SGData['SpGrp']:
732            if 's' in sym:
733                gensym = 'ss'
734        if SGData['SGPtGrp'] in ['-62m',] and sym == '00s':
735            gensym = '0ss'
736        elif SGData['SGPtGrp'] in ['222',]:
737            if sym == '00s':
738                gensym = '0ss'
739            elif sym == '0s0':
740                gensym = 'ss0'
741            elif sym == 's00':
742                gensym = 's0s'
743        elif SGData['SGPtGrp'] in ['mmm',]:
744            if 'g' in modsym:
745                if sym == 's00':
746                    gensym = 's0s'
747                elif sym == '0s0':
748                    gensym = '0ss'
749            elif 'a' in modsym:
750                if sym == '0s0':
751                    gensym = 'ss0'
752                elif sym == '00s':
753                    gensym = 's0s'
754            elif 'b' in modsym:
755                if sym == '00s':
756                    gensym = '0ss'
757                elif sym == 's00':
758                    gensym = 'ss0'
759        return gensym
760                   
761    def checkGen(gensym):
762        sym = ''.join(gensym)
763# monoclinic - all done
764        if str(SSGKl) == '[-1]' and sym == 's':
765            return False
766        elif SGData['SGPtGrp'] in ['2/m',]:
767            if str(SSGKl) == '[-1, 1]' and sym == '0s':
768                return False
769            elif str(SSGKl) == '[1, -1]' and sym == 's0':
770                return False
771#orthorhombic - all
772        elif SGData['SGPtGrp'] in ['222',] and sym not in ['','s00','0s0','00s']:
773            return False 
774        elif SGData['SGPtGrp'] in ['2mm','m2m','mm2','mmm'] and sym not in ['',]+GenSymList[4:15]:
775            return False 
776#tetragonal - all done
777        elif SGData['SGPtGrp'] in ['4',] and sym not in ['','s','q']:
778            return False 
779        elif SGData['SGPtGrp'] in ['-4',] and sym not in ['',]:
780            return False             
781        elif SGData['SGPtGrp'] in ['4/m',] and sym not in ['','s0','q0']:
782            return False
783        elif SGData['SGPtGrp'] in ['422',] and sym not in ['','q00','s00']:
784            return False         
785        elif SGData['SGPtGrp'] in ['4mm',] and sym not in ['','ss0','s0s','0ss','00s','qq0','qqs']:
786            return False
787        elif SGData['SGPtGrp'] in ['-4m2',] and sym not in ['','0s0','0q0']:
788            return False
789        elif SGData['SGPtGrp'] in ['-42m',] and sym not in ['','0ss','00q',]:
790            return False
791        elif SGData['SGPtGrp'] in ['4/mmm',] and sym not in ['','s00s','s0s0','00ss','000s',]:
792            return False
793#trigonal/rhombohedral - all done
794        elif SGData['SGPtGrp'] in ['3',] and sym not in ['','t']:
795            return False 
796        elif SGData['SGPtGrp'] in ['-3',] and sym not in ['',]:
797            return False 
798        elif SGData['SGPtGrp'] in ['32',] and sym not in ['','t0']:
799            return False 
800        elif SGData['SGPtGrp'] in ['321','312'] and sym not in ['','t00']:
801            return False 
802        elif SGData['SGPtGrp'] in ['3m','-3m'] and sym not in ['','0s']:
803            return False 
804        elif SGData['SGPtGrp'] in ['3m1','-3m1'] and sym not in ['','0s0']:
805            return False 
806        elif SGData['SGPtGrp'] in ['31m','-31m'] and sym not in ['','00s']:
807            return False 
808#hexagonal - all done
809        elif SGData['SGPtGrp'] in ['6',] and sym not in ['','s','h','t']:
810            return False 
811        elif SGData['SGPtGrp'] in ['-6',] and sym not in ['',]:
812            return False
813        elif SGData['SGPtGrp'] in ['6/m',] and sym not in ['','s0']:
814            return False
815        elif SGData['SGPtGrp'] in ['622',] and sym not in ['','h00','t00','s00']:
816            return False         
817        elif SGData['SGPtGrp'] in ['6mm',] and sym not in ['','ss0','s0s','0ss']:
818            return False
819        elif SGData['SGPtGrp'] in ['-6m2',] and sym not in ['','0s0']:
820            return False
821        elif SGData['SGPtGrp'] in ['-62m',] and sym not in ['','00s']:
822            return False
823        elif SGData['SGPtGrp'] in ['6/mmm',] and sym not in ['','s00s','s0s0','00ss']:
824            return False
825        return True
826       
827    LaueModList = [
828        'abg','ab0','ab1/2','a0g','a1/2g',  '0bg','1/2bg','a00','a01/2','a1/20',
829        'a1/21/2','a01','a10','0b0','0b1/2', '1/2b0','1/2b1/2','0b1','1b0','00g',
830        '01/2g','1/20g','1/21/2g','01g','10g', '1/31/3g']
831    LaueList = ['-1','2/m','mmm','4/m','4/mmm','3R','3mR','3','3m1','31m','6/m','6/mmm','m3','m3m']
832    GenSymList = ['','s','0s','s0', '00s','0s0','s00','s0s','ss0','0ss','q00','0q0','00q','qq0','q0q', '0qq',
833        'q','qqs','s0s0','00ss','s00s','t','t00','t0','h','h00','000s']
834    Fracs = {'1/2':0.5,'1/3':1./3,'1':1.0,'0':0.,'s':.5,'t':1./3,'q':.25,'h':1./6,'a':0.,'b':0.,'g':0.}
835    LaueId = LaueList.index(SGData['SGLaue'])
836    if SGData['SGLaue'] in ['m3','m3m']:
837        return '(3+1) superlattices not defined for cubic space groups',None
838    elif SGData['SGLaue'] in ['3R','3mR']:
839        return '(3+1) superlattices not defined for rhombohedral settings - use hexagonal setting',None
840    try:
841        modsym,gensym = splitSSsym(SSymbol)
842    except ValueError:
843        return 'Error in superspace symbol '+SSymbol,None
844    if ''.join(gensym) not in GenSymList:
845        return 'unknown generator symbol '+''.join(gensym),None
846    try:
847        LaueModId = LaueModList.index(''.join(modsym))
848    except ValueError:
849        return 'Unknown modulation symbol '+''.join(modsym),None
850    if not checkModSym():
851        return 'Modulation '+''.join(modsym)+' not consistent with space group '+SGData['SpGrp'],None
852    modQ = [Fracs[mod] for mod in modsym]
853    SSGKl = SGData['SSGKl'][:]
854    if SGData['SGLaue'] in ['2/m','mmm']:
855        SSGKl = fixMonoOrtho()
856    if len(gensym) and len(gensym) != len(SSGKl):
857        return 'Wrong number of items in generator symbol '+''.join(gensym),None
858    if not checkGen(gensym):
859        return 'Generator '+''.join(gensym)+' not consistent with space group '+SGData['SpGrp'],None
860    gensym = specialGen(gensym,modsym)
861    genQ = [Fracs[mod] for mod in gensym]
862    if not genQ:
863        genQ = [0,0,0,0]
864    SSGData = {'SSpGrp':SGData['SpGrp']+SSymbol,'modQ':modQ,'modSymb':modsym,'SSGKl':SSGKl}
865    SSCen = np.zeros((len(SGData['SGCen']),4))
866    for icen,cen in enumerate(SGData['SGCen']):
867        SSCen[icen,0:3] = cen
868    SSCen[0] = np.zeros(4)
869    SSGData['SSGCen'] = SSCen
870    SSGData['SSGOps'] = []
871    for iop,op in enumerate(SGData['SGOps']):
872        T = np.zeros(4)
873        ssop = np.zeros((4,4))
874        ssop[:3,:3] = op[0]
875        T[:3] = op[1]
876        SSGData['SSGOps'].append([ssop,T])
877    E,Result = genSSGOps()
878    if E:
879        SSGData['SSGOps'] = Result
880        if DEBUG:
881            print 'Super spacegroup operators for '+SSGData['SSpGrp']
882            for Op in Result:
883                print SSMT2text(Op).replace(' ','')
884            if SGData['SGInv']:                                 
885                for Op in Result:
886                    Op = [-Op[0],-Op[1]%1.]
887                    print SSMT2text(Op).replace(' ','')                                 
888        return None,SSGData
889    else:
890        return Result+'\nOperator conflict - incorrect superspace symbol',None
891
892def splitSSsym(SSymbol):
893    '''
894    Splits supersymmetry symbol into two lists of strings
895    '''
896    modsym,gensym = SSymbol.replace(' ','').split(')')
897    nfrac = modsym.count('/')
898    modsym = modsym.lstrip('(')
899    if nfrac == 0:
900        modsym = list(modsym)
901    elif nfrac == 1:
902        pos = modsym.find('/')
903        if pos == 1:
904            modsym = [modsym[:3],modsym[3],modsym[4]]
905        elif pos == 2:
906            modsym = [modsym[0],modsym[1:4],modsym[4]]
907        else:
908            modsym = [modsym[0],modsym[1],modsym[2:]]
909    else:
910        lpos = modsym.find('/')
911        rpos = modsym.rfind('/')
912        if lpos == 1 and rpos == 4:
913            modsym = [modsym[:3],modsym[3:6],modsym[6]]
914        elif lpos == 1 and rpos == 5:
915            modsym = [modsym[:3],modsym[3],modsym[4:]]
916        else:
917            modsym = [modsym[0],modsym[1:4],modsym[4:]]
918    gensym = list(gensym)
919    return modsym,gensym
920       
921def SSGPrint(SGData,SSGData):
922    '''
923    Print the output of SSpcGroup in a nicely formatted way. Used in SSpaceGroup
924
925    :param SGData: space group data structure as defined in SpcGroup above.
926    :param SSGData: from :func:`SSpcGroup`
927    :returns:
928        SSGText - list of strings with the superspace group details
929        SGTable - list of strings for each of the operations
930    '''
931    Mult = len(SSGData['SSGCen'])*len(SSGData['SSGOps'])
932    SSGText = []
933    SSGText.append(' Superspace Group: '+SSGData['SSpGrp'])
934    CentStr = 'centrosymmetric'
935    if not SGData['SGInv']:
936        CentStr = 'non'+CentStr
937    if SGData['SGLatt'] in 'ABCIFR':
938        SSGText.append(' The lattice is '+CentStr+' '+SGData['SGLatt']+'-centered '+SGData['SGSys'].lower())
939    else:
940        SSGText.append(' The superlattice is '+CentStr+' '+'primitive '+SGData['SGSys'].lower())       
941    SSGText.append(' The Laue symmetry is '+SGData['SGLaue'])
942    SSGText.append(' The superlattice point group is '+SGData['SGPtGrp']+','+''.join([str(i) for i in SSGData['SSGKl']]))
943    SSGText.append(' The number of superspace group generators is '+str(len(SGData['SSGKl'])))
944    SSGText.append(' Multiplicity of a general site is '+str(Mult))
945    if SGData['SGUniq'] in ['a','b','c']:
946        SSGText.append(' The unique monoclinic axis is '+SGData['SGUniq'])
947    if SGData['SGInv']:
948        SSGText.append(' The inversion center is located at 0,0,0')
949    if SGData['SGPolax']:
950        SSGText.append(' The location of the origin is arbitrary in '+SGData['SGPolax'])
951    SSGText.append(' ')
952    if len(SSGData['SSGCen']) > 1:
953        SSGText.append(' The equivalent positions are:')
954        SSGText.append(' ('+SSLatt2text(SSGData['SSGCen'])+')+\n')
955    else:
956        SSGText.append(' The equivalent positions are:\n')
957    SSGTable = []
958    for i,Opr in enumerate(SSGData['SSGOps']):
959        SSGTable.append('(%2d) %s'%(i+1,SSMT2text(Opr)))
960    return SSGText,SSGTable
961   
962def SSGModCheck(Vec,modSymb):
963    ''' Checks modulation vector compatibility with supersymmetry space group symbol.
964    Superspace group symbol takes precidence & the vector will be modified accordingly
965    '''
966    Fracs = {'1/2':0.5,'1/3':1./3,'1':1.0,'0':0.,'a':0.,'b':0.,'g':0.}
967    modQ = [Fracs[mod] for mod in modSymb]
968    Vec = [0.1 if (vec == 0.0 and mod in ['a','b','g']) else vec for [vec,mod] in zip(Vec,modSymb)]
969    return [Q if mod not in ['a','b','g'] and vec != Q else vec for [vec,mod,Q] in zip(Vec,modSymb,modQ)],  \
970        [True if mod in ['a','b','g'] else False for mod in modSymb]
971
972def SSMT2text(Opr):
973    "From superspace group matrix/translation operator returns text version"
974    XYZS = ('x','y','z','t')    #Stokes, Campbell & van Smaalen notation
975    TRA = ('   ','ERR','1/6','1/4','1/3','ERR','1/2','ERR','2/3','3/4','5/6','ERR')
976    Fld = ''
977    M,T = Opr
978    for j in range(4):
979        IJ = ''
980        for k in range(4):
981            txt = str(int(round(M[j][k])))
982            txt = txt.replace('1',XYZS[k]).replace('0','')
983            if '2' in txt:
984                txt += XYZS[k]
985            if IJ and M[j][k] > 0:
986                IJ += '+'+txt
987            else:
988                IJ += txt
989        IK = int(round(T[j]*12))%12
990        if IK:
991            if not IJ:
992                break
993            if IJ[0] == '-':
994                Fld += (TRA[IK]+IJ).rjust(8)
995            else:
996                Fld += (TRA[IK]+'+'+IJ).rjust(8)
997        else:
998            Fld += IJ.rjust(8)
999        if j != 3: Fld += ', '
1000    return Fld
1001   
1002def SSLatt2text(SSGCen):
1003    "Lattice centering vectors to text"
1004    lattTxt = ''
1005    for vec in SSGCen:
1006        lattTxt += ' '
1007        for item in vec:
1008            if int(item*12.):
1009                lattTxt += '1/%d,'%(12/int(item*12))
1010            else:
1011                lattTxt += '0,'
1012        lattTxt = lattTxt.rstrip(',')
1013        lattTxt += ';'
1014    lattTxt = lattTxt.rstrip(';').lstrip(' ')
1015    return lattTxt
1016       
1017def SSpaceGroup(SGSymbol,SSymbol):
1018    '''
1019    Print the output of SSpcGroup in a nicely formatted way.
1020
1021    :param SGSymbol: space group symbol with spaces between axial fields.
1022    :param SSymbol: superspace group symbol extension (string).
1023    :returns: nothing
1024    '''
1025
1026    E,A = SpcGroup(SGSymbol)
1027    if E > 0:
1028        print SGErrors(E)
1029        return
1030    E,B = SSpcGroup(A,SSymbol)   
1031    if E > 0:
1032        print E
1033        return
1034    for l in SSGPrint(B):
1035        print l
1036       
1037def SGProd(OpA,OpB):
1038    '''
1039    Form space group operator product. OpA & OpB are [M,V] pairs;
1040        both must be of same dimension (3 or 4). Returns [M,V] pair
1041    '''
1042    A,U = OpA
1043    B,V = OpB
1044    M = np.inner(B,A.T)
1045    W = np.inner(B,U)+V
1046    return M,W
1047       
1048def MoveToUnitCell(xyz):
1049    '''
1050    Translates a set of coordinates so that all values are >=0 and < 1
1051
1052    :param xyz: a list or numpy array of fractional coordinates
1053    :returns: XYZ - numpy array of new coordinates now 0 or greater and less than 1
1054    '''
1055    XYZ = np.zeros(3)
1056    for i,x in enumerate(xyz):
1057        XYZ[i] = (x-int(x))%1.0
1058    return XYZ
1059       
1060def Opposite(XYZ,toler=0.0002):
1061    '''
1062    Gives opposite corner, edge or face of unit cell for position within tolerance.
1063        Result may be just outside the cell within tolerance
1064
1065    :param XYZ: 0 >= np.array[x,y,z] > 1 as by MoveToUnitCell
1066    :param toler: unit cell fraction tolerance making opposite
1067    :returns:
1068        XYZ: array of opposite positions; always contains XYZ
1069    '''
1070    perm3 = [[1,1,1],[0,1,1],[1,0,1],[1,1,0],[1,0,0],[0,1,0],[0,0,1],[0,0,0]]
1071    TB = np.where(abs(XYZ-1)<toler,-1,0)+np.where(abs(XYZ)<toler,1,0)
1072    perm = TB*perm3
1073    cperm = ['%d%d%d'%(i,j,k) for i,j,k in perm]
1074    D = dict(zip(cperm,perm))
1075    new = []
1076    for key in D:
1077        new.append(np.array(D[key])+np.array(XYZ))
1078    return new
1079       
1080def GenAtom(XYZ,SGData,All=False,Uij=[],Move=True):
1081    '''
1082    Generates the equivalent positions for a specified coordinate and space group
1083
1084    :param XYZ: an array, tuple or list containing 3 elements: x, y & z
1085    :param SGData: from :func:`SpcGroup`
1086    :param All: True return all equivalent positions including duplicates;
1087      False return only unique positions
1088    :param Uij: [U11,U22,U33,U12,U13,U23] or [] if no Uij
1089    :param Move: True move generated atom positions to be inside cell
1090      False do not move atoms       
1091    :return: [[XYZEquiv],Idup,[UijEquiv]]
1092
1093      *  [XYZEquiv] is list of equivalent positions (XYZ is first entry)
1094      *  Idup = [-][C]SS where SS is the symmetry operator number (1-24), C (if not 0,0,0)
1095      * is centering operator number (1-4) and - is for inversion
1096        Cell = unit cell translations needed to put new positions inside cell
1097        [UijEquiv] - equivalent Uij; absent if no Uij given
1098       
1099    '''
1100    XYZEquiv = []
1101    UijEquiv = []
1102    Idup = []
1103    Cell = []
1104    X = np.array(XYZ)
1105    if Move:
1106        X = MoveToUnitCell(X)
1107    for ic,cen in enumerate(SGData['SGCen']):
1108        C = np.array(cen)
1109        for invers in range(int(SGData['SGInv']+1)):
1110            for io,[M,T] in enumerate(SGData['SGOps']):
1111                idup = ((io+1)+100*ic)*(1-2*invers)
1112                XT = np.inner(M,X)+T
1113                if len(Uij):
1114                    U = Uij2U(Uij)
1115                    U = np.inner(M,np.inner(U,M).T)
1116                    newUij = U2Uij(U)
1117                if invers:
1118                    XT = -XT
1119                XT += C
1120                if Move:
1121                    newX = MoveToUnitCell(XT)
1122                else:
1123                    newX = XT
1124                cell = np.asarray(np.rint(newX-XT),dtype=np.int32)
1125                if All:
1126                    if np.allclose(newX,X,atol=0.0002):
1127                        idup = False
1128                else:
1129                    if True in [np.allclose(newX,oldX,atol=0.0002) for oldX in XYZEquiv]:
1130                        idup = False
1131                if All or idup:
1132                    XYZEquiv.append(newX)
1133                    Idup.append(idup)
1134                    Cell.append(cell)
1135                    if len(Uij):
1136                        UijEquiv.append(newUij)                   
1137    if len(Uij):
1138        return zip(XYZEquiv,UijEquiv,Idup,Cell)
1139    else:
1140        return zip(XYZEquiv,Idup,Cell)
1141
1142def GenHKLf(HKL,SGData):
1143    '''
1144    Uses old GSAS Fortran routine genhkl.for
1145
1146    :param HKL:  [h,k,l] must be integral values for genhkl.for to work
1147    :param SGData: space group data obtained from SpcGroup
1148    :returns: iabsnt,mulp,Uniq,phi
1149
1150     *   iabsnt = True if reflection is forbidden by symmetry
1151     *   mulp = reflection multiplicity including Friedel pairs
1152     *   Uniq = numpy array of equivalent hkl in descending order of h,k,l
1153     *   phi = phase offset for each equivalent h,k,l
1154
1155    '''
1156    hklf = HKL+[0,]
1157    Ops = SGData['SGOps']
1158    OpM = np.array([op[0] for op in Ops])
1159    OpT = np.array([op[1] for op in Ops])
1160    Inv = SGData['SGInv']
1161    Cen = np.array([cen for cen in SGData['SGCen']])
1162   
1163    Nuniq,Uniq,iabsnt,mulp = pyspg.genhklpy(hklf,len(Ops),OpM,OpT,SGData['SGInv'],len(Cen),Cen)
1164    h,k,l,f = Uniq
1165    Uniq=np.array(zip(h[:Nuniq],k[:Nuniq],l[:Nuniq]))
1166    phi = f[:Nuniq]
1167   
1168    return iabsnt,mulp,Uniq,phi
1169   
1170def checkSSLaue(HKL,SGData,SSGData):
1171    #Laue check here - Toss HKL if outside unique Laue part
1172    h,k,l,m = HKL
1173    if SGData['SGLaue'] == '2/m':
1174        if SGData['SGUniq'] == 'a':
1175            if 'a' in SSGData['modSymb'] and h == 0 and m < 0:
1176                return False
1177            elif 'b' in SSGData['modSymb'] and k == 0 and l ==0 and m < 0:
1178                return False
1179            else:
1180                return True
1181        elif SGData['SGUniq'] == 'b':
1182            if 'b' in SSGData['modSymb'] and k == 0 and m < 0:
1183                return False
1184            elif 'a' in SSGData['modSymb'] and h == 0 and l ==0 and m < 0:
1185                return False
1186            else:
1187                return True
1188        elif SGData['SGUniq'] == 'c':
1189            if 'g' in SSGData['modSymb'] and l == 0 and m < 0:
1190                return False
1191            elif 'a' in SSGData['modSymb'] and h == 0 and k ==0 and m < 0:
1192                return False
1193            else:
1194                return True
1195    elif SGData['SGLaue'] == 'mmm':
1196        if 'a' in SSGData['modSymb']:
1197            if h == 0 and m < 0:
1198                return False
1199            else:
1200                return True
1201        elif 'b' in SSGData['modSymb']:
1202            if k == 0 and m < 0:
1203                return False
1204            else:
1205                return True
1206        elif 'g' in SSGData['modSymb']:
1207            if l == 0 and m < 0:
1208                return False
1209            else:
1210                return True
1211    else:   #tetragonal, trigonal, hexagonal (& triclinic?)
1212        if l == 0 and m < 0:
1213            return False
1214        else:
1215            return True
1216       
1217   
1218def checkSSextc(HKL,SSGData):
1219    Ops = SSGData['SSGOps']
1220    OpM = np.array([op[0] for op in Ops])
1221    OpT = np.array([op[1] for op in Ops])
1222    HKLS = np.array([HKL,-HKL])     #Freidel's Law
1223    DHKL = np.reshape(np.inner(HKLS,OpM)-HKL,(-1,4))
1224    PHKL = np.reshape(np.inner(HKLS,OpT),(-1,))
1225    for dhkl,phkl in zip(DHKL,PHKL)[1:]:    #skip identity
1226        if dhkl.any():
1227            continue
1228        else:
1229            if phkl%1.:
1230                return False
1231    return True
1232                                 
1233def GetOprPtrName(key):
1234    'Needs a doc string'
1235    OprPtrName = {
1236        '-6643':[   2,' 1bar ', 1],'6479' :[  10,'  2z  ', 2],'-6479':[   9,'  mz  ', 3],
1237        '6481' :[   7,'  my  ', 4],'-6481':[   6,'  2y  ', 5],'6641' :[   4,'  mx  ', 6],
1238        '-6641':[   3,'  2x  ', 7],'6591' :[  28,' m+-0 ', 8],'-6591':[  27,' 2+-0 ', 9],
1239        '6531' :[  25,' m110 ',10],'-6531':[  24,' 2110 ',11],'6537' :[  61,'  4z  ',12],
1240        '-6537':[  62,' -4z  ',13],'975'  :[  68,' 3+++1',14],'6456' :[ 114,'  3z1 ',15],
1241        '-489' :[  73,' 3+-- ',16],'483'  :[  78,' 3-+- ',17],'-969' :[  83,' 3--+ ',18],
1242        '819'  :[  22,' m+0- ',19],'-819' :[  21,' 2+0- ',20],'2431' :[  16,' m0+- ',21],
1243        '-2431':[  15,' 20+- ',22],'-657' :[  19,' m101 ',23],'657'  :[  18,' 2101 ',24],
1244        '1943' :[  48,' -4x  ',25],'-1943':[  47,'  4x  ',26],'-2429':[  13,' m011 ',27],
1245        '2429' :[  12,' 2011 ',28],'639'  :[  55,' -4y  ',29],'-639' :[  54,'  4y  ',30],
1246        '-6484':[ 146,' 2010 ', 4],'6484' :[ 139,' m010 ', 5],'-6668':[ 145,' 2100 ', 6],
1247        '6668' :[ 138,' m100 ', 7],'-6454':[ 148,' 2120 ',18],'6454' :[ 141,' m120 ',19],
1248        '-6638':[ 149,' 2210 ',20],'6638' :[ 142,' m210 ',21],              #search ends here
1249        '2223' :[  68,' 3+++2',39],
1250        '6538' :[ 106,'  6z1 ',40],'-2169':[  83,' 3--+2',41],'2151' :[  73,' 3+--2',42],
1251        '2205' :[  79,'-3-+-2',43],'-2205':[  78,' 3-+-2',44],'489'  :[  74,'-3+--1',45],
1252        '801'  :[  53,'  4y1 ',46],'1945' :[  47,'  4x3 ',47],'-6585':[  62,' -4z3 ',48],
1253        '6585' :[  61,'  4z3 ',49],'6584' :[ 114,'  3z2 ',50],'6666' :[ 106,'  6z5 ',51],
1254        '6643' :[   1,' Iden ',52],'-801' :[  55,' -4y1 ',53],'-1945':[  48,' -4x3 ',54],
1255        '-6666':[ 105,' -6z5 ',55],'-6538':[ 105,' -6z1 ',56],'-2223':[  69,'-3+++2',57],
1256        '-975' :[  69,'-3+++1',58],'-6456':[ 113,' -3z1 ',59],'-483' :[  79,'-3-+-1',60],
1257        '969'  :[  84,'-3--+1',61],'-6584':[ 113,' -3z2 ',62],'2169' :[  84,'-3--+2',63],
1258        '-2151':[  74,'-3+--2',64],'0':[0,' ????',0]
1259        }
1260    return OprPtrName[key]
1261
1262def GetKNsym(key):
1263    'Needs a doc string'
1264    KNsym = {
1265        '0'         :'    1   ','1'         :'   -1   ','64'        :'    2(x)','32'        :'    m(x)',
1266        '97'        :'  2/m(x)','16'        :'    2(y)','8'         :'    m(y)','25'        :'  2/m(y)',
1267        '2'         :'    2(z)','4'         :'    m(z)','7'         :'  2/m(z)','134217728' :'   2(yz)',
1268        '67108864'  :'   m(yz)','201326593' :' 2/m(yz)','2097152'   :'  2(0+-)','1048576'   :'  m(0+-)',
1269        '3145729'   :'2/m(0+-)','8388608'   :'   2(xz)','4194304'   :'   m(xz)','12582913'  :' 2/m(xz)',
1270        '524288'    :'  2(+0-)','262144'    :'  m(+0-)','796433'    :'2/m(+0-)','1024'      :'   2(xy)',
1271        '512'       :'   m(xy)','1537'      :' 2/m(xy)','256'       :'  2(+-0)','128'       :'  m(+-0)',
1272        '385'       :'2/m(+-0)','76'        :'  mm2(x)','52'        :'  mm2(y)','42'        :'  mm2(z)',
1273        '135266336' :' mm2(yz)','69206048'  :'mm2(0+-)','8650760'   :' mm2(xz)','4718600'   :'mm2(+0-)',
1274        '1156'      :' mm2(xy)','772'       :'mm2(+-0)','82'        :'  222   ','136314944' :'  222(x)',
1275        '8912912'   :'  222(y)','1282'      :'  222(z)','127'       :'  mmm   ','204472417' :'  mmm(x)',
1276        '13369369'  :'  mmm(y)','1927'      :'  mmm(z)','33554496'  :'  4(100)','16777280'  :' -4(100)',
1277        '50331745'  :'4/m(100)','169869394' :'422(100)','84934738'  :'-42m 100','101711948' :'4mm(100)',
1278        '254804095' :'4/mmm100','536870928 ':'  4(010)','268435472' :' -4(010)','805306393' :'4/m (10)',
1279        '545783890' :'422(010)','272891986' :'-42m 010','541327412' :'4mm(010)','818675839' :'4/mmm010',
1280        '2050'      :'  4(001)','4098'      :' -4(001)','6151'      :'4/m(001)','3410'      :'422(001)',
1281        '4818'      :'-42m 001','2730'      :'4mm(001)','8191'      :'4/mmm001','8192'      :'  3(111)',
1282        '8193'      :' -3(111)','2629888'   :' 32(111)','1319040'   :' 3m(111)','3940737'   :'-3m(111)',
1283        '32768'     :'  3(+--)','32769'     :' -3(+--)','10519552'  :' 32(+--)','5276160'   :' 3m(+--)',
1284        '15762945'  :'-3m(+--)','65536'     :'  3(-+-)','65537'     :' -3(-+-)','134808576' :' 32(-+-)',
1285        '67437056'  :' 3m(-+-)','202180097' :'-3m(-+-)','131072'    :'  3(--+)','131073'    :' -3(--+)',
1286        '142737664' :' 32(--+)','71434368'  :' 3m(--+)','214040961' :'-3m(--+)','237650'    :'   23   ',
1287        '237695'    :'   m3   ','715894098' :'   432  ','358068946' :'  -43m  ','1073725439':'   m3m  ',
1288        '68157504'  :' mm2d100','4456464'   :' mm2d010','642'       :' mm2d001','153092172' :'-4m2 100',
1289        '277348404' :'-4m2 010','5418'      :'-4m2 001','1075726335':'  6/mmm ','1074414420':'-6m2 100',
1290        '1075070124':'-6m2 120','1075069650':'   6mm  ','1074414890':'   622  ','1073758215':'   6/m  ',
1291        '1073758212':'   -6   ','1073758210':'    6   ','1073759865':'-3m(100)','1075724673':'-3m(120)',
1292        '1073758800':' 3m(100)','1075069056':' 3m(120)','1073759272':' 32(100)','1074413824':' 32(120)',
1293        '1073758209':'   -3   ','1073758208':'    3   ','1074135143':'mmm(100)','1075314719':'mmm(010)',
1294        '1073743751':'mmm(110)','1074004034':' mm2z100','1074790418':' mm2z010','1073742466':' mm2z110',
1295        '1074004004':'mm2(100)','1074790412':'mm2(010)','1073742980':'mm2(110)','1073872964':'mm2(120)',
1296        '1074266132':'mm2(210)','1073742596':'mm2(+-0)','1073872930':'222(100)','1074266122':'222(010)',
1297        '1073743106':'222(110)','1073741831':'2/m(001)','1073741921':'2/m(100)','1073741849':'2/m(010)',
1298        '1073743361':'2/m(110)','1074135041':'2/m(120)','1075314689':'2/m(210)','1073742209':'2/m(+-0)',
1299        '1073741828':' m(001) ','1073741888':' m(100) ','1073741840':' m(010) ','1073742336':' m(110) ',
1300        '1074003968':' m(120) ','1074790400':' m(210) ','1073741952':' m(+-0) ','1073741826':' 2(001) ',
1301        '1073741856':' 2(100) ','1073741832':' 2(010) ','1073742848':' 2(110) ','1073872896':' 2(120) ',
1302        '1074266112':' 2(210) ','1073742080':' 2(+-0) ','1073741825':'   -1   '
1303        }
1304    return KNsym[key]       
1305
1306def GetNXUPQsym(siteSym):
1307    '''       
1308    The codes XUPQ are for lookup of symmetry constraints for position(X), thermal parm(U) & magnetic moments
1309    (P&Q-not used in GSAS-II)
1310    '''
1311    NXUPQsym = {
1312        '    1   ':(28,29,28,28),'   -1   ':( 1,29,28, 0),'    2(x)':(12,18,12,25),'    m(x)':(25,18,12,25),
1313        '  2/m(x)':( 1,18, 0,-1),'    2(y)':(13,17,13,24),'    m(y)':(24,17,13,24),'  2/m(y)':( 1,17, 0,-1),
1314        '    2(z)':(14,16,14,23),'    m(z)':(23,16,14,23),'  2/m(z)':( 1,16, 0,-1),'   2(yz)':(10,23,10,22),
1315        '   m(yz)':(22,23,10,22),' 2/m(yz)':( 1,23, 0,-1),'  2(0+-)':(11,24,11,21),'  m(0+-)':(21,24,11,21),
1316        '2/m(0+-)':( 1,24, 0,-1),'   2(xz)':( 8,21, 8,20),'   m(xz)':(20,21, 8,20),' 2/m(xz)':( 1,21, 0,-1),
1317        '  2(+0-)':( 9,22, 9,19),'  m(+0-)':(19,22, 9,19),'2/m(+0-)':( 1,22, 0,-1),'   2(xy)':( 6,19, 6,18),
1318        '   m(xy)':(18,19, 6,18),' 2/m(xy)':( 1,19, 0,-1),'  2(+-0)':( 7,20, 7,17),'  m(+-0)':(17,20, 7,17),
1319        '2/m(+-0)':( 1,20, 0,-1),'  mm2(x)':(12,10, 0,-1),'  mm2(y)':(13,10, 0,-1),'  mm2(z)':(14,10, 0,-1),
1320        ' mm2(yz)':(10,13, 0,-1),'mm2(0+-)':(11,13, 0,-1),' mm2(xz)':( 8,12, 0,-1),'mm2(+0-)':( 9,12, 0,-1),
1321        ' mm2(xy)':( 6,11, 0,-1),'mm2(+-0)':( 7,11, 0,-1),'  222   ':( 1,10, 0,-1),'  222(x)':( 1,13, 0,-1),
1322        '  222(y)':( 1,12, 0,-1),'  222(z)':( 1,11, 0,-1),'  mmm   ':( 1,10, 0,-1),'  mmm(x)':( 1,13, 0,-1),
1323        '  mmm(y)':( 1,12, 0,-1),'  mmm(z)':( 1,11, 0,-1),'  4(100)':(12, 4,12, 0),' -4(100)':( 1, 4,12, 0),
1324        '4/m(100)':( 1, 4,12,-1),'422(100)':( 1, 4, 0,-1),'-42m 100':( 1, 4, 0,-1),'4mm(100)':(12, 4, 0,-1),
1325        '4/mmm100':( 1, 4, 0,-1),'  4(010)':(13, 3,13, 0),' -4(010)':( 1, 3,13, 0),'4/m (10)':( 1, 3,13,-1),
1326        '422(010)':( 1, 3, 0,-1),'-42m 010':( 1, 3, 0,-1),'4mm(010)':(13, 3, 0,-1),'4/mmm010':(1, 3, 0,-1,),
1327        '  4(001)':(14, 2,14, 0),' -4(001)':( 1, 2,14, 0),'4/m(001)':( 1, 2,14,-1),'422(001)':( 1, 2, 0,-1),
1328        '-42m 001':( 1, 2, 0,-1),'4mm(001)':(14, 2, 0,-1),'4/mmm001':( 1, 2, 0,-1),'  3(111)':( 2, 5, 2, 0),
1329        ' -3(111)':( 1, 5, 2, 0),' 32(111)':( 1, 5, 0, 2),' 3m(111)':( 2, 5, 0, 2),'-3m(111)':( 1, 5, 0,-1),
1330        '  3(+--)':( 5, 8, 5, 0),' -3(+--)':( 1, 8, 5, 0),' 32(+--)':( 1, 8, 0, 5),' 3m(+--)':( 5, 8, 0, 5),
1331        '-3m(+--)':( 1, 8, 0,-1),'  3(-+-)':( 4, 7, 4, 0),' -3(-+-)':( 1, 7, 4, 0),' 32(-+-)':( 1, 7, 0, 4),
1332        ' 3m(-+-)':( 4, 7, 0, 4),'-3m(-+-)':( 1, 7, 0,-1),'  3(--+)':( 3, 6, 3, 0),' -3(--+)':( 1, 6, 3, 0),
1333        ' 32(--+)':( 1, 6, 0, 3),' 3m(--+)':( 3, 6, 0, 3),'-3m(--+)':( 1, 6, 0,-1),'   23   ':( 1, 1, 0, 0),
1334        '   m3   ':( 1, 1, 0, 0),'   432  ':( 1, 1, 0, 0),'  -43m  ':( 1, 1, 0, 0),'   m3m  ':( 1, 1, 0, 0),
1335        ' mm2d100':(12,13, 0,-1),' mm2d010':(13,12, 0,-1),' mm2d001':(14,11, 0,-1),'-4m2 100':( 1, 4, 0,-1),
1336        '-4m2 010':( 1, 3, 0,-1),'-4m2 001':( 1, 2, 0,-1),'  6/mmm ':( 1, 9, 0,-1),'-6m2 100':( 1, 9, 0,-1),
1337        '-6m2 120':( 1, 9, 0,-1),'   6mm  ':(14, 9, 0,-1),'   622  ':( 1, 9, 0,-1),'   6/m  ':( 1, 9,14,-1),
1338        '   -6   ':( 1, 9,14, 0),'    6   ':(14, 9,14, 0),'-3m(100)':( 1, 9, 0,-1),'-3m(120)':( 1, 9, 0,-1),
1339        ' 3m(100)':(14, 9, 0,14),' 3m(120)':(14, 9, 0,14),' 32(100)':( 1, 9, 0,14),' 32(120)':( 1, 9, 0,14),
1340        '   -3   ':( 1, 9,14, 0),'    3   ':(14, 9,14, 0),'mmm(100)':( 1,14, 0,-1),'mmm(010)':( 1,15, 0,-1),
1341        'mmm(110)':( 1,11, 0,-1),' mm2z100':(14,14, 0,-1),' mm2z010':(14,15, 0,-1),' mm2z110':(14,11, 0,-1),
1342        'mm2(100)':(12,14, 0,-1),'mm2(010)':(13,15, 0,-1),'mm2(110)':( 6,11, 0,-1),'mm2(120)':(15,14, 0,-1),
1343        'mm2(210)':(16,15, 0,-1),'mm2(+-0)':( 7,11, 0,-1),'222(100)':( 1,14, 0,-1),'222(010)':( 1,15, 0,-1),
1344        '222(110)':( 1,11, 0,-1),'2/m(001)':( 1,16,14,-1),'2/m(100)':( 1,25,12,-1),'2/m(010)':( 1,28,13,-1),
1345        '2/m(110)':( 1,19, 6,-1),'2/m(120)':( 1,27,15,-1),'2/m(210)':( 1,26,16,-1),'2/m(+-0)':( 1,20,17,-1),
1346        ' m(001) ':(23,16,14,23),' m(100) ':(26,25,12,26),' m(010) ':(27,28,13,27),' m(110) ':(18,19, 6,18),
1347        ' m(120) ':(24,27,15,24),' m(210) ':(25,26,16,25),' m(+-0) ':(17,20, 7,17),' 2(001) ':(14,16,14,23),
1348        ' 2(100) ':(12,25,12,26),' 2(010) ':(13,28,13,27),' 2(110) ':( 6,19, 6,18),' 2(120) ':(15,27,15,24),
1349        ' 2(210) ':(16,26,16,25),' 2(+-0) ':( 7,20, 7,17),'   -1   ':( 1,29,28, 0)
1350        }
1351    return NXUPQsym[siteSym]
1352
1353def GetCSxinel(siteSym): 
1354    'Needs a doc string'
1355    CSxinel = [[],                         # 0th empty - indices are Fortran style
1356        [[0,0,0],[ 0.0, 0.0, 0.0]],      #1  0  0  0
1357        [[1,1,1],[ 1.0, 1.0, 1.0]],      #2  X  X  X
1358        [[1,1,1],[ 1.0, 1.0,-1.0]],      #3  X  X -X
1359        [[1,1,1],[ 1.0,-1.0, 1.0]],      #4  X -X  X
1360        [[1,1,1],[ 1.0,-1.0,-1.0]],      #5 -X  X  X
1361        [[1,1,0],[ 1.0, 1.0, 0.0]],      #6  X  X  0
1362        [[1,1,0],[ 1.0,-1.0, 0.0]],      #7  X -X  0
1363        [[1,0,1],[ 1.0, 0.0, 1.0]],      #8  X  0  X
1364        [[1,0,1],[ 1.0, 0.0,-1.0]],      #9  X  0 -X
1365        [[0,1,1],[ 0.0, 1.0, 1.0]],      #10  0  Y  Y
1366        [[0,1,1],[ 0.0, 1.0,-1.0]],      #11 0  Y -Y
1367        [[1,0,0],[ 1.0, 0.0, 0.0]],      #12  X  0  0
1368        [[0,1,0],[ 0.0, 1.0, 0.0]],      #13  0  Y  0
1369        [[0,0,1],[ 0.0, 0.0, 1.0]],      #14  0  0  Z
1370        [[1,1,0],[ 1.0, 2.0, 0.0]],      #15  X 2X  0
1371        [[1,1,0],[ 2.0, 1.0, 0.0]],      #16 2X  X  0
1372        [[1,1,2],[ 1.0, 1.0, 1.0]],      #17  X  X  Z
1373        [[1,1,2],[ 1.0,-1.0, 1.0]],      #18  X -X  Z
1374        [[1,2,1],[ 1.0, 1.0, 1.0]],      #19  X  Y  X
1375        [[1,2,1],[ 1.0, 1.0,-1.0]],      #20  X  Y -X
1376        [[1,2,2],[ 1.0, 1.0, 1.0]],      #21  X  Y  Y
1377        [[1,2,2],[ 1.0, 1.0,-1.0]],      #22  X  Y -Y
1378        [[1,2,0],[ 1.0, 1.0, 0.0]],      #23  X  Y  0
1379        [[1,0,2],[ 1.0, 0.0, 1.0]],      #24  X  0  Z
1380        [[0,1,2],[ 0.0, 1.0, 1.0]],      #25  0  Y  Z
1381        [[1,1,2],[ 1.0, 2.0, 1.0]],      #26  X 2X  Z
1382        [[1,1,2],[ 2.0, 1.0, 1.0]],      #27 2X  X  Z
1383        [[1,2,3],[ 1.0, 1.0, 1.0]],      #28  X  Y  Z
1384        ]
1385    indx = GetNXUPQsym(siteSym)
1386    return CSxinel[indx[0]]
1387   
1388def GetCSuinel(siteSym):
1389    "returns Uij terms, multipliers, GUI flags & Uiso2Uij multipliers"
1390    CSuinel = [[],                                             # 0th empty - indices are Fortran style
1391        [[1,1,1,0,0,0],[ 1.0, 1.0, 1.0, 0.0, 0.0, 0.0],[1,0,0,0,0,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #1  A  A  A  0  0  0
1392        [[1,1,2,0,0,0],[ 1.0, 1.0, 1.0, 0.0, 0.0, 0.0],[1,0,1,0,0,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #2  A  A  C  0  0  0
1393        [[1,2,1,0,0,0],[ 1.0, 1.0, 1.0, 0.0, 0.0, 0.0],[1,1,0,0,0,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #3  A  B  A  0  0  0
1394        [[1,2,2,0,0,0],[ 1.0, 1.0, 1.0, 0.0, 0.0, 0.0],[1,1,0,0,0,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #4  A  B  B  0  0  0
1395        [[1,1,1,2,2,2],[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],[1,0,0,1,0,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #5  A  A  A  D  D  D
1396        [[1,1,1,2,2,2],[ 1.0, 1.0, 1.0, 1.0,-1.0,-1.0],[1,0,0,1,0,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #6  A  A  A  D -D -D
1397        [[1,1,1,2,2,2],[ 1.0, 1.0, 1.0, 1.0,-1.0, 1.0],[1,0,0,1,0,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #7  A  A  A  D -D  D
1398        [[1,1,1,2,2,2],[ 1.0, 1.0, 1.0, 1.0, 1.0,-1.0],[1,0,0,1,0,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #8  A  A  A  D  D -D
1399        [[1,1,2,1,0,0],[ 1.0, 1.0, 1.0, 0.5, 0.0, 0.0],[1,0,1,0,0,0],[1.0,1.0,1.0,0.5,0.0,0.0]],    #9  A  A  C A/2 0  0
1400        [[1,2,3,0,0,0],[ 1.0, 1.0, 1.0, 0.0, 0.0, 0.0],[1,1,1,0,0,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #10  A  B  C  0  0  0
1401        [[1,1,2,3,0,0],[ 1.0, 1.0, 1.0, 1.0, 0.0, 0.0],[1,0,1,1,0,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #11  A  A  C  D  0  0
1402        [[1,2,1,0,3,0],[ 1.0, 1.0, 1.0, 0.0, 1.0, 0.0],[1,1,0,0,1,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #12  A  B  A  0  E  0
1403        [[1,2,2,0,0,3],[ 1.0, 1.0, 1.0, 0.0, 0.0, 1.0],[1,1,0,0,0,1],[1.0,1.0,1.0,0.0,0.0,0.0]],    #13  A  B  B  0  0  F
1404        [[1,2,3,2,0,0],[ 1.0, 1.0, 1.0, 0.5, 0.0, 0.0],[1,1,1,0,0,0],[1.0,1.0,1.0,0.0,0.5,0.0]],    #14  A  B  C B/2 0  0
1405        [[1,2,3,1,0,0],[ 1.0, 1.0, 1.0, 0.5, 0.0, 0.0],[1,1,1,0,0,0],[1.0,1.0,1.0,0.0,0.5,0.0]],    #15  A  B  C A/2 0  0
1406        [[1,2,3,4,0,0],[ 1.0, 1.0, 1.0, 1.0, 0.0, 0.0],[1,1,1,1,0,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #16  A  B  C  D  0  0
1407        [[1,2,3,0,4,0],[ 1.0, 1.0, 1.0, 0.0, 1.0, 0.0],[1,1,1,0,1,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #17  A  B  C  0  E  0
1408        [[1,2,3,0,0,4],[ 1.0, 1.0, 1.0, 0.0, 0.0, 1.0],[1,1,1,0,0,1],[1.0,1.0,1.0,0.0,0.0,0.0]],    #18  A  B  C  0  0  F
1409        [[1,1,2,3,4,4],[ 1.0, 1.0, 1.0, 1.0, 1.0,-1.0],[1,0,1,1,1,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #19  A  A  C  D  E -E
1410        [[1,1,2,3,4,4],[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],[1,0,1,1,1,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #20  A  A  C  D  E  E
1411        [[1,2,1,3,4,3],[ 1.0, 1.0, 1.0, 1.0, 1.0,-1.0],[1,1,0,1,1,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #21  A  B  A  D  E -D
1412        [[1,2,1,3,4,3],[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],[1,1,0,1,1,0],[1.0,1.0,1.0,0.0,0.0,0.0]],    #22  A  B  A  D  E  D
1413        [[1,2,2,3,3,4],[ 1.0, 1.0, 1.0, 1.0,-1.0, 1.0],[1,1,0,1,0,1],[1.0,1.0,1.0,0.0,0.0,0.0]],    #23  A  B  B  D -D  F
1414        [[1,2,2,3,3,4],[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],[1,1,0,1,0,1],[1.0,1.0,1.0,0.0,0.0,0.0]],    #24  A  B  B  D  D  F
1415        [[1,2,3,2,4,4],[ 1.0, 1.0, 1.0, 0.5, 0.5, 1.0],[1,1,1,0,0,1],[1.0,1.0,1.0,0.5,0.0,0.0]],    #25  A  B  C B/2 F/2 F
1416        [[1,2,3,1,0,4],[ 1.0, 1.0, 1.0, 0.5, 0.0, 1.0],[1,1,1,0,0,1],[1.0,1.0,1.0,0.5,0.0,0.0]],    #26  A  B  C A/2  0  F
1417        [[1,2,3,2,4,0],[ 1.0, 1.0, 1.0, 0.5, 1.0, 0.0],[1,1,1,0,1,0],[1.0,1.0,1.0,0.5,0.0,0.0]],    #27  A  B  C B/2  E  0
1418        [[1,2,3,1,4,4],[ 1.0, 1.0, 1.0, 0.5, 1.0, 0.5],[1,1,1,0,1,0],[1.0,1.0,1.0,0.5,0.0,0.0]],    #28  A  B  C A/2  E E/2
1419        [[1,2,3,4,5,6],[ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0],[1,1,1,1,1,1],[1.0,1.0,1.0,0.0,0.0,0.0]],    #29  A  B  C  D  E   F
1420        ]
1421    indx = GetNXUPQsym(siteSym)
1422    return CSuinel[indx[1]]
1423   
1424def GetSSfxuinel(XYZ,UIJ,SGData,SSGData):
1425    CSI = {'Sfrac':[[1,2],[1.,1.]],'Spos':[[1,2,3, 4,5,6],[1.,1.,1., 1.,1.,1.]],    #sin & cos
1426        'Sadp':[[1,2,3,4,5,6, 7,8,9,10,11,12],[1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.]],
1427        'Smag':[[1,2,3, 4,5,6],[1.,1.,1., 1.,1.,1.]]}
1428    deltx = np.ones((3,4))*.01
1429    deltx[:3,:3] = np.eye((3))*.001
1430    deltu = np.eye((6))*.0001
1431    xyz = np.array(XYZ)%1.
1432    xyzt = np.array(XYZ+[0,])%1.
1433    uij = np.array(UIJ)
1434    SGOps = SGData['SGOps']
1435    SSGOps = SSGData['SSGOps']
1436    ssop = SSGOps[0]
1437    sop = SGOps[0]
1438    for iop,Op in enumerate(SGOps):
1439        nxyz = (np.inner(Op[0],xyz)+Op[1])%1.
1440        if SGData['SGInv'] and np.allclose(xyz,-nxyz%1.,1.e-6):
1441            ssop = SSGOps[iop]
1442            ssop = [-ssop[0],-ssop[1]%1.]
1443            sop = [-Op[0],-Op[1]%1.]
1444            break
1445        elif np.allclose(xyz,nxyz,1.e-6) and iop:
1446            ssop = SSGOps[iop]
1447            sop = SGOps[iop]
1448            break
1449    siteSym = SytSym(XYZ,SGData)[0].strip().split('(')[0]
1450    OpText =  MT2text(sop).replace(' ','')
1451    SSOptext = SSMT2text(ssop).replace(' ','')
1452    if siteSym == '1':   #"1" site symmetry
1453        return CSI
1454    elif siteSym == '-1':   #"-1" site symmetry
1455        CSI['Spos'][0] = [1,2,3, 0,0,0]
1456        CSI['Sadp'][0] = [0,0,0,0,0,0, 1,2,3,4,5,6]
1457        return CSI
1458    return CSI  #for now       
1459#    print siteSym,OpText,SSOptext   
1460    UniqAx = {'a':'a','b':'b','c':'g'}
1461    if SGData['SGLaue'] == '2/m':
1462        if UniqAx[SGData['SGUniq']] in SSGData['modSymb']:   #e.g. (0b0)
1463            if 's' in SSGData['SSpGrp'].split('(')[1]:
1464                if siteSym == 'm':
1465                    CSI['Spos'][0] = [1,0,2, 0,3,0]
1466                    CSI['Sadp'][0] = [1,2,3,0,4,0, 0,0,0,5,0,6]
1467                elif siteSym == '2/m':
1468                    CSI['Spos'][0] = [1,0,2, 0,0,0]
1469                    CSI['Sadp'][0] = [0,0,0,0,0,0, 0,0,0,1,0,2]
1470                elif siteSym == '2':
1471                    CSI['Spos'][0] = [1,0,2, 3,0,4]               
1472                    CSI['Sadp'][0] = [0,0,0,1,0,2, 0,0,0,3,0,4]
1473            elif '1/2' in SSGData['modSymb']:    #e.g. (0b1/2)
1474                if siteSym == 'm':
1475                    CSI['Spos'][0] = [0,0,0, 0,0,0]
1476                    CSI['Sadp'][0] = [0,0,0,0,0,0, 0,0,0,0,0,0]
1477                elif siteSym == '2/m':
1478                    CSI['Spos'][0] = [1,0,2, 0,0,0]
1479                    CSI['Sadp'][0] = [0,0,0,0,0,0, 1,2,3,0,4,0]
1480                elif siteSym == '2':
1481                    CSI['Spos'][0] = [1,0,2, 3,0,4]
1482                    CSI['Sadp'][0] = [0,0,0,1,0,2, 0,0,0,3,0,4]
1483            else:
1484                if siteSym == 'm':
1485                    CSI['Spos'][0] = [0,1,0, 2,0,3]
1486                    CSI['Sadp'][0] = [0,0,0,1,0,2, 3,4,5,0,6,0]
1487                elif siteSym == '2/m':
1488                    CSI['Spos'][0] = [0,1,0, 0,0,0]
1489                    CSI['Sadp'][0] = [0,0,0,0,0,0, 1,2,3,0,4,0]
1490                elif siteSym == '2':
1491                    CSI['Spos'][0] = [0,1,0, 0,2,0]
1492                    CSI['Sadp'][0] = [1,2,3,0,4,0, 5,6,7,0,8,0]
1493           
1494        else:   #e.g. (a0g)
1495            if 's' in SSGData['SSpGrp'].split('(')[1]:
1496                if siteSym == 'm':
1497                    CSI['Spos'][0] = [0,1,0, 0,2,0]
1498                    CSI['Sadp'][0] = [0,0,0,1,0,2, 0,0,0,3,0,4]
1499                elif siteSym == '2/m':
1500                    CSI['Spos'][0] = [0,1,0, 0,0,0]
1501                    CSI['Sadp'][0] = [0,0,0,0,0,0, 0,0,0,1,0,2]
1502                elif siteSym == '2':
1503                    CSI['Spos'][0] = [0,1,0, 2,0,3]
1504                    CSI['Sadp'][0] = [1,2,3,0,4,0, 0,0,0,5,0,6]
1505            else:
1506                if siteSym == 'm':
1507                    CSI['Spos'][0] = [1,0,2, 3,0,4]
1508                    CSI['Sadp'][0] = [1,2,3,0,4,0, 5,6,7,0,8,0]
1509                elif siteSym == '2/m':
1510                    CSI['Spos'][0] = [1,0,2, 0,0,0]
1511                    CSI['Sadp'][0] = [0,0,0,0,0,0, 1,2,3,0,4,0]
1512                elif siteSym == '2':
1513                    CSI['Spos'][0] = [1,0,2, 0,3,0]
1514                    CSI['Sadp'][0] = [0,0,0,1,0,2, 3,4,5,0,6,0]
1515        Sx = CSI['Spos'][0]
1516        Su = CSI['Sadp'][0]
1517        if SGData['SGUniq'] == 'a':
1518            CSI['Spos'][0] = [Sx[1],Sx[2],Sx[0], Sx[4],Sx[5],Sx[3]]
1519            CSI['Sadp'][0] = [Su[1],Sx[2],Sx[0],Su[4],Su[5],Su[3], Su[7],Su[8],Su[6],Su[10],Su[11],Su[9]]
1520        elif SGData['SGUniq'] == 'c':
1521            CSI['Spos'][0] = [Sx[2],Sx[0],Sx[1], Sx[5],Sx[3],Sx[4]]
1522            CSI['Sadp'][0] = [Su[2],Su[0],Su[1],Su[5],Su[3],Su[4], Su[8],Su[6],Su[7],Su[11],Su[9],Su[10]]
1523#        return CSI
1524#    elif SGData['SGLaue'] == 'mmm':
1525#    elif SGData['SGLaue'] in ['4/m','4/mmm']:
1526#    elif SGData['SGLaue'] in ['3','3m1','31m']:
1527#    elif SGData['SGLaue'] in ['6/m','6/mmm']:
1528#       
1529    xsin = np.zeros(3,dtype='i')
1530    xcos = np.zeros(3,dtype='i')
1531    usin = np.zeros(6,dtype='i')
1532    ucos = np.zeros(6,dtype='i')
1533    csi = np.ones((6),dtype='i')*-1
1534    for i,idelt in enumerate(deltx):
1535#        print 'idelt:',idelt
1536        nxyzt = np.inner(ssop[0],(xyzt+idelt))+ssop[1]
1537        nxyzt[3] -= ssop[1][3]
1538#        print 'nxyz',nxyzt
1539        xsin[i] = np.allclose((xyzt-idelt),nxyzt,1.e-6)
1540#        print 'sin ',(xyzt-idelt),xsin[i]
1541        xcos[i] = np.allclose((xyzt+idelt),nxyzt,1.e-6)
1542#        print 'cos ',(xyzt+idelt),xcos[i]
1543    n = -1
1544    for i,isin in enumerate(xsin):
1545        if isin:
1546            n += 1
1547            csi[i] = n
1548    for i,icos in enumerate(xcos):
1549        if icos:
1550            n += 1
1551            csi[i+3] = n
1552#    print csi
1553#    print CSI['Spos'][0]
1554#    print xsin,xcos
1555    for i,idelt in enumerate(deltu):
1556        nuij = U2Uij(np.inner(sop[0],np.inner(np.abs(Uij2U(uij+idelt)),sop[0])))
1557        usin[i] = np.equal(np.abs(uij-idelt),nuij)[i]
1558        ucos[i] = np.equal(np.abs(uij+idelt),nuij)[i]
1559#    print CSI['Sadp'][0]
1560#    print usin,ucos
1561    return CSI
1562   
1563def MustrainNames(SGData):
1564    'Needs a doc string'
1565    laue = SGData['SGLaue']
1566    uniq = SGData['SGUniq']
1567    if laue in ['m3','m3m']:
1568        return ['S400','S220']
1569    elif laue in ['6/m','6/mmm','3m1']:
1570        return ['S400','S004','S202']
1571    elif laue in ['31m','3']:
1572        return ['S400','S004','S202','S211']
1573    elif laue in ['3R','3mR']:
1574        return ['S400','S220','S310','S211']
1575    elif laue in ['4/m','4/mmm']:
1576        return ['S400','S004','S220','S022']
1577    elif laue in ['mmm']:
1578        return ['S400','S040','S004','S220','S202','S022']
1579    elif laue in ['2/m']:
1580        SHKL = ['S400','S040','S004','S220','S202','S022']
1581        if uniq == 'a':
1582            SHKL += ['S013','S031','S211']
1583        elif uniq == 'b':
1584            SHKL += ['S301','S103','S121']
1585        elif uniq == 'c':
1586            SHKL += ['S130','S310','S112']
1587        return SHKL
1588    else:
1589        SHKL = ['S400','S040','S004','S220','S202','S022']
1590        SHKL += ['S310','S103','S031','S130','S301','S013']
1591        SHKL += ['S211','S121','S112']
1592        return SHKL
1593       
1594def HStrainVals(HSvals,SGData):
1595    laue = SGData['SGLaue']
1596    uniq = SGData['SGUniq']
1597    DIJ = np.zeros(6)
1598    if laue in ['m3','m3m']:
1599        DIJ[:3] = [HSvals[0],HSvals[0],HSvals[0]]
1600    elif laue in ['6/m','6/mmm','3m1','31m','3']:
1601        DIJ[:4] = [HSvals[0],HSvals[0],HSvals[1],HSvals[0]]
1602    elif laue in ['3R','3mR']:
1603        DIJ = [HSvals[0],HSvals[0],HSvals[0],HSvals[1],HSvals[1],HSvals[1]]
1604    elif laue in ['4/m','4/mmm']:
1605        DIJ[:3] = [HSvals[0],HSvals[0],HSvals[1]]
1606    elif laue in ['mmm']:
1607        DIJ[:3] = [HSvals[0],HSvals[1],HSvals[2]]
1608    elif laue in ['2/m']:
1609        DIJ[:3] = [HSvals[0],HSvals[1],HSvals[2]]
1610        if uniq == 'a':
1611            DIJ[5] = HSvals[3]
1612        elif uniq == 'b':
1613            DIJ[4] = HSvals[3]
1614        elif uniq == 'c':
1615            DIJ[3] = HSvals[3]
1616    else:
1617        DIJ = [HSvals[0],HSvals[1],HSvals[2],HSvals[3],HSvals[4],HSvals[5]]
1618    return DIJ
1619
1620def HStrainNames(SGData):
1621    'Needs a doc string'
1622    laue = SGData['SGLaue']
1623    uniq = SGData['SGUniq']
1624    if laue in ['m3','m3m']:
1625        return ['D11','eA']         #add cubic strain term
1626    elif laue in ['6/m','6/mmm','3m1','31m','3']:
1627        return ['D11','D33']
1628    elif laue in ['3R','3mR']:
1629        return ['D11','D12']
1630    elif laue in ['4/m','4/mmm']:
1631        return ['D11','D33']
1632    elif laue in ['mmm']:
1633        return ['D11','D22','D33']
1634    elif laue in ['2/m']:
1635        Dij = ['D11','D22','D33']
1636        if uniq == 'a':
1637            Dij += ['D23']
1638        elif uniq == 'b':
1639            Dij += ['D13']
1640        elif uniq == 'c':
1641            Dij += ['D12']
1642        return Dij
1643    else:
1644        Dij = ['D11','D22','D33','D12','D13','D23']
1645        return Dij
1646   
1647def MustrainCoeff(HKL,SGData):
1648    'Needs a doc string'
1649    #NB: order of terms is the same as returned by MustrainNames
1650    laue = SGData['SGLaue']
1651    uniq = SGData['SGUniq']
1652    h,k,l = HKL
1653    Strm = []
1654    if laue in ['m3','m3m']:
1655        Strm.append(h**4+k**4+l**4)
1656        Strm.append(3.0*((h*k)**2+(h*l)**2+(k*l)**2))
1657    elif laue in ['6/m','6/mmm','3m1']:
1658        Strm.append(h**4+k**4+2.0*k*h**3+2.0*h*k**3+3.0*(h*k)**2)
1659        Strm.append(l**4)
1660        Strm.append(3.0*((h*l)**2+(k*l)**2+h*k*l**2))
1661    elif laue in ['31m','3']:
1662        Strm.append(h**4+k**4+2.0*k*h**3+2.0*h*k**3+3.0*(h*k)**2)
1663        Strm.append(l**4)
1664        Strm.append(3.0*((h*l)**2+(k*l)**2+h*k*l**2))
1665        Strm.append(4.0*h*k*l*(h+k))
1666    elif laue in ['3R','3mR']:
1667        Strm.append(h**4+k**4+l**4)
1668        Strm.append(3.0*((h*k)**2+(h*l)**2+(k*l)**2))
1669        Strm.append(2.0*(h*l**3+l*k**3+k*h**3)+2.0*(l*h**3+k*l**3+l*k**3))
1670        Strm.append(4.0*(k*l*h**2+h*l*k**2+h*k*l**2))
1671    elif laue in ['4/m','4/mmm']:
1672        Strm.append(h**4+k**4)
1673        Strm.append(l**4)
1674        Strm.append(3.0*(h*k)**2)
1675        Strm.append(3.0*((h*l)**2+(k*l)**2))
1676    elif laue in ['mmm']:
1677        Strm.append(h**4)
1678        Strm.append(k**4)
1679        Strm.append(l**4)
1680        Strm.append(3.0*(h*k)**2)
1681        Strm.append(3.0*(h*l)**2)
1682        Strm.append(3.0*(k*l)**2)
1683    elif laue in ['2/m']:
1684        Strm.append(h**4)
1685        Strm.append(k**4)
1686        Strm.append(l**4)
1687        Strm.append(3.0*(h*k)**2)
1688        Strm.append(3.0*(h*l)**2)
1689        Strm.append(3.0*(k*l)**2)
1690        if uniq == 'a':
1691            Strm.append(2.0*k*l**3)
1692            Strm.append(2.0*l*k**3)
1693            Strm.append(4.0*k*l*h**2)
1694        elif uniq == 'b':
1695            Strm.append(2.0*l*h**3)
1696            Strm.append(2.0*h*l**3)
1697            Strm.append(4.0*h*l*k**2)
1698        elif uniq == 'c':
1699            Strm.append(2.0*h*k**3)
1700            Strm.append(2.0*k*h**3)
1701            Strm.append(4.0*h*k*l**2)
1702    else:
1703        Strm.append(h**4)
1704        Strm.append(k**4)
1705        Strm.append(l**4)
1706        Strm.append(3.0*(h*k)**2)
1707        Strm.append(3.0*(h*l)**2)
1708        Strm.append(3.0*(k*l)**2)
1709        Strm.append(2.0*k*h**3)
1710        Strm.append(2.0*h*l**3)
1711        Strm.append(2.0*l*k**3)
1712        Strm.append(2.0*h*k**3)
1713        Strm.append(2.0*l*h**3)
1714        Strm.append(2.0*k*l**3)
1715        Strm.append(4.0*k*l*h**2)
1716        Strm.append(4.0*h*l*k**2)
1717        Strm.append(4.0*k*h*l**2)
1718    return Strm
1719   
1720def Muiso2Shkl(muiso,SGData,cell):
1721    "this is to convert isotropic mustrain to generalized Shkls"
1722    import GSASIIlattice as G2lat
1723    A = G2lat.cell2AB(cell)[0]
1724   
1725    def minMus(Shkl,muiso,H,SGData,A):
1726        U = np.inner(A.T,H)
1727        S = np.array(MustrainCoeff(U,SGData))
1728        Sum = np.sqrt(np.sum(np.multiply(S,Shkl[:,np.newaxis]),axis=0))
1729        rad = np.sqrt(np.sum((Sum[:,np.newaxis]*H)**2,axis=1))
1730        return (muiso-rad)**2
1731       
1732    laue = SGData['SGLaue']
1733    PHI = np.linspace(0.,360.,60,True)
1734    PSI = np.linspace(0.,180.,60,True)
1735    X = np.outer(npsind(PHI),npsind(PSI))
1736    Y = np.outer(npcosd(PHI),npsind(PSI))
1737    Z = np.outer(np.ones(np.size(PHI)),npcosd(PSI))
1738    HKL = np.dstack((X,Y,Z))
1739    if laue in ['m3','m3m']:
1740        S0 = [1000.,1000.]
1741    elif laue in ['6/m','6/mmm','3m1']:
1742        S0 = [1000.,1000.,1000.]
1743    elif laue in ['31m','3']:
1744        S0 = [1000.,1000.,1000.,1000.]
1745    elif laue in ['3R','3mR']:
1746        S0 = [1000.,1000.,1000.,1000.]
1747    elif laue in ['4/m','4/mmm']:
1748        S0 = [1000.,1000.,1000.,1000.]
1749    elif laue in ['mmm']:
1750        S0 = [1000.,1000.,1000.,1000.,1000.,1000.]
1751    elif laue in ['2/m']:
1752        S0 = [1000.,1000.,1000.,0.,0.,0.,0.,0.,0.]
1753    else:
1754        S0 = [1000.,1000.,1000.,1000.,1000., 1000.,1000.,1000.,1000.,1000., 
1755            1000.,1000.,0.,0.,0.]
1756    S0 = np.array(S0)
1757    HKL = np.reshape(HKL,(-1,3))
1758    result = so.leastsq(minMus,S0,(np.ones(HKL.shape[0])*muiso,HKL,SGData,A))
1759    return result[0]
1760       
1761def SytSym(XYZ,SGData):
1762    '''
1763    Generates the number of equivalent positions and a site symmetry code for a specified coordinate and space group
1764
1765    :param XYZ: an array, tuple or list containing 3 elements: x, y & z
1766    :param SGData: from SpcGroup
1767    :Returns: a two element tuple:
1768
1769     * The 1st element is a code for the site symmetry (see GetKNsym)
1770     * The 2nd element is the site multiplicity
1771
1772    '''
1773    def PackRot(SGOps):
1774        IRT = []
1775        for ops in SGOps:
1776            M = ops[0]
1777            irt = 0
1778            for j in range(2,-1,-1):
1779                for k in range(2,-1,-1):
1780                    irt *= 3
1781                    irt += M[k][j]
1782            IRT.append(int(irt))
1783        return IRT
1784       
1785    SymName = ''
1786    Mult = 1
1787    Isym = 0
1788    if SGData['SGLaue'] in ['3','3m1','31m','6/m','6/mmm']:
1789        Isym = 1073741824
1790    Jdup = 0
1791    Xeqv = GenAtom(XYZ,SGData,True)
1792    IRT = PackRot(SGData['SGOps'])
1793    L = -1
1794    for ic,cen in enumerate(SGData['SGCen']):
1795        for invers in range(int(SGData['SGInv']+1)):
1796            for io,ops in enumerate(SGData['SGOps']):
1797                irtx = (1-2*invers)*IRT[io]
1798                L += 1
1799                if not Xeqv[L][1]:
1800                    Jdup += 1
1801                    jx = GetOprPtrName(str(irtx))
1802                    if jx[2] < 39:
1803                        Isym += 2**(jx[2]-1)
1804    if Isym == 1073741824: Isym = 0
1805    Mult = len(SGData['SGOps'])*len(SGData['SGCen'])*(int(SGData['SGInv'])+1)/Jdup
1806         
1807    return GetKNsym(str(Isym)),Mult
1808   
1809def ElemPosition(SGData):
1810    ''' Under development.
1811    Object here is to return a list of symmetry element types and locations suitable
1812    for say drawing them.
1813    So far I have the element type... getting all possible locations without lookup may be impossible!
1814    '''
1815    SymElements = []
1816    Inv = SGData['SGInv']
1817    Cen = SGData['SGCen']
1818    eleSym = {-3:['','-1'],-2:['',-6],-1:['2','-4'],0:['3','-3'],1:['4','m'],2:['6',''],3:['1','']}
1819    # get operators & expand if centrosymmetric
1820    Ops = SGData['SGOps']
1821    opM = np.array([op[0].T for op in Ops])
1822    opT = np.array([op[1] for op in Ops])
1823    if Inv:
1824        opM = np.concatenate((opM,-opM))
1825        opT = np.concatenate((opT,-opT))
1826    opMT = zip(opM,opT)
1827    for M,T in opMT[1:]:        #skip I
1828        Dt = int(nl.det(M))
1829        Tr = int(np.trace(M))
1830        Dt = -(Dt-1)/2
1831        Es = eleSym[Tr][Dt]
1832        if Dt:              #rotation-inversion
1833            I = np.eye(3)
1834            if Tr == 1:     #mirrors/glides
1835                if np.any(T):       #glide
1836                    M2 = np.inner(M,M)
1837                    MT = np.inner(M,T)+T
1838                    print 'glide',Es,MT
1839                    print M2
1840                else:               #mirror
1841                    print 'mirror',Es,T
1842                    print I-M
1843                X = [-1,-1,-1]
1844            elif Tr == -3:  # pure inversion
1845                X = np.inner(nl.inv(I-M),T)
1846                print 'inversion',Es,X
1847            else:           #other rotation-inversion
1848                M2 = np.inner(M,M)
1849                MT = np.inner(M,T)+T
1850                print 'rot-inv',Es,MT
1851                print M2
1852                X = [-1,-1,-1]
1853        else:               #rotations
1854            print 'rotation',Es
1855            X = [-1,-1,-1]
1856        #SymElements.append([Es,X])
1857       
1858    return #SymElements
1859   
1860def ApplyStringOps(A,SGData,X,Uij=[]):
1861    'Needs a doc string'
1862    SGOps = SGData['SGOps']
1863    SGCen = SGData['SGCen']
1864    Ax = A.split('+')
1865    Ax[0] = int(Ax[0])
1866    iC = 0
1867    if Ax[0] < 0:
1868        iC = 1
1869    Ax[0] = abs(Ax[0])
1870    nA = Ax[0]%100-1
1871    cA = Ax[0]/100
1872    Cen = SGCen[cA]
1873    M,T = SGOps[nA]
1874    if len(Ax)>1:
1875        cellA = Ax[1].split(',')
1876        cellA = np.array([int(a) for a in cellA])
1877    else:
1878        cellA = np.zeros(3)
1879    newX = (1-2*iC)*(Cen+np.inner(M,X)+T)+cellA
1880    if len(Uij):
1881        U = Uij2U(Uij)
1882        U = np.inner(M,np.inner(U,M).T)
1883        newUij = U2Uij(U)
1884        return [newX,newUij]
1885    else:
1886        return newX
1887       
1888def StringOpsProd(A,B,SGData):
1889    """
1890    Find A*B where A & B are in strings '-' + '100*c+n' + '+ijk'
1891    where '-' indicates inversion, c(>0) is the cell centering operator,
1892    n is operator number from SgOps and ijk are unit cell translations (each may be <0).
1893    Should return resultant string - C. SGData - dictionary using entries:
1894
1895       *  'SGCen': cell centering vectors [0,0,0] at least
1896       *  'SGOps': symmetry operations as [M,T] so that M*x+T = x'
1897
1898    """
1899    SGOps = SGData['SGOps']
1900    SGCen = SGData['SGCen']
1901    #1st split out the cell translation part & work on the operator parts
1902    Ax = A.split('+'); Bx = B.split('+')
1903    Ax[0] = int(Ax[0]); Bx[0] = int(Bx[0])
1904    iC = 0
1905    if Ax[0]*Bx[0] < 0:
1906        iC = 1
1907    Ax[0] = abs(Ax[0]); Bx[0] = abs(Bx[0])
1908    nA = Ax[0]%100-1;  nB = Bx[0]%100-1
1909    cA = Ax[0]/100;  cB = Bx[0]/100
1910    Cen = (SGCen[cA]+SGCen[cB])%1.0
1911    cC = np.nonzero([np.allclose(C,Cen) for C in SGCen])[0][0]
1912    Ma,Ta = SGOps[nA]; Mb,Tb = SGOps[nB]
1913    Mc = np.inner(Ma,Mb.T)
1914#    print Ma,Mb,Mc
1915    Tc = (np.add(np.inner(Mb,Ta)+1.,Tb))%1.0
1916#    print Ta,Tb,Tc
1917#    print [np.allclose(M,Mc)&np.allclose(T,Tc) for M,T in SGOps]
1918    nC = np.nonzero([np.allclose(M,Mc)&np.allclose(T,Tc) for M,T in SGOps])[0][0]
1919    #now the cell translation part
1920    if len(Ax)>1:
1921        cellA = Ax[1].split(',')
1922        cellA = [int(a) for a in cellA]
1923    else:
1924        cellA = [0,0,0]
1925    if len(Bx)>1:
1926        cellB = Bx[1].split(',')
1927        cellB = [int(b) for b in cellB]
1928    else:
1929        cellB = [0,0,0]
1930    cellC = np.add(cellA,cellB)
1931    C = str(((nC+1)+(100*cC))*(1-2*iC))+'+'+ \
1932        str(int(cellC[0]))+','+str(int(cellC[1]))+','+str(int(cellC[2]))
1933    return C
1934           
1935def U2Uij(U):
1936    #returns the UIJ vector U11,U22,U33,U12,U13,U23 from tensor U
1937    return [U[0][0],U[1][1],U[2][2],2.*U[0][1],2.*U[0][2],2.*U[1][2]]
1938   
1939def Uij2U(Uij):
1940    #returns the thermal motion tensor U from Uij as numpy array
1941    return np.array([[Uij[0],Uij[3]/2.,Uij[4]/2.],[Uij[3]/2.,Uij[1],Uij[5]/2.],[Uij[4]/2.,Uij[5]/2.,Uij[2]]])
1942
1943def StandardizeSpcName(spcgroup):
1944    '''Accept a spacegroup name where spaces may have not been used
1945    in the names according to the GSAS convention (spaces between symmetry
1946    for each axis) and return the space group name as used in GSAS
1947    '''
1948    rspc = spcgroup.replace(' ','').upper()
1949    # deal with rhombohedral and hexagonal setting designations
1950    rhomb = ''
1951    if rspc[-1:] == 'R':
1952        rspc = rspc[:-1]
1953        rhomb = ' R'
1954    elif rspc[-1:] == 'H': # hexagonal is assumed and thus can be ignored
1955        rspc = rspc[:-1]
1956    # look for a match in the spacegroup lists
1957    for i in spglist.values():
1958        for spc in i:
1959            if rspc == spc.replace(' ','').upper():
1960                return spc + rhomb
1961    # how about the post-2002 orthorhombic names?
1962    for i,spc in sgequiv_2002_orthorhombic:
1963        if rspc == i.replace(' ','').upper():
1964            return spc
1965    # not found
1966    return ''
1967
1968   
1969spglist = {}
1970'''A dictionary of space groups as ordered and named in the pre-2002 International
1971Tables Volume A, except that spaces are used following the GSAS convention to
1972separate the different crystallographic directions.
1973Note that the symmetry codes here will recognize many non-standard space group
1974symbols with different settings. They are ordered by Laue group
1975'''
1976spglist = {
1977    'P1' : ('P 1','P -1',), # 1-2
1978    'P2/m': ('P 2','P 21','P m','P a','P c','P n',
1979        'P 2/m','P 21/m','P 2/c','P 2/a','P 2/n','P 21/c','P 21/a','P 21/n',), #3-15
1980    'C2/m':('C 2','C m','C c','C n',
1981        'C 2/m','C 2/c','C 2/n',),
1982    'Pmmm':('P 2 2 2',
1983        'P 2 2 21','P 21 2 2','P 2 21 2',
1984        'P 21 21 2','P 2 21 21','P 21 2 21',
1985        'P 21 21 21',
1986        'P m m 2','P 2 m m','P m 2 m',
1987        'P m c 21','P 21 m a','P b 21 m','P m 21 b','P c m 21','P 21 a m',
1988        'P c c 2','P 2 a a','P b 2 b',
1989        'P m a 2','P 2 m b','P c 2 m','P m 2 a','P b m 2','P 2 c m',
1990        'P c a 21','P 21 a b','P c 21 b','P b 21 a','P b c 21','P 21 c a',
1991        'P n c 2','P 2 n a','P b 2 n','P n 2 b','P c n 2','P 2 a n',
1992        'P m n 21','P 21 m n','P n 21 m','P m 21 n','P n m 21','P 21 n m',
1993        'P b a 2','P 2 c b','P c 2 a',
1994        'P n a 21','P 21 n b','P c 21 n','P n 21 a','P b n 21','P 21 c n',
1995        'P n n 2','P 2 n n','P n 2 n',
1996        'P m m m','P n n n',
1997        'P c c m','P m a a','P b m b',
1998        'P b a n','P n c b','P c n a',
1999        'P m m a','P b m m','P m c m','P m a m','P m m b','P c m m',
2000        'P n n a','P b n n','P n c n','P n a n','P n n b','P c n n',
2001        'P m n a','P b m n','P n c m','P m a n','P n m b','P c n m',
2002        'P c c a','P b a a','P b c b','P b a b','P c c b','P c a a',
2003        'P b a m','P m c b','P c m a',
2004        'P c c n','P n a a','P b n b',
2005        'P b c m','P m c a','P b m a','P c m b','P c a m','P m a b',
2006        'P n n m','P m n n','P n m n',
2007        'P m m n','P n m m','P m n m',
2008        'P b c n','P n c a','P b n a','P c n b','P c a n','P n a b',
2009        'P b c a','P c a b',
2010        'P n m a','P b n m','P m c n','P n a m','P m n b','P c m n',
2011        ),
2012    'Cmmm':('C 2 2 21','C 2 2 2','C m m 2',
2013        'C m c 21','C c m 21','C c c 2','C m 2 m','C 2 m m',
2014        'C m 2 a','C 2 m b','C c 2 m','C 2 c m','C c 2 a','C 2 c b',
2015        'C m c m','C m c a','C c m b',
2016        'C m m m','C c c m','C m m a','C m m b','C c c a','C c c b',),
2017    'Immm':('I 2 2 2','I 21 21 21',
2018        'I m m 2','I m 2 m','I 2 m m',
2019        'I b a 2','I 2 c b','I c 2 a',
2020        'I m a 2','I 2 m b','I c 2 m','I m 2 a','I b m 2','I 2 c m',
2021        'I m m m','I b a m','I m c b','I c m a',
2022        'I b c a','I c a b',
2023        'I m m a','I b m m ','I m c m','I m a m','I m m b','I c m m',),
2024    'Fmmm':('F 2 2 2','F m m m', 'F d d d',
2025        'F m m 2','F m 2 m','F 2 m m',
2026        'F d d 2','F d 2 d','F 2 d d',),
2027    'P4/mmm':('P 4','P 41','P 42','P 43','P -4','P 4/m','P 42/m','P 4/n','P 42/n',
2028        'P 4 2 2','P 4 21 2','P 41 2 2','P 41 21 2','P 42 2 2',
2029        'P 42 21 2','P 43 2 2','P 43 21 2','P 4 m m','P 4 b m','P 42 c m',
2030        'P 42 n m','P 4 c c','P 4 n c','P 42 m c','P 42 b c','P -4 2 m',
2031        'P -4 2 c','P -4 21 m','P -4 21 c','P -4 m 2','P -4 c 2','P -4 b 2',
2032        'P -4 n 2','P 4/m m m','P 4/m c c','P 4/n b m','P 4/n n c','P 4/m b m',
2033        'P 4/m n c','P 4/n m m','P 4/n c c','P 42/m m c','P 42/m c m',
2034        'P 42/n b c','P 42/n n m','P 42/m b c','P 42/m n m','P 42/n m c',
2035        'P 42/n c m',),
2036    'I4/mmm':('I 4','I 41','I -4','I 4/m','I 41/a','I 4 2 2','I 41 2 2','I 4 m m',
2037        'I 4 c m','I 41 m d','I 41 c d',
2038        'I -4 m 2','I -4 c 2','I -4 2 m','I -4 2 d','I 4/m m m','I 4/m c m',
2039        'I 41/a m d','I 41/a c d'),
2040    'R3-H':('R 3','R -3','R 3 2','R 3 m','R 3 c','R -3 m','R -3 c',),
2041    'P6/mmm': ('P 3','P 31','P 32','P -3','P 3 1 2','P 3 2 1','P 31 1 2',
2042        'P 31 2 1','P 32 1 2','P 32 2 1', 'P 3 m 1','P 3 1 m','P 3 c 1',
2043        'P 3 1 c','P -3 1 m','P -3 1 c','P -3 m 1','P -3 c 1','P 6','P 61',
2044        'P 65','P 62','P 64','P 63','P -6','P 6/m','P 63/m','P 6 2 2',
2045        'P 61 2 2','P 65 2 2','P 62 2 2','P 64 2 2','P 63 2 2','P 6 m m',
2046        'P 6 c c','P 63 c m','P 63 m c','P -6 m 2','P -6 c 2','P -6 2 m',
2047        'P -6 2 c','P 6/m m m','P 6/m c c','P 63/m c m','P 63/m m c',),
2048    'Pm3m': ('P 2 3','P 21 3','P m 3','P n 3','P a 3','P 4 3 2','P 42 3 2',
2049        'P 43 3 2','P 41 3 2','P -4 3 m','P -4 3 n','P m 3 m','P n 3 n',
2050        'P m 3 n','P n 3 m',),
2051    'Im3m':('I 2 3','I 21 3','I m -3','I a -3', 'I 4 3 2','I 41 3 2',
2052        'I -4 3 m', 'I -4 3 d','I m -3 m','I m 3 m','I a -3 d',),
2053    'Fm3m':('F 2 3','F m -3','F d -3','F 4 3 2','F 41 3 2','F -4 3 m',
2054        'F -4 3 c','F m -3 m','F m 3 m','F m -3 c','F d -3 m','F d -3 c',),
2055}
2056
2057ssdict = {}
2058'''A dictionary of superspace group symbols allowed for each entry in spglist
2059(except cubics). Monoclinics are all b-unique setting.
2060'''
2061ssdict = {
2062#1,2
2063    'P 1':['(abg)',],'P -1':['(abg)',],
2064#monoclinic - done
2065#3
2066    'P 2':['(a0g)','(a1/2g)','(0b0)','(0b0)s','(1/2b0)','(0b1/2)',],
2067#4       
2068    'P 21':['(a0g)','(0b0)','(1/2b0)','(0b1/2)',],
2069#5
2070    'C 2':['(a0g)','(0b0)','(0b0)s','(0b1/2)',],
2071#6
2072    'P m':['(a0g)','(a0g)s','(a1/2g)','(0b0)','(1/2b0)','(0b1/2)',],
2073#7
2074    'P a':['(a0g)','(a1/2g)','(0b0)','(0b1/2)',],
2075    'P c':['(a0g)','(a1/2g)','(0b0)','(1/2b0)',],
2076    'P n':['(a0g)','(a1/2g)','(0b0)','(1/2b1/2)',],
2077#8       
2078    'C m':['(a0g)','(a0g)s','(0b0)','(0b1/2)',],
2079#9       
2080    'C c':['(a0g)','(a0g)s','(0b0)',],
2081    'C n':['(a0g)','(a0g)s','(0b0)',],
2082#10       
2083    'P 2/m':['(a0g)','(a0g)0s','(a1/2g)','(0b0)','(0b0)s0','(1/2b0)','(0b1/2)',],
2084#11
2085    'P 21/m':['(a0g)','(a0g)0s','(0b0)','(0b0)s0','(1/2b0)','(0b1/2)',],
2086#12       
2087    'C 2/m':['(a0g)','(a0g)0s','(0b0)','(0b0)s0','(0b1/2)',],
2088#13
2089    'P 2/c':['(a0g)','(a0g)0s','(a1/2g)','(0b0)','(0b0)s0','(1/2b0)',],
2090    'P 2/a':['(a0g)','(a0g)0s','(a1/2g)','(0b0)','(0b0)s0','(0b1/2)',],
2091    'P 2/n':['(a0g)','(a0g)0s','(a1/2g)','(0b0)','(0b0)s0','(1/2b1/2)',],
2092#14
2093    'P 21/c':['(a0g)','(0b0)','(1/2b0)',],
2094    'P 21/a':['(a0g)','(0b0)','(0b1/2)',],
2095    'P 21/n':['(a0g)','(0b0)','(1/2b1/2)',],
2096#15
2097    'C 2/c':['(a0g)','(0b0)','(0b0)s0',],
2098    'C 2/n':['(a0g)','(0b0)','(0b0)s0',],
2099#orthorhombic
2100#16   
2101    'P 2 2 2':['(00g)','(00g)00s','(01/2g)','(1/20g)','(1/21/2g)',
2102        '(a00)','(a00)s00','(a01/2)','(a1/20)','(a1/21/2)',
2103        '(0b0)','(0b0)0s0','(1/2b0)','(0b1/2)','(1/2b1/2)',],
2104#17       
2105    'P 2 2 21':['(00g)','(01/2g)','(1/20g)','(1/21/2g)',
2106        '(a00)','(a00)s00','(a1/20)','(0b0)','(0b0)0s0','(1/2b0)',],
2107    'P 21 2 2':['(a00)','(a01/2)','(a1/20)','(a1/21/2)',
2108        '(0b0)','(0b0)0s0','(1/2b0)','(00g)','(00g)00s','(1/20g)',],
2109    'P 2 21 2':['(0b0)','(0b1/2)','(1/2b0)','(1/2b1/2)',
2110        '(00g)','(00g)00s','(1/20g)','(a00)','(a00)s00','(a1/20)',],
2111#18       
2112    'P 21 21 2':['(00g)','(00g)00s','(a00)','(a01/2)','(0b0)','(0b1/2)',],
2113    'P 2 21 21':['(a00)','(a00)s00','(0b0)','(0b1/2)','(00g)','(01/2g)',],
2114    'P 21 2 21':['(0b0)','(0b0)0s0','(00g)','(01/2g)','(a00)','(a01/2)',],
2115#19       
2116    'P 21 21 21':['(00g)','(a00)','(0b0)',],
2117#20       
2118    'C 2 2 21':['(00g)','(10g)','(01g)','(a00)','(a00)s00','(0b0)','(0b0)0s0',],
2119    'A 21 2 2':['(a00)','(a10)','(a01)','(0b0)','(0b0)0s0','(00g)','(00g)00s',],
2120    'B 2 21 2':['(0b0)','(1b0)','(0b1)','(00g)','(00g)00s','(a00)','(a00)s00',],
2121#21       
2122    'C 2 2 2':['(00g)','(00g)00s','(10g)','(10g)00s','(01g)','(01g)00s',
2123        '(a00)','(a00)s00','(a01/2)','(0b0)','(0b0)0s0','(0b1/2)',],
2124    'A 2 2 2':['(a00)','(a00)s00','(a10)','(a10)s00','(a01)','(a01)s00',
2125        '(0b0)','(0b0)0s0','(0b1/2)','(00g)','(00g)00s','(01/2g)',],
2126    'B 2 2 2':['(0b0)','(0b0)0s0','(1b0)','(1b0)0s0','(0b1)','(0b1)0s0',
2127        '(00g)','(00g)00s','(01/2g)','(a00)','(a00)s00','(a01/2)',],
2128#22       
2129    'F 2 2 2':['(00g)','(00g)00s','(10g)','(01g)',
2130        '(a00)','(a00)s00','(a10)','(a01)',
2131        '(0b0)','(0b0)0s0','(1b0)','(0b1)',],
2132#23       
2133    'I 2 2 2':['(00g)','(00g)00s','(a00)','(a00)s00','(0b0)','(0b0)0s0',],
2134#24       
2135    'I 21 21 21':['(00g)','(00g)00s','(a00','(a00)s00','(0b0)','(0b0)0s0',],
2136#25       
2137    'P m m 2':['(00g)','(00g)s0s','(00g)0ss','(00g)ss0',
2138        '(01/2g)','(01/2g)s0s','(1/20g)','(1/20g)0ss','(1/21/2g)',
2139        '(a00)','(a00)0s0','(a1/20)','(a01/2)','(a01/2)0s0','(a1/21/2)',
2140        '(0b0)','(0b0)s00','(0b1/2)','(0b1/2)s00','(1/2b0)','(1/2b1/2)',],       
2141    'P 2 m m':['(a00)','(a00)ss0','(a00)s0s','(a00)0ss',
2142        '(a01/2)','(a01/2)ss0','(a1/20)','(a1/20)s0s','(a1/21/2)',
2143        '(0b0)','(0b0)00s','(1/2b0)','(0b1/2)','(0b1/2)00s','(1/2b1/2)',
2144        '(00g)','(00g)0s0','(01/2g)','(01/2g)0s0','(1/20g)','(1/21/2g)',],
2145    'P m 2 m':['(0b0)','(0b0)ss0','(0b0)0ss','(0b0)s0s',
2146        '(0b1/2)','(0b1/2)ss0','(1/2b0)','(1/2b0)0ss','(1/2b1/2)',
2147        '(00g)','(00g)s00','(1/20g)','(01/2g)','(01/2g)s00','(1/21/2g)',
2148        '(a00)','(a00)0s0','(a01/2)','(a01/2)0s0','(a1/20)','(a1/21/2)',],       
2149#26       
2150    'P m c 21':['(00g)','(00g)s0s','(01/2g)','(01/2g)s0s','(1/20g)','(1/21/2g)',
2151        '(a00)','(a00)0s0','(a1/20)','(0b0)','(0b0)s00','(0b1/2)',],
2152    'P 21 m a':['(a00)','(a00)ss0','(a01/2)','(a01/2)ss0','(a1/20)','(a1/21/2)',
2153        '(0b0)','(0b0)00s','(1/2b0)','(00g)','(00g)0s0','(01/2g)',],
2154    'P b 21 m':['(0b0)','(0b0)ss0','(0b1/2)','(0b1/2)ss0','(1/2b0)','(1/2b1/2)',
2155        '(00g)','(00g)s00','(1/20g)','(a00)','(a00)0s0','(a01/2)',],
2156    'P m 21 b':['(a00)','(a00)ss0','(a01/2)','(a01/2)ss0','(a1/20)','(a1/21/2)',
2157        '(00g)','(00g)0s0','(01/2g)','(0b0)','(0b0)s00','(0b1/2)',],
2158    'P c m 21':['(00g)','(00g)0ss','(1/20g)','(1/20g)0ss','(01/2g)','(1/21/2g)',
2159        '(0b0)','(0a0)s00','(1/2b0)','(a00)','(a00)0s0','(a01/2)',],
2160    'P 21 a m':['(0b0)','(0b0)ss0','(0b1/2)','(0b1/2)ss0','(1/2b0)','(1/2b1/2)',
2161        '(a00)','(a00)00s','(a1/20)','(00g)','(00g)s00','(1/20g)',],
2162#27       
2163    'P c c 2':['(00g)','(00g)s0s','(00g)0ss','(01/2g)','(1/20g)','(1/21/2g)',
2164        '(a00)','(a00)0s0','(a1/20)','(0b0)','(0b0)s00','(1/2b0)',],
2165    'P 2 a a':['(a00)','(a00)ss0','(a00)s0s','(a01/2)','(a1/20)','(a1/21/2)',
2166        '(0b0)','(0b0)00s','(0b1/2)','(00g)','(00g)0s0','(01/2g)',],
2167    'P b 2 b':['(0b0)','(0b0)0ss','(0b0)ss0','(1/2b0)','(0b1/2)','(1/2b1/2)',
2168        '(00g)','(00g)s00','(1/20g)','(a00)','(a00)00s','(a01/2)',],
2169#28       
2170    'P m a 2':['(00g)','(00g)s0s','(00g)ss0','(00g)0ss','(01/2g)','(01/2g)s0s',
2171        '(a00)','(a01/2)','(a1/20)','(a1/21/2)','(0b0)','(0b0)s00',],
2172    'P 2 m b':[],
2173    'P c 2 m':[],
2174    'P m 2 a':[],
2175    'P b m 2':[],
2176    'P 2 c m':[],
2177#29       
2178    'P c a 21':['(00g)','(00g)0ss','(01/2g)','(1/20g)',
2179        '(a00)','(a00)0s0','(a1/20)','(0b0)','(0b0)s00','(1/2b0)',],
2180    'P 21 a b':[],
2181    'P c 21 b':[],
2182    'P b 21 a':[],
2183    'P b c 21':[],
2184    'P 21 c a':[],
2185#30       
2186    'P c n 2':[],
2187    'P 2 a n':[],
2188    'P n 2 b':[],
2189    'P b 2 n':[],
2190    'P n c 2':[],
2191    'P 2 n a':[],
2192#31       
2193    'P m n 21':[],
2194    'P 21 m n':[],
2195    'P n 21 m':[],
2196    'P m 21 n':[],
2197    'P n m 21':[],
2198    'P 21 n m':[],
2199#32       
2200    'P b a 2':['(00g)','(00g)s0s','(00g)0ss','(00g)ss0','(1/21/2g)qq0',
2201        '(a00)','(a01/2)','(0b0)','(0b1/2)',],
2202    'P 2 c b':['(a00)','(a00)ss0','(a00)s0s','(a00)0ss','(a1/21/2)0qq',
2203        '(0b0)','(1/2b0)','(00g)','(1/20g)',],
2204    'P c 2 a':['(0b0)','(0b0)ss0','(0b0)0ss','(0b0)s0s','(1/2b1/2)q0q',
2205        '(00g)','01/2g)','(a00)','(a1/20)',],
2206#33       
2207    'P n a 21':[],
2208    'P 21 n b':[],
2209    'P c 21 n':[],
2210    'P n 21 a':[],
2211    'P b n 21':[],
2212    'P 21 c n':[],
2213#34       
2214    'P n n 2':['(00g)','(00g)s0s','(00g)0ss','(1/21/2g)qq0',
2215        '(a00)','(a1/21/2)0q0','(a1/21/2)00q','(0b0)','(1/2b1/2)q00','(1/2b1/2)00q',],
2216    'P 2 n n':['(a00)','(a00)ss0','(a00)s0s','(a1/21/2)0qq',
2217        '(0b0)','(1/2b1/2)q00','(1/2b1/2)00q','(00g)','(1/21/2b)0q0','(1/21/2g)q00',],
2218    'P n 2 n':['(0b0)','(0b0)ss0','(0b0)0ss','(1/2b1/2)q0q',
2219        '(00g)','(1/21/2g)0q0','(1/21/2g)q00','(a00)','(a1/21/2)00q','(b1/21/2)0q0',],
2220#35       
2221    'C m m 2':['(00g)','(00g)s0s','(00g)0ss','(00g)ss0','(10g)','(10g)s0s','(10g)0ss','(10g)ss0',
2222        '(01g)','(01g)s0s','(01g)0ss','(01g)ss0','(a00)','(a00)0s0','(a01/2)','(a01/2)0s0',
2223        '(0b0)','(0b0)s00','(0b1/2)','(0b1/2)s00',],
2224    'A 2 m m':['(a00)','(a00)s0s','(a00)0ss','(a00)ss0','(a10)','(a10)s0s','(a10)0ss','(a10)ss0',
2225        '(a01)','(a01)s0s','(a01)0ss','(a01)ss0','(0b0)','(0b0)00s','(1/2b0)','(1/2b0)00s',
2226        '(00g)','(00g)0s0','(01/2g)','(01/2g)0s0',],
2227    'B m 2 m':['(0b0)','(0b0)s0s','(0b0)0ss','(0b0)ss0','(1b0)','(1b0)s0s','(1b0)0ss','(1b0)ss0',
2228        '(0b1)','(0b1)s0s','(0b1)0ss','(0b1)ss0','(a00)','(a00)00s','(a01/2)','(a01/2)00s',
2229        '(00g)','(00g)s00','(1/20g)','(1/20g)s00',],
2230#36
2231    'C m c 21':['(00g)','(00g)s0s','(10g)','(10g)s0s','(a00)','(a00)0s0','(0b0)','(0b0)s00',],
2232    'A 21 m a':['(a00)','(a00)ss0','(a10)','(a10)ss0','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2233    'B m 21 b':['(0b0)','(0b0)ss0','(1b0)','(1b0)ss0','(a00)','(a00)00s','(00g)','(00g)s00',],
2234    'B b 21 m':['(0b0)','(0b0)0ss','(0b1)','(0b1)ss0','(a00)','(a00)00s','(00g)','(00g)s00',],
2235    'C c m 21':['(00g)','(00g)0ss','(01g)','(01g)0ss','(a00)','(a00)0s0','(0b0)','(0b0)s00',],
2236    'A 21 a m':['(a00)','(a00)s0s','(a01)','(a01)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2237#37
2238    'C c c 2':['(00g)','(00g)s0s','(00g)0ss','(10g)','(10g)s0s','(10g)0ss','(01g)','(01g)s0s','(01g)0ss',
2239        '(a00)','(a00)0s0','(0b0)','(0b0)s00',],
2240    'A 2 a a':['(a00)','(a00)ss0','(a00)s0s','(a10)','(a10)ss0','(a10)ss0','(a01)','(a01)ss0','(a01)ss0',
2241        '(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2242    'B b 2 b':['(0b0)','(0b0)0ss','(0b0)ss0','(0b1)','(0b1)0ss','(0b1)ss0','(1b0)','(1b0)0ss','(1b0)ss0',
2243        '(a00)','(a00)00s','(00g)','(00g)s00',],
2244#38
2245    'A m m 2':[],
2246    'B 2 m m':[],
2247    'C m 2 m':[],
2248    'A m 2 m':[],
2249    'B m m 2':[],
2250    'C 2 m m':[],
2251#39
2252    'A b m 2':[],
2253    'B 2 c m':[],
2254    'C m 2 a':[],
2255    'A c 2 m':[],
2256    'B m a 2':[],
2257    'C 2 m b':[],
2258#40       
2259    'A m a 2':[],
2260    'B 2 m b':[],
2261    'C c 2 m':[],
2262    'A m 2 a':[],
2263    'B b m 2':[],
2264    'C 2 c m':[],
2265#41
2266    'A b a 2':[],
2267    'B 2 c b':[],
2268    'C c 2 a':[],
2269    'A c 2 a':[],
2270    'B b a 2':[],
2271    'C 2 c b':[],
2272       
2273#42       
2274    'F m m 2':['(00g)','(00g)s0s','(00g)0ss','(00g)ss0','(10g)','(10g)ss0','(10g)s0s',
2275        '(01g)','(01g)ss0','(01g)0ss','(a00)','(a00)0s0','(a01)','(a01)0s0',
2276        '(0b0)','(0b0)s00','(0b1)','(0b1)s00',],       
2277    'F 2 m m':['(a00)','(a00)ss0','(a00)s0s','(a00)0ss','(a10)','(a10)0ss','(a10)ss0',
2278        '(a01)','(a01)0ss','(a01)s0s','(0b0)','(0b0)00s','(1b0)','(1b0)00s',
2279        '(00g)','(00g)0s0','(10g)','(10g)0s0',],
2280    'F m 2 m':['(0b0)','(0b0)0ss','(0b0)ss0','(0b0)s0s','(0b1)','(0b1)s0s','(0b1)0ss',
2281        '(1b0)','(1b0)s0s','(1b0)ss0','(00g)','(00g)s00','(01g)','(01g)s00',
2282        '(a00)','(a00)00s','(a10)','(a10)00s',],       
2283#43       
2284    'F d d 2':['(00g)','(00g)0ss','(00g)s0s','(a00)','(0b0)',],
2285    'F 2 d d':['(a00)','(a00)s0s','(a00)ss0','(00g)','(0b0)',],       
2286    'F d 2 d':['(0b0)','(0b0)0ss','(0b0)ss0','(a00)','(00g)',],
2287#44
2288    'I m m 2':['(00g)','(00g)ss0','(00g)s0s','(00g)0ss','(a00)','(a00)0s0','(0b0)','(0b0)s00',],
2289    'I 2 m m':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2290    'I m 2 m':['(0b0)','(0b0)s0s','(0b0)0ss','(0b0)ss0','(00g)','(00g)s00','(a00)','(a00)00s',],
2291#45       
2292    'I b a 2':['(00g)','(00g)ss0','(00g)s0s','(00g)0ss','(a00)','(a00)0s0','(0b0)','(0b0)s00',],
2293    'I 2 c b':['(0b0)','(0b0)s0s','(0b0)0ss','(0b0)ss0','(00g)','(00g)s00','(a00)','(a00)00s',],
2294    'I c 2 a':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2295#46       
2296    'I m a 2':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2297    'I 2 m b':['(0b0)','(0b0)s0s','(0b0)0ss','(0b0)ss0','(00g)','(00g)s00','(a00)','(a00)00s',],       
2298    'I c 2 m':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2299    'I m 2 a':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2300    'I b m 2':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2301    'I 2 c m':['(0b0)','(0b0)s0s','(0b0)0ss','(0b0)ss0','(00g)','(00g)s00','(a00)','(a00)00s',],
2302#47       
2303    'P m m m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(01/2g)','(01/2g)s00','(1/20g)','(1/20g)s00','(1/21/2g)',
2304        '(a00)','(a00)0s0','(a00)00s','(a00)0ss','(a01/2)','(a01/2)0s0','(a1/20)','(a1/20)00s','(a1/21/2)',
2305        '(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s','(1/2b0)','(1/2b0)00s','(0b1/2)','(0b1/2)s00','(1/2b1/2)',],
2306#48 o@i qq0,0qq,q0q ->000
2307    'P n n n':['(00g)','(00g)s00','(00g)0s0','(1/21/2g)',
2308        '(a00)','(a00)0s0','(a00)00s','(a1/21/2)',
2309        '(0b0)','(0b0)s00','(0b0)00s','(1/2b1/2)',],
2310#49       
2311    'P c c m':['(00g)','(00g)s00','(00g)0s0','(01/2g)','(1/20g)','(1/21/2g)',
2312        '(a00)','(a00)0s0','(a00)00s','(a00)0ss','(a1/20)','(a1/20)00s',
2313        '(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s','(1/2b0)','(1/2b0)00s',],       
2314    'P m a a':['(a00)','(a00)0s0','(a00)00s','(a01/2)','(a1/20)','(a1/21/2)',
2315        '(0b0)','(0b0)00s','(0b0)s00','(0b0)s0s','(0b1/2)','(0b1/2)s00',
2316        '(00g)','(00g)0s0','(00g)s00','(00g)ss0','(01/2g)','(01/2g)s00',],       
2317    'P b m b':['(0b0)','(0b0)00s','(0b0)s00','(0b1/2)','(1/2b0)','(1/2b1/2)',
2318        '(00g)','(00g)s00','(00g)0s0','(00g)ss0','(1/20g)','(1/20g)0s0',
2319        '(a00)','(a00)00s','(a00)0s0','(a00)0ss','(a01/2)','(a01/2)0s0',],
2320#50 o@i qq0,0qq,q0q ->000
2321    'P b a n':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(1/21/2g)',
2322        '(a00)','(a00)0s0','(a01/2)','(0b0)','(0b0)s00','(0b1/2)',],
2323    'P n c b':['(a00)','(a00)0s0','(a00)00s','(a00)0ss','(a1/21/2)',
2324        '(0b0)','(0b0)00s','(1/2b0)','(00g)','(00g)0s0','(1/20g)',],
2325    'P c n a':['(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s','(1/2b1/2)',
2326        '(00g)','(00g)s00','(01/2a)','(a00)','(a00)00s','(a1/20)',],
2327#51       
2328    'P m m a':[],
2329    'P b m m':[],
2330    'P m c m':[],
2331    'P m a m':[],
2332    'P m m b':[],
2333    'P c m m':[],
2334#52   o@i qq0,0qq,q0q ->000     
2335    'P n n a':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)00s',
2336        '(0b0)','(0b0)00s','(a1/21/2)','(1/2b1/2)',],
2337    'P b n n':['(a00)','(a00)0s0','(a00)00s','(0b0)','(0b0)s00',
2338        '(00g)','(00g)s00','(1/2b1/2)','(1/21/2g)',],
2339    'P n c n':['(0b0)','(0b0)s00','(0b0)00s','(00g)','(00g)0s0',
2340        '(a00)','(a00)0s0','(1/21/2g)','(a1/21/2)',],
2341    'P n a n':['(0b0)','(0b0)s00','(0b0)00s','(00g)','(00g)0s0',
2342        '(a00)','(a00)0s0','(1/21/2g)','(a1/21/2)',],
2343    'P n n b':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)00s',
2344        '(0b0)','(0b0)00s','(a1/21/2)','(1/2b1/2)',],
2345    'P c n n':['(a00)','(a00)0s0','(a00)00s','(0b0)','(0b0)s00',
2346        '(00g)','(00g)s00','(1/2b1/2)','(1/21/2g)',],
2347#53       
2348    'P m n a':[],
2349    'P b m n':[],
2350    'P n c m':[],
2351    'P m a n':[],
2352    'P n m b':[],
2353    'P c n m':[],
2354#54       
2355    'P c c a':[],
2356    'P b a a':[],
2357    'P b c b':[],
2358    'P b a b':[],
2359    'P c c b':[],
2360    'P c a a':[],
2361#55       
2362    'P b a m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0',
2363        '(a00)','(a00)00s','(a01/2)','(0b0)','(0b0)00s','(0b1/2)'],
2364    'P m c b':['(a00)','(a00)0s0','(a00)00s','(a00)0ss',
2365        '(0b0)','(0b0)s00','(1/2b0)','(00g)','(00g)s00','(1/20g)'],
2366    'P c m a':['(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s',
2367        '(a00)','(a00)0s0','(a1/20)','(00g)','(00g)0s0','(01/2g)'],
2368#56       
2369    'P c c n':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2370        '(0b0)','(0b0)s00'],
2371    'P n a a':['(a00)','(a00)0s0','(a00)00s','(0b0)','(0b0)00s',
2372        '(00g)','(00g)0s0'],
2373    'P b n b':['(0b0)','(0b0)s00','(0b0)00s','(a00)','(a00)00s',
2374        '(00g)','(00g)s00'],
2375#57       
2376    'P b c m':[],
2377    'P m c a':[],
2378    'P b m a':[],
2379    'P c m b':[],
2380    'P c a m':[],
2381    'P m a b':[],
2382#58       
2383    'P n n m':['(00g)','(00g)s00','(00g)0s0','(a00)',
2384        '(a00)00s','(0b0)','(0b0)00s'],
2385    'P m n n':['(00g)','(00g)s00','(a00)','(a00)0s0',
2386        '(a00)00s','(0b0)','(0b0)s00'],
2387    'P n m n':['(00g)','(00g)0s0','(a00)','(a00)0s0',
2388        '(0b0)','(0b0)s00','(0b0)00s',],
2389#59 o@i
2390    'P m m n':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2391        '(a01/2)','(a01/2)0s0','(0b0)','(0b0)s00','(0b1/2)','(0b1/2)s00',],
2392    'P n m m':['(a00)','(a00)0s0','(a00)00s','(a00)0ss','(00g)','(00g)0s0',
2393        '(1/20g)','(1/20g)0s0','(0b0)','(0b0)00s','(1/2b0)','(1/2b0)00s'],
2394    'P m n m':['(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s','(00g)','(00g)s00',
2395        '(01/2g)','(01/2g)s00','(a00)','(a00)00s','(a1/20)','(a1/20)00s'],
2396#60       
2397    'P b c n':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2398        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
2399    'P n c a':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2400        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
2401    'P b n a':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2402        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
2403    'P c n b':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2404        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
2405    'P c a n':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2406        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
2407    'P n a b':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2408        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
2409#61       
2410    'P b c a':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0','(a00)00s',
2411        '(0b0)','(0b0)s00','(0b0)00s'],
2412    'P c a b':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0','(a00)00s',
2413        '(0b0)','(0b0)s00','(0b0)00s'],
2414#62       
2415    'P n m a':['(00g)','(00g)0s0','(a00)','(a00)0s0','(0b0)','(0b0)00s'],
2416    'P b n m':['(00g)','(00g)s00','(a00)','(a00)00s','(0b0)','(0b0)00s'],
2417    'P m c n':['(00g)','(00g)s00','(a00)','(a00)0s0','(0b0)','(0b0)s00'],
2418    'P n a m':['(00g)','(00g)0s0','(a00)','(a00)00s','(0b0)','(0b0)00s'],
2419    'P m n b':['(00g)','(00g)s00','(a00)','(a00)00s','(0b0)','(0b0)s00'],
2420    'P c m n':['(00g)','(00g)0s0','(a00)','(a00)0s0','(0b0)','(0b0)s00'],
2421#63
2422    'C m c m':[],
2423    'A m m a':[],
2424    'B b m m':[],
2425    'B m m b':[],
2426    'C c m m':[],
2427    'A m a m':[],
2428#64       
2429    'C m c a':['(00g)','(00g)s00','(10g)','(10g)s00','(a00)',],
2430    'A b m a':[],
2431    'B b c m':[],
2432    'B m a b':[],
2433    'C c m b':[],
2434    'A c a m':[],
2435#65       
2436    'C m m m':[],
2437    'A m m m':[],
2438    'B m m m':[],
2439#66       
2440    'C c c m':[],
2441    'A m m a':[],
2442    'B b m b':[],
2443#67       
2444    'C m m a':[],
2445    'A b m m':[],
2446    'B m c m':[],
2447    'B m a m':[],
2448    'C m m b':[],
2449    'A c m m':[],
2450#68 o@i
2451    'C c c a':[],
2452    'A b a a':[],
2453    'B b c b':[],
2454    'B b a b':[],
2455    'C c c b':[],
2456    'A c a a':[],
2457#69       
2458    'F m m m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2459        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s',
2460        '(10g)','(10g)s00','(10g)0s0','(10g)ss0','(a10)','(a10)0s0',
2461        '(a10)00s','(a10)0ss','(0b1)','(0b1)s00','(0b1)00s','(0b1)s0s',
2462        '(01g)','(01g)s00','(01g)0s0','(01g)ss0','(a01)','(a01)0s0',
2463        '(a01)00s','(a01)0ss','(1b0)','(1b0)s00','(1b0)00s','(1b0)s0s'],
2464#70 o@i       
2465    'F d d d':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2466        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s',],
2467       
2468#71
2469    'I m m m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2470        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s',],
2471#72       
2472    'I b a m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2473        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2474    'I m c b':['(a00)','(a00)0s0','(a00)00s','(a00)0ss','(0b0)','(0b0)00s',
2475        '(0b0)s00','(0b0)s0s','(00g)','(00g)0s0','(00g)s00','(00g)ss0'],
2476    'I c m a':['(0b0)','(0b0)00s','(0b0)s00','(0b0)s0s','(00g)','(00g)s00',
2477        '(00g)0s0','(00g)ss0','(a00)','(a00)00s','(a00)0s0','(a00)0ss'],
2478#73       
2479    'I b c a':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2480        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2481    'I c a b':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2482        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2483#74       
2484    'I m m a':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2485        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2486    'I b m m ':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2487        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2488    'I m c m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2489        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2490    'I m a m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2491        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2492    'I m m b':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2493        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2494    'I c m m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2495        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2496#tetragonal - done
2497#75
2498    'P 4':['(00g)','(00g)q','(00g)s','(1/21/2g)','(1/21/2g)q',],
2499#76
2500    'P 41':['(00g)','(1/21/2g)',],
2501#77
2502    'P 42':['(00g)','(00g)q','(1/21/2g)','(1/21/2g)q',],
2503#78
2504    'P 43':['(00g)','(1/21/2g)',],
2505#79
2506    'I 4':['(00g)','(00g)q','(00g)s',],
2507#80
2508    'I 41':['(00g)','(00g)q',],
2509#81
2510    'P -4':['(00g)','(1/21/2g)',],
2511#82
2512    'I -4':['(00g)',],
2513#83
2514    'P 4/m':['(00g)','(00g)s0','(1/21/2g)',],
2515#84
2516    'P 42/m':['(00g)','(1/21/2g)',],
2517#85 o@i q0 -> 00
2518    'P 4/n':['(00g)','(00g)s0','(1/21/2g)',], #q0?
2519#86 o@i q0 -> 00
2520    'P 42/n':['(00g)','(1/21/2g)',],      #q0?
2521#87
2522    'I 4/m':['(00g)','(00g)s0',],
2523#88
2524    'I 41/a':['(00g)',],
2525#89
2526    'P 4 2 2':['(00g)','(00g)q00','(00g)s00','(1/21/2g)','(1/21/2g)q00',],
2527#90
2528    'P 4 21 2':['(00g)','(00g)q00','(00g)s00',],
2529#91
2530    'P 41 2 2':['(00g)','(1/21/2g)',],
2531#92
2532    'P 41 21 2':['(00g)',],
2533#93
2534    'P 42 2 2':['(00g)','(00g)q00','(1/21/2g)','(1/21/2g)q00',],
2535#94
2536    'P 42 21 2':['(00g)','(00g)q00',],
2537#95
2538    'P 43 2 2':['(00g)','(1/21/2g)',],
2539#96
2540    'P 43 21 2':['(00g)',],
2541#97
2542    'I 4 2 2':['(00g)','(00g)q00','(00g)s00',],
2543#98
2544    'I 41 2 2':['(00g)','(00g)q00',],
2545#99
2546    'P 4 m m':['(00g)','(00g)ss0','(00g)0ss','(00g)s0s','(1/21/2g)','(1/21/2g)0ss'],
2547#100
2548    'P 4 b m':['(00g)','(00g)ss0','(00g)0ss','(00g)s0s','(1/21/2g)qq0','(1/21/2g)qqs',],
2549#101
2550    'P 42 c m':['(00g)','(00g)0ss','(1/21/2g)','(1/21/2g)0ss',],
2551#102
2552    'P 42 n m':['(00g)','(00g)0ss','(1/21/2g)qq0','(1/21/2g)qqs',],
2553#103
2554    'P 4 c c':['(00g)','(00g)ss0','(1/21/2g)',],
2555#104
2556    'P 4 n c':['(00g)','(00g)ss0','(1/21/2g)qq0',],
2557#105
2558    'P 42 m c':['(00g)','(00g)ss0','(1/21/2g)',],
2559#106
2560    'P 42 b c':['(00g)','(00g)ss0','(1/21/2g)qq0',],
2561#107
2562    'I 4 m m':['(00g)','(00g)ss0','(00g)0ss','(00g)s0s',],
2563#108
2564    'I 4 c m':['(00g)','(00g)ss0','(00g)0ss','(00g)s0s',],
2565#109
2566    'I 41 m d':['(00g)','(00g)ss0',],
2567#110
2568    'I 41 c d':['(00g)','(00g)ss0',],
2569#111
2570    'P -4 2 m':['(00g)','(00g)0ss','(1/21/2g)','(1/21/2g)0ss',],
2571#112
2572    'P -4 2 c':['(00g)','(1/21/2g)',],
2573#113
2574    'P -4 21 m':['(00g)','(00g)0ss',],
2575#114
2576    'P -4 21 c':['(00g)',],
2577#115    00s -> 0ss
2578    'P -4 m 2':['(00g)','(00g)0ss','(1/21/2g)',],
2579#116
2580    'P -4 c 2':['(00g)','(1/21/2g)',],
2581#117    00s -> 0ss
2582    'P -4 b 2':['(00g)','(00g)0s0','(1/21/2g)0q0',],
2583#118
2584    'P -4 n 2':['(00g)','(1/21/2g)0q0',],
2585#119
2586    'I -4 m 2':['(00g)','(00g)0s0',],
2587#120
2588    'I -4 c 2':['(00g)','(00g)0s0',],
2589#121    00s -> 0ss
2590    'I -4 2 m':['(00g)','(00g)0ss',],
2591#122
2592    'I -4 2 d':['(00g)',],
2593#123
2594    'P 4/m m m':['(00g)','(00g)s0s0','(00g)00ss','(00g)s00s',
2595        '(1/21/2g)','(1/21/2g)s0s0','(1/21/2g)00ss','(1/21/2g)s00s',],
2596#124
2597    'P 4/m c c':['(00g)','(00g)s0s0','(1/21/2g)',],
2598#125    o@i q0q0 -> 0000, q0qs -> 00ss
2599    'P 4/n b m':['(00g)','(00g)s0s0','(00g)00ss','(00g)s00s','(1/21/2g)','(1/21/2g)00ss',],
2600#126    o@i q0q0 -> 0000
2601    'P 4/n n c':['(00g)','(00g)s0s0','(1/21/2g)',],
2602#127
2603    'P 4/m b m':['(00g)','(00g)s0s0','(00g)00ss','(00g)s00s',],
2604#128
2605    'P 4/m n c':['(00g)','(00g)s0s0',],
2606#129
2607    'P 4/n m m':['(00g)','(00g)s0s0','(00g)00ss','(00g)s00s',],
2608#130
2609    'P 4/n c c':['(00g)','(00g)s0s0',],
2610#131
2611    'P 42/m m c':['(00g)','(00g)s0s0','(1/21/2g)',],
2612#132
2613    'P 42/m c m':['(00g)','(00g)00ss','(1/21/2g)','(1/21/2g)00ss',],
2614#133    o@i q0q0 -> 0000
2615    'P 42/n b c':['(00g)','(00g)s0s0','(1/21/2g)',],
2616#134    o@i q0q0 -> 0000, q0qs -> 00ss
2617    'P 42/n n m':['(00g)','(00g)00ss','(1/21/2g)','(1/21/2g)00ss',],
2618#135
2619    'P 42/m b c':['(00g)','(00g)s0s0',],
2620#136
2621    'P 42/m n m':['(00g)','(00g)00ss',],
2622#137
2623    'P 42/n m c':['(00g)','(00g)s0s0',],
2624#138
2625    'P 42/n c m':['(00g)','(00g)00ss',],
2626#139
2627    'I 4/m m m':['(00g)','(00g)s0s0','(00g)00ss','(00g)s00s',],
2628#140
2629    'I 4/m c m':['(00g)','(00g)s0s0','(00g)00ss','(00g)s00s',],
2630#141
2631    'I 41/a m d':['(00g)','(00g)s0s0',],
2632#142
2633    'I 41/a c d':['(00g)','(00g)s0s0',],
2634    #trigonal/rhombahedral - done & checked
2635#143
2636    'P 3':['(00g)','(00g)t','(1/31/3g)',],
2637#144
2638    'P 31':['(00g)','(1/31/3g)',],
2639#145
2640    'P 32':['(00g)','(1/31/3g)',],
2641#146
2642    'R 3':['(00g)','(00g)t',],
2643#147
2644    'P -3':['(00g)','(1/31/3g)',],
2645#148
2646    'R -3':['(00g)',],
2647#149
2648    'P 3 1 2':['(00g)','(00g)t00','(1/31/3g)',],
2649#150
2650    'P 3 2 1':['(00g)','(00g)t00',],
2651#151
2652    'P 31 1 2':['(00g)','(1/31/3g)',],
2653#152
2654    'P 31 2 1':['(00g)',],
2655#153
2656    'P 32 1 2':['(00g)','(1/31/3g)',],
2657#154
2658    'P 32 2 1':['(00g)',],
2659#155
2660    'R 3 2':['(00g)','(00g)t0',],
2661#156
2662    'P 3 m 1':['(00g)','(00g)0s0',],
2663#157
2664    'P 3 1 m':['(00g)','(00g)00s','(1/31/3g)','(1/31/3g)00s',],
2665#158
2666    'P 3 c 1':['(00g)',],
2667#159
2668    'P 3 1 c':['(00g)','(1/31/3g)',],
2669#160
2670    'R 3 m':['(00g)','(00g)0s',],
2671#161
2672    'R 3 c':['(00g)',],
2673#162
2674    'P -3 1 m':['(00g)','(00g)00s','(1/31/3g)','(1/31/3g)00s',],
2675#163
2676    'P -3 1 c':['(00g)','(1/31/3g)',],
2677#164
2678    'P -3 m 1':['(00g)','(00g)0s0',],
2679#165
2680    'P -3 c 1':['(00g)',],
2681#166       
2682    'R -3 m':['(00g)','(00g)0s',],
2683#167
2684    'R -3 c':['(00g)',],
2685    #hexagonal - done & checked
2686#168
2687    'P 6':['(00g)','(00g)h','(00g)t','(00g)s',],
2688#169
2689    'P 61':['(00g)',],
2690#170
2691    'P 65':['(00g)',],
2692#171
2693    'P 62':['(00g)','(00g)h',],
2694#172
2695    'P 64':['(00g)','(00g)h',],
2696#173
2697    'P 63':['(00g)','(00g)h',],
2698#174
2699    'P -6':['(00g)',],
2700#175
2701    'P 6/m':['(00g)','(00g)s0',],
2702#176
2703    'P 63/m':['(00g)',],
2704#177
2705    'P 6 2 2':['(00g)','(00g)h00','(00g)t00','(00g)s00',],
2706#178
2707    'P 61 2 2':['(00g)',],
2708#179
2709    'P 65 2 2':['(00g)',],
2710#180
2711    'P 62 2 2':['(00g)','(00g)h00',],
2712#181
2713    'P 64 2 2':['(00g)','(00g)h00',],
2714#182
2715    'P 63 2 2':['(00g)','(00g)h00',],
2716#183
2717    'P 6 m m':['(00g)','(00g)ss0','(00g)0ss','(00g)s0s',],
2718#184
2719    'P 6 c c':['(00g)','(00g)s0s',],
2720#185
2721    'P 63 c m':['(00g)','(00g)0ss',],
2722#186
2723    'P 63 m c':['(00g)','(00g)0ss',],
2724#187
2725    'P -6 m 2':['(00g)','(00g)0s0',],
2726#188
2727    'P -6 c 2':['(00g)',],
2728#189
2729    'P -6 2 m':['(00g)','(00g)00s',],
2730#190
2731    'P -6 2 c':['(00g)',],
2732#191
2733    'P 6/m m m':['(00g)','(00g)s0s0','(00g)00ss','(00g)s00s',],
2734#192
2735    'P 6/m c c':['(00g)','(00g)s00s',],
2736#193
2737    'P 63/m c m':['(00g)','(00g)00ss',],
2738#194
2739    'P 63/m m c':['(00g)','(00g)00ss'],
2740    }
2741
2742#'A few non-standard space groups for test use'
2743nonstandard_sglist = ('P 21 1 1','P 1 21 1','P 1 1 21','R 3 r','R 3 2 h', 
2744                      'R -3 r', 'R 3 2 r','R 3 m h', 'R 3 m r',
2745                      'R 3 c r','R -3 c r','R -3 m r',),
2746
2747#A list of orthorhombic space groups that were renamed in the 2002 Volume A,
2748# along with the pre-2002 name. The e designates a double glide-plane'''
2749sgequiv_2002_orthorhombic= (('A e m 2', 'A b m 2',),
2750                            ('A e a 2', 'A b a 2',),
2751                            ('C m c e', 'C m c a',),
2752                            ('C m m e', 'C m m a',),
2753                            ('C c c e', 'C c c a'),)
2754#Use the space groups types in this order to list the symbols in the
2755#order they are listed in the International Tables, vol. A'''
2756symtypelist = ('triclinic', 'monoclinic', 'orthorhombic', 'tetragonal', 
2757               'trigonal', 'hexagonal', 'cubic')
2758
2759# self-test materials follow. Requires files in directory testinp
2760selftestlist = []
2761'''Defines a list of self-tests'''
2762selftestquiet = True
2763def _ReportTest():
2764    'Report name and doc string of current routine when ``selftestquiet`` is False'
2765    if not selftestquiet:
2766        import inspect
2767        caller = inspect.stack()[1][3]
2768        doc = eval(caller).__doc__
2769        if doc is not None:
2770            print('testing '+__file__+' with '+caller+' ('+doc+')')
2771        else:
2772            print('testing '+__file__()+" with "+caller)
2773def test0():
2774    '''self-test #0: exercise MoveToUnitCell'''
2775    _ReportTest()
2776    msg = "MoveToUnitCell failed"
2777    assert (MoveToUnitCell([1,2,3]) == [0,0,0]).all, msg
2778    assert (MoveToUnitCell([2,-1,-2]) == [0,0,0]).all, msg
2779    assert abs(MoveToUnitCell(np.array([-.1]))[0]-0.9) < 1e-6, msg
2780    assert abs(MoveToUnitCell(np.array([.1]))[0]-0.1) < 1e-6, msg
2781selftestlist.append(test0)
2782
2783def test1():
2784    '''self-test #1: SpcGroup against previous results'''
2785    #'''self-test #1: SpcGroup and SGPrint against previous results'''
2786    _ReportTest()
2787    testdir = ospath.join(ospath.split(ospath.abspath( __file__ ))[0],'testinp')
2788    if ospath.exists(testdir):
2789        if testdir not in sys.path: sys.path.insert(0,testdir)
2790    import spctestinp
2791    def CompareSpcGroup(spc, referr, refdict, reflist): 
2792        'Compare output from GSASIIspc.SpcGroup with results from a previous run'
2793        # if an error is reported, the dictionary can be ignored
2794        msg0 = "CompareSpcGroup failed on space group %s" % spc
2795        result = SpcGroup(spc)
2796        if result[0] == referr and referr > 0: return True
2797        keys = result[1].keys()
2798        #print result[1]['SpGrp']
2799        #msg = msg0 + " in list lengths"
2800        #assert len(keys) == len(refdict.keys()), msg
2801        for key in refdict.keys():
2802            if key == 'SGOps' or  key == 'SGCen':
2803                msg = msg0 + (" in key %s length" % key)
2804                assert len(refdict[key]) == len(result[1][key]), msg
2805                for i in range(len(refdict[key])):
2806                    msg = msg0 + (" in key %s level 0" % key)
2807                    assert np.allclose(result[1][key][i][0],refdict[key][i][0]), msg
2808                    msg = msg0 + (" in key %s level 1" % key)
2809                    assert np.allclose(result[1][key][i][1],refdict[key][i][1]), msg
2810            else:
2811                msg = msg0 + (" in key %s" % key)
2812                assert result[1][key] == refdict[key], msg
2813        msg = msg0 + (" in key %s reflist" % key)
2814        #for (l1,l2) in zip(reflist, SGPrint(result[1])):
2815        #    assert l2.replace('\t','').replace(' ','') == l1.replace(' ',''), 'SGPrint ' +msg
2816        # for now disable SGPrint testing, output has changed
2817        #assert reflist == SGPrint(result[1]), 'SGPrint ' +msg
2818    for spc in spctestinp.SGdat:
2819        CompareSpcGroup(spc, 0, spctestinp.SGdat[spc], spctestinp.SGlist[spc] )
2820selftestlist.append(test1)
2821
2822def test2():
2823    '''self-test #2: SpcGroup against cctbx (sgtbx) computations'''
2824    _ReportTest()
2825    testdir = ospath.join(ospath.split(ospath.abspath( __file__ ))[0],'testinp')
2826    if ospath.exists(testdir):
2827        if testdir not in sys.path: sys.path.insert(0,testdir)
2828    import sgtbxtestinp
2829    def CompareWcctbx(spcname, cctbx_in, debug=0):
2830        'Compare output from GSASIIspc.SpcGroup with results from cctbx.sgtbx'
2831        cctbx = cctbx_in[:] # make copy so we don't delete from the original
2832        spc = (SpcGroup(spcname))[1]
2833        if debug: print spc['SpGrp']
2834        if debug: print spc['SGCen']
2835        latticetype = spcname.strip().upper()[0]
2836        # lattice type of R implies Hexagonal centering", fix the rhombohedral settings
2837        if latticetype == "R" and len(spc['SGCen']) == 1: latticetype = 'P'
2838        assert latticetype == spc['SGLatt'], "Failed: %s does not match Lattice: %s" % (spcname, spc['SGLatt'])
2839        onebar = [1]
2840        if spc['SGInv']: onebar.append(-1)
2841        for (op,off) in spc['SGOps']:
2842            for inv in onebar:
2843                for cen in spc['SGCen']:
2844                    noff = off + cen
2845                    noff = MoveToUnitCell(noff)
2846                    mult = tuple((op*inv).ravel().tolist())
2847                    if debug: print "\n%s: %s + %s" % (spcname,mult,noff)
2848                    for refop in cctbx:
2849                        if debug: print refop
2850                        # check the transform
2851                        if refop[:9] != mult: continue
2852                        if debug: print "mult match"
2853                        # check the translation
2854                        reftrans = list(refop[-3:])
2855                        reftrans = MoveToUnitCell(reftrans)
2856                        if all(abs(noff - reftrans) < 1.e-5):
2857                            cctbx.remove(refop)
2858                            break
2859                    else:
2860                        assert False, "failed on %s:\n\t %s + %s" % (spcname,mult,noff)
2861    for key in sgtbxtestinp.sgtbx:
2862        CompareWcctbx(key, sgtbxtestinp.sgtbx[key])
2863selftestlist.append(test2)
2864
2865def test3(): 
2866    '''self-test #3: exercise SytSym (includes GetOprPtrName, GenAtom, GetKNsym)
2867     for selected space groups against info in IT Volume A '''
2868    _ReportTest()
2869    def ExerciseSiteSym (spc, crdlist):
2870        'compare site symmetries and multiplicities for a specified space group'
2871        msg = "failed on site sym test for %s" % spc
2872        (E,S) = SpcGroup(spc)
2873        assert not E, msg
2874        for t in crdlist:
2875            symb, m = SytSym(t[0],S)
2876            if symb.strip() != t[2].strip() or m != t[1]:
2877                print spc,t[0],m,symb,t[2]
2878            assert m == t[1]
2879            #assert symb.strip() == t[2].strip()
2880
2881    ExerciseSiteSym('p 1',[
2882            ((0.13,0.22,0.31),1,'1'),
2883            ((0,0,0),1,'1'),
2884            ])
2885    ExerciseSiteSym('p -1',[
2886            ((0.13,0.22,0.31),2,'1'),
2887            ((0,0.5,0),1,'-1'),
2888            ])
2889    ExerciseSiteSym('C 2/c',[
2890            ((0.13,0.22,0.31),8,'1'),
2891            ((0.0,.31,0.25),4,'2(y)'),
2892            ((0.25,.25,0.5),4,'-1'),
2893            ((0,0.5,0),4,'-1'),
2894            ])
2895    ExerciseSiteSym('p 2 2 2',[
2896            ((0.13,0.22,0.31),4,'1'),
2897            ((0,0.5,.31),2,'2(z)'),
2898            ((0.5,.31,0.5),2,'2(y)'),
2899            ((.11,0,0),2,'2(x)'),
2900            ((0,0.5,0),1,'222'),
2901            ])
2902    ExerciseSiteSym('p 4/n',[
2903            ((0.13,0.22,0.31),8,'1'),
2904            ((0.25,0.75,.31),4,'2(z)'),
2905            ((0.5,0.5,0.5),4,'-1'),
2906            ((0,0.5,0),4,'-1'),
2907            ((0.25,0.25,.31),2,'4(001)'),
2908            ((0.25,.75,0.5),2,'-4(001)'),
2909            ((0.25,.75,0.0),2,'-4(001)'),
2910            ])
2911    ExerciseSiteSym('p 31 2 1',[
2912            ((0.13,0.22,0.31),6,'1'),
2913            ((0.13,0.0,0.833333333),3,'2(100)'),
2914            ((0.13,0.13,0.),3,'2(110)'),
2915            ])
2916    ExerciseSiteSym('R 3 c',[
2917            ((0.13,0.22,0.31),18,'1'),
2918            ((0.0,0.0,0.31),6,'3'),
2919            ])
2920    ExerciseSiteSym('R 3 c R',[
2921            ((0.13,0.22,0.31),6,'1'),
2922            ((0.31,0.31,0.31),2,'3(111)'),
2923            ])
2924    ExerciseSiteSym('P 63 m c',[
2925            ((0.13,0.22,0.31),12,'1'),
2926            ((0.11,0.22,0.31),6,'m(100)'),
2927            ((0.333333,0.6666667,0.31),2,'3m(100)'),
2928            ((0,0,0.31),2,'3m(100)'),
2929            ])
2930    ExerciseSiteSym('I a -3',[
2931            ((0.13,0.22,0.31),48,'1'),
2932            ((0.11,0,0.25),24,'2(x)'),
2933            ((0.11,0.11,0.11),16,'3(111)'),
2934            ((0,0,0),8,'-3(111)'),
2935            ])
2936selftestlist.append(test3)
2937
2938if __name__ == '__main__':
2939    # run self-tests
2940    selftestquiet = False
2941    for test in selftestlist:
2942        test()
2943    print "OK"
Note: See TracBrowser for help on using the repository browser.