source: trunk/GSASIIspc.py @ 1612

Last change on this file since 1612 was 1612, checked in by vondreele, 8 years ago

Set up SS atom defaults
fix "config" error

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 120.7 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: 2014-12-18 14:51:33 +0000 (Thu, 18 Dec 2014) $
12# $Author: vondreele $
13# $Revision: 1612 $
14# $URL: trunk/GSASIIspc.py $
15# $Id: GSASIIspc.py 1612 2014-12-18 14:51:33Z 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: 1612 $")
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':[[0,1],[1.,1.]],'Spos':[[0,1,2, 0,1,2],[1.,1.,1., 1.,1.,1.]],    #sin & cos
1426        'Sadp':[[0,1,2,3,4,5, 0,1,2,3,4,5],[1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.]],
1427        'Smag':[[0,1,2, 0,1,2],[1.,1.,1., 1.,1.,1.]]}
1428    deltx = np.eye((3))*.001
1429    deltu = np.eye((6))*.0001
1430    xyz = np.array(XYZ)%1.
1431    uij = np.array(UIJ)
1432    SGOps = SGData['SGOps']
1433    SSGOps = SSGData['SSGOps']
1434    ssop = SSGOps[0]
1435    sop = SGOps[0]
1436    for iop,Op in enumerate(SGOps):
1437        nxyz = (np.inner(Op[0],xyz)+Op[1])%1.
1438        if SGData['SGInv'] and np.allclose(xyz,-nxyz%1.,1.e-6):
1439            ssop = SSGOps[iop]
1440            ssop = [-ssop[0],-ssop[1]%1.]
1441            sop = [-Op[0],-Op[1]%1.]
1442            break
1443        elif np.allclose(xyz,nxyz,1.e-6) and iop:
1444            ssop = SSGOps[iop]
1445            sop = SGOps[iop]
1446            break
1447    siteSym = SytSym(XYZ,SGData)[0].strip().split('(')[0]
1448    OpText =  MT2text(sop).replace(' ','')
1449    SSOptext = SSMT2text(ssop).replace(' ','')
1450    if siteSym == '1':   #"1" site symmetry
1451        return CSI
1452    elif siteSym == '-1':   #"-1" site symmetry
1453        CSI['Spos'][0] = [0,1,2, -1,-1,-1]
1454        CSI['Sadp'][0] = [-1,-1,-1,-1,-1,-1, 0,1,2,3,4,5,]
1455        return CSI       
1456    print siteSym,OpText,SSOptext   
1457    UniqAx = {'a':'a','b':'b','c':'g'}
1458    if SGData['SGLaue'] == '2/m':
1459        if UniqAx[SGData['SGUniq']] in SSGData['modSymb']:   #e.g. (0b0)
1460            if 's' in SSGData['SSpGrp'].split('(')[1]:
1461                if siteSym == 'm':
1462                    CSI['Spos'][0] = [0,-1,1, -1,1,-1]
1463                    CSI['Sadp'][0] = [0,1,2,-1,3,-1, -1,-1,-1,4,-1,5]
1464                elif siteSym == '2/m':
1465                    CSI['Spos'][0] = [0,-1,1, -1,-1,-1]
1466                    CSI['Sadp'][0] = [-1,-1,-1,-1,-1,-1, -1,-1,-1,0,-1,1]
1467                elif siteSym == '2':
1468                    CSI['Spos'][0] = [0,-1,1, 2,-1,3]               
1469                    CSI['Sadp'][0] = [-1,-1,-1,0,-1,1, -1,-1,-1,2,-1,3]
1470            elif '1/2' in SSGData['modSymb']:    #e.g. (0b1/2)
1471                if siteSym == 'm':
1472                    CSI['Spos'][0] = [-1,-1,-1, -1,-1,-1]
1473                    CSI['Sadp'][0] = [-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1]
1474                elif siteSym == '2/m':
1475                    CSI['Spos'][0] = [0,-1,1, -1,-1,-1]
1476                    CSI['Sadp'][0] = [-1,-1,-1,-1,-1,-1, 0,1,2,-1,3,-1]
1477                elif siteSym == '2':
1478                    CSI['Spos'][0] = [0,-1,1, 2,-1,3]
1479                    CSI['Sadp'][0] = [-1,-1,-1,0,-1,1, -1,-1,-1,2,-1,3]
1480            else:
1481                if siteSym == 'm':
1482                    CSI['Spos'][0] = [-1,0,-1, 1,-1,2]
1483                    CSI['Sadp'][0] = [-1,-1,-1,0,-1,1, 2,3,4,-1,5,-1]
1484                elif siteSym == '2/m':
1485                    CSI['Spos'][0] = [-1,0,-1, -1,-1,-1]
1486                    CSI['Sadp'][0] = [-1,-1,-1,-1,-1,-1, 0,1,2,-1,3,-1]
1487                elif siteSym == '2':
1488                    CSI['Spos'][0] = [-1,0,-1, -1,1,-1]
1489                    CSI['Sadp'][0] = [0,1,2,-1,3,-1, 4,5,6,-1,7,-1]
1490           
1491        else:   #e.g. (a0g)
1492            if 's' in SSGData['SSpGrp'].split('(')[1]:
1493                if siteSym == 'm':
1494                    CSI['Spos'][0] = [-1,0,-1, -1,1,-1]
1495                    CSI['Sadp'][0] = [-1,-1,-1,0,-1,1, -1,-1,-1,2,-1,3]
1496                elif siteSym == '2/m':
1497                    CSI['Spos'][0] = [-1,0,-1, -1,-1,-1]
1498                    CSI['Sadp'][0] = [-1,-1,-1,-1,-1,-1, -1,-1,-1,0,-1,1]
1499                elif siteSym == '2':
1500                    CSI['Spos'][0] = [-1,0,-1, 1,-1,2]
1501                    CSI['Sadp'][0] = [0,1,2,-1,3,-1, -1,-1,-1,4,-1,5]
1502            else:
1503                if siteSym == 'm':
1504                    CSI['Spos'][0] = [0,-1,1, 2,-1,3]
1505                    CSI['Sadp'][0] = [0,1,2,-1,3,-1, 4,5,6,-1,7,-1]
1506                elif siteSym == '2/m':
1507                    CSI['Spos'][0] = [0,-1,1, -1,-1,-1]
1508                    CSI['Sadp'][0] = [-1,-1,-1,-1,-1,-1, 0,1,2,-1,3,-1]
1509                elif siteSym == '2':
1510                    CSI['Spos'][0] = [0,-1,1, -1,2,-1]
1511                    CSI['Sadp'][0] = [-1,-1,-1,0,-1,1, 2,3,4,-1,5,-1]
1512        Sx = CSI['Spos'][0]
1513        Su = CSI['Sadp'][0]
1514        if SGData['SGUniq'] == 'a':
1515            CSI['Spos'][0] = [Sx[1],Sx[2],Sx[0], Sx[4],Sx[5],Sx[3]]
1516            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]]
1517        elif SGData['SGUniq'] == 'c':
1518            CSI['Spos'][0] = [Sx[2],Sx[0],Sx[1], Sx[5],Sx[3],Sx[4]]
1519            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]]
1520#        return CSI
1521#    elif SGData['SGLaue'] == 'mmm':
1522#    elif SGData['SGLaue'] in ['4/m','4/mmm']:
1523#    elif SGData['SGLaue'] in ['3','3m1','31m']:
1524#    elif SGData['SGLaue'] in ['6/m','6/mmm']:
1525#       
1526    xsin = np.zeros(3)
1527    xcos = np.zeros(3)
1528    usin = np.zeros(6)
1529    ucos = np.zeros(6)
1530    for i,idelt in enumerate(deltx):
1531        nxyz = (np.inner(sop[0],(xyz+idelt))+sop[1])%1.
1532        print 'nxyz',i,nxyz
1533        xsin[i] = np.equal((xyz-idelt)%1.,nxyz)[i]
1534        print 'sin',(xyz-idelt)%1.
1535        xcos[i] = np.equal((xyz+idelt)%1.,nxyz)[i]
1536        print 'cos',(xyz+idelt)%1.
1537    print CSI['Spos'][0]
1538    print xsin,xcos
1539    for i,idelt in enumerate(deltu):
1540        nuij = U2Uij(np.inner(sop[0],np.inner(np.abs(Uij2U(uij+idelt)),sop[0])))
1541        usin[i] = np.equal(np.abs(uij-idelt),nuij)[i]
1542        ucos[i] = np.equal(np.abs(uij+idelt),nuij)[i]
1543    print CSI['Sadp'][0]
1544    print usin,ucos
1545    return CSI
1546   
1547def MustrainNames(SGData):
1548    'Needs a doc string'
1549    laue = SGData['SGLaue']
1550    uniq = SGData['SGUniq']
1551    if laue in ['m3','m3m']:
1552        return ['S400','S220']
1553    elif laue in ['6/m','6/mmm','3m1']:
1554        return ['S400','S004','S202']
1555    elif laue in ['31m','3']:
1556        return ['S400','S004','S202','S211']
1557    elif laue in ['3R','3mR']:
1558        return ['S400','S220','S310','S211']
1559    elif laue in ['4/m','4/mmm']:
1560        return ['S400','S004','S220','S022']
1561    elif laue in ['mmm']:
1562        return ['S400','S040','S004','S220','S202','S022']
1563    elif laue in ['2/m']:
1564        SHKL = ['S400','S040','S004','S220','S202','S022']
1565        if uniq == 'a':
1566            SHKL += ['S013','S031','S211']
1567        elif uniq == 'b':
1568            SHKL += ['S301','S103','S121']
1569        elif uniq == 'c':
1570            SHKL += ['S130','S310','S112']
1571        return SHKL
1572    else:
1573        SHKL = ['S400','S040','S004','S220','S202','S022']
1574        SHKL += ['S310','S103','S031','S130','S301','S013']
1575        SHKL += ['S211','S121','S112']
1576        return SHKL
1577       
1578def HStrainVals(HSvals,SGData):
1579    laue = SGData['SGLaue']
1580    uniq = SGData['SGUniq']
1581    DIJ = np.zeros(6)
1582    if laue in ['m3','m3m']:
1583        DIJ[:3] = [HSvals[0],HSvals[0],HSvals[0]]
1584    elif laue in ['6/m','6/mmm','3m1','31m','3']:
1585        DIJ[:4] = [HSvals[0],HSvals[0],HSvals[1],HSvals[0]]
1586    elif laue in ['3R','3mR']:
1587        DIJ = [HSvals[0],HSvals[0],HSvals[0],HSvals[1],HSvals[1],HSvals[1]]
1588    elif laue in ['4/m','4/mmm']:
1589        DIJ[:3] = [HSvals[0],HSvals[0],HSvals[1]]
1590    elif laue in ['mmm']:
1591        DIJ[:3] = [HSvals[0],HSvals[1],HSvals[2]]
1592    elif laue in ['2/m']:
1593        DIJ[:3] = [HSvals[0],HSvals[1],HSvals[2]]
1594        if uniq == 'a':
1595            DIJ[5] = HSvals[3]
1596        elif uniq == 'b':
1597            DIJ[4] = HSvals[3]
1598        elif uniq == 'c':
1599            DIJ[3] = HSvals[3]
1600    else:
1601        DIJ = [HSvals[0],HSvals[1],HSvals[2],HSvals[3],HSvals[4],HSvals[5]]
1602    return DIJ
1603
1604def HStrainNames(SGData):
1605    'Needs a doc string'
1606    laue = SGData['SGLaue']
1607    uniq = SGData['SGUniq']
1608    if laue in ['m3','m3m']:
1609        return ['D11','eA']         #add cubic strain term
1610    elif laue in ['6/m','6/mmm','3m1','31m','3']:
1611        return ['D11','D33']
1612    elif laue in ['3R','3mR']:
1613        return ['D11','D12']
1614    elif laue in ['4/m','4/mmm']:
1615        return ['D11','D33']
1616    elif laue in ['mmm']:
1617        return ['D11','D22','D33']
1618    elif laue in ['2/m']:
1619        Dij = ['D11','D22','D33']
1620        if uniq == 'a':
1621            Dij += ['D23']
1622        elif uniq == 'b':
1623            Dij += ['D13']
1624        elif uniq == 'c':
1625            Dij += ['D12']
1626        return Dij
1627    else:
1628        Dij = ['D11','D22','D33','D12','D13','D23']
1629        return Dij
1630   
1631def MustrainCoeff(HKL,SGData):
1632    'Needs a doc string'
1633    #NB: order of terms is the same as returned by MustrainNames
1634    laue = SGData['SGLaue']
1635    uniq = SGData['SGUniq']
1636    h,k,l = HKL
1637    Strm = []
1638    if laue in ['m3','m3m']:
1639        Strm.append(h**4+k**4+l**4)
1640        Strm.append(3.0*((h*k)**2+(h*l)**2+(k*l)**2))
1641    elif laue in ['6/m','6/mmm','3m1']:
1642        Strm.append(h**4+k**4+2.0*k*h**3+2.0*h*k**3+3.0*(h*k)**2)
1643        Strm.append(l**4)
1644        Strm.append(3.0*((h*l)**2+(k*l)**2+h*k*l**2))
1645    elif laue in ['31m','3']:
1646        Strm.append(h**4+k**4+2.0*k*h**3+2.0*h*k**3+3.0*(h*k)**2)
1647        Strm.append(l**4)
1648        Strm.append(3.0*((h*l)**2+(k*l)**2+h*k*l**2))
1649        Strm.append(4.0*h*k*l*(h+k))
1650    elif laue in ['3R','3mR']:
1651        Strm.append(h**4+k**4+l**4)
1652        Strm.append(3.0*((h*k)**2+(h*l)**2+(k*l)**2))
1653        Strm.append(2.0*(h*l**3+l*k**3+k*h**3)+2.0*(l*h**3+k*l**3+l*k**3))
1654        Strm.append(4.0*(k*l*h**2+h*l*k**2+h*k*l**2))
1655    elif laue in ['4/m','4/mmm']:
1656        Strm.append(h**4+k**4)
1657        Strm.append(l**4)
1658        Strm.append(3.0*(h*k)**2)
1659        Strm.append(3.0*((h*l)**2+(k*l)**2))
1660    elif laue in ['mmm']:
1661        Strm.append(h**4)
1662        Strm.append(k**4)
1663        Strm.append(l**4)
1664        Strm.append(3.0*(h*k)**2)
1665        Strm.append(3.0*(h*l)**2)
1666        Strm.append(3.0*(k*l)**2)
1667    elif laue in ['2/m']:
1668        Strm.append(h**4)
1669        Strm.append(k**4)
1670        Strm.append(l**4)
1671        Strm.append(3.0*(h*k)**2)
1672        Strm.append(3.0*(h*l)**2)
1673        Strm.append(3.0*(k*l)**2)
1674        if uniq == 'a':
1675            Strm.append(2.0*k*l**3)
1676            Strm.append(2.0*l*k**3)
1677            Strm.append(4.0*k*l*h**2)
1678        elif uniq == 'b':
1679            Strm.append(2.0*l*h**3)
1680            Strm.append(2.0*h*l**3)
1681            Strm.append(4.0*h*l*k**2)
1682        elif uniq == 'c':
1683            Strm.append(2.0*h*k**3)
1684            Strm.append(2.0*k*h**3)
1685            Strm.append(4.0*h*k*l**2)
1686    else:
1687        Strm.append(h**4)
1688        Strm.append(k**4)
1689        Strm.append(l**4)
1690        Strm.append(3.0*(h*k)**2)
1691        Strm.append(3.0*(h*l)**2)
1692        Strm.append(3.0*(k*l)**2)
1693        Strm.append(2.0*k*h**3)
1694        Strm.append(2.0*h*l**3)
1695        Strm.append(2.0*l*k**3)
1696        Strm.append(2.0*h*k**3)
1697        Strm.append(2.0*l*h**3)
1698        Strm.append(2.0*k*l**3)
1699        Strm.append(4.0*k*l*h**2)
1700        Strm.append(4.0*h*l*k**2)
1701        Strm.append(4.0*k*h*l**2)
1702    return Strm
1703   
1704def Muiso2Shkl(muiso,SGData,cell):
1705    "this is to convert isotropic mustrain to generalized Shkls"
1706    import GSASIIlattice as G2lat
1707    A = G2lat.cell2AB(cell)[0]
1708   
1709    def minMus(Shkl,muiso,H,SGData,A):
1710        U = np.inner(A.T,H)
1711        S = np.array(MustrainCoeff(U,SGData))
1712        Sum = np.sqrt(np.sum(np.multiply(S,Shkl[:,np.newaxis]),axis=0))
1713        rad = np.sqrt(np.sum((Sum[:,np.newaxis]*H)**2,axis=1))
1714        return (muiso-rad)**2
1715       
1716    laue = SGData['SGLaue']
1717    PHI = np.linspace(0.,360.,60,True)
1718    PSI = np.linspace(0.,180.,60,True)
1719    X = np.outer(npsind(PHI),npsind(PSI))
1720    Y = np.outer(npcosd(PHI),npsind(PSI))
1721    Z = np.outer(np.ones(np.size(PHI)),npcosd(PSI))
1722    HKL = np.dstack((X,Y,Z))
1723    if laue in ['m3','m3m']:
1724        S0 = [1000.,1000.]
1725    elif laue in ['6/m','6/mmm','3m1']:
1726        S0 = [1000.,1000.,1000.]
1727    elif laue in ['31m','3']:
1728        S0 = [1000.,1000.,1000.,1000.]
1729    elif laue in ['3R','3mR']:
1730        S0 = [1000.,1000.,1000.,1000.]
1731    elif laue in ['4/m','4/mmm']:
1732        S0 = [1000.,1000.,1000.,1000.]
1733    elif laue in ['mmm']:
1734        S0 = [1000.,1000.,1000.,1000.,1000.,1000.]
1735    elif laue in ['2/m']:
1736        S0 = [1000.,1000.,1000.,0.,0.,0.,0.,0.,0.]
1737    else:
1738        S0 = [1000.,1000.,1000.,1000.,1000., 1000.,1000.,1000.,1000.,1000., 
1739            1000.,1000.,0.,0.,0.]
1740    S0 = np.array(S0)
1741    HKL = np.reshape(HKL,(-1,3))
1742    result = so.leastsq(minMus,S0,(np.ones(HKL.shape[0])*muiso,HKL,SGData,A))
1743    return result[0]
1744       
1745def SytSym(XYZ,SGData):
1746    '''
1747    Generates the number of equivalent positions and a site symmetry code for a specified coordinate and space group
1748
1749    :param XYZ: an array, tuple or list containing 3 elements: x, y & z
1750    :param SGData: from SpcGroup
1751    :Returns: a two element tuple:
1752
1753     * The 1st element is a code for the site symmetry (see GetKNsym)
1754     * The 2nd element is the site multiplicity
1755
1756    '''
1757    def PackRot(SGOps):
1758        IRT = []
1759        for ops in SGOps:
1760            M = ops[0]
1761            irt = 0
1762            for j in range(2,-1,-1):
1763                for k in range(2,-1,-1):
1764                    irt *= 3
1765                    irt += M[k][j]
1766            IRT.append(int(irt))
1767        return IRT
1768       
1769    SymName = ''
1770    Mult = 1
1771    Isym = 0
1772    if SGData['SGLaue'] in ['3','3m1','31m','6/m','6/mmm']:
1773        Isym = 1073741824
1774    Jdup = 0
1775    Xeqv = GenAtom(XYZ,SGData,True)
1776    IRT = PackRot(SGData['SGOps'])
1777    L = -1
1778    for ic,cen in enumerate(SGData['SGCen']):
1779        for invers in range(int(SGData['SGInv']+1)):
1780            for io,ops in enumerate(SGData['SGOps']):
1781                irtx = (1-2*invers)*IRT[io]
1782                L += 1
1783                if not Xeqv[L][1]:
1784                    Jdup += 1
1785                    jx = GetOprPtrName(str(irtx))
1786                    if jx[2] < 39:
1787                        Isym += 2**(jx[2]-1)
1788    if Isym == 1073741824: Isym = 0
1789    Mult = len(SGData['SGOps'])*len(SGData['SGCen'])*(int(SGData['SGInv'])+1)/Jdup
1790         
1791    return GetKNsym(str(Isym)),Mult
1792   
1793def ElemPosition(SGData):
1794    ''' Under development.
1795    Object here is to return a list of symmetry element types and locations suitable
1796    for say drawing them.
1797    So far I have the element type... getting all possible locations without lookup may be impossible!
1798    '''
1799    SymElements = []
1800    Inv = SGData['SGInv']
1801    Cen = SGData['SGCen']
1802    eleSym = {-3:['','-1'],-2:['',-6],-1:['2','-4'],0:['3','-3'],1:['4','m'],2:['6',''],3:['1','']}
1803    # get operators & expand if centrosymmetric
1804    Ops = SGData['SGOps']
1805    opM = np.array([op[0].T for op in Ops])
1806    opT = np.array([op[1] for op in Ops])
1807    if Inv:
1808        opM = np.concatenate((opM,-opM))
1809        opT = np.concatenate((opT,-opT))
1810    opMT = zip(opM,opT)
1811    for M,T in opMT[1:]:        #skip I
1812        Dt = int(nl.det(M))
1813        Tr = int(np.trace(M))
1814        Dt = -(Dt-1)/2
1815        Es = eleSym[Tr][Dt]
1816        if Dt:              #rotation-inversion
1817            I = np.eye(3)
1818            if Tr == 1:     #mirrors/glides
1819                if np.any(T):       #glide
1820                    M2 = np.inner(M,M)
1821                    MT = np.inner(M,T)+T
1822                    print 'glide',Es,MT
1823                    print M2
1824                else:               #mirror
1825                    print 'mirror',Es,T
1826                    print I-M
1827                X = [-1,-1,-1]
1828            elif Tr == -3:  # pure inversion
1829                X = np.inner(nl.inv(I-M),T)
1830                print 'inversion',Es,X
1831            else:           #other rotation-inversion
1832                M2 = np.inner(M,M)
1833                MT = np.inner(M,T)+T
1834                print 'rot-inv',Es,MT
1835                print M2
1836                X = [-1,-1,-1]
1837        else:               #rotations
1838            print 'rotation',Es
1839            X = [-1,-1,-1]
1840        #SymElements.append([Es,X])
1841       
1842    return #SymElements
1843   
1844def ApplyStringOps(A,SGData,X,Uij=[]):
1845    'Needs a doc string'
1846    SGOps = SGData['SGOps']
1847    SGCen = SGData['SGCen']
1848    Ax = A.split('+')
1849    Ax[0] = int(Ax[0])
1850    iC = 0
1851    if Ax[0] < 0:
1852        iC = 1
1853    Ax[0] = abs(Ax[0])
1854    nA = Ax[0]%100-1
1855    cA = Ax[0]/100
1856    Cen = SGCen[cA]
1857    M,T = SGOps[nA]
1858    if len(Ax)>1:
1859        cellA = Ax[1].split(',')
1860        cellA = np.array([int(a) for a in cellA])
1861    else:
1862        cellA = np.zeros(3)
1863    newX = (1-2*iC)*(Cen+np.inner(M,X)+T)+cellA
1864    if len(Uij):
1865        U = Uij2U(Uij)
1866        U = np.inner(M,np.inner(U,M).T)
1867        newUij = U2Uij(U)
1868        return [newX,newUij]
1869    else:
1870        return newX
1871       
1872def StringOpsProd(A,B,SGData):
1873    """
1874    Find A*B where A & B are in strings '-' + '100*c+n' + '+ijk'
1875    where '-' indicates inversion, c(>0) is the cell centering operator,
1876    n is operator number from SgOps and ijk are unit cell translations (each may be <0).
1877    Should return resultant string - C. SGData - dictionary using entries:
1878
1879       *  'SGCen': cell centering vectors [0,0,0] at least
1880       *  'SGOps': symmetry operations as [M,T] so that M*x+T = x'
1881
1882    """
1883    SGOps = SGData['SGOps']
1884    SGCen = SGData['SGCen']
1885    #1st split out the cell translation part & work on the operator parts
1886    Ax = A.split('+'); Bx = B.split('+')
1887    Ax[0] = int(Ax[0]); Bx[0] = int(Bx[0])
1888    iC = 0
1889    if Ax[0]*Bx[0] < 0:
1890        iC = 1
1891    Ax[0] = abs(Ax[0]); Bx[0] = abs(Bx[0])
1892    nA = Ax[0]%100-1;  nB = Bx[0]%100-1
1893    cA = Ax[0]/100;  cB = Bx[0]/100
1894    Cen = (SGCen[cA]+SGCen[cB])%1.0
1895    cC = np.nonzero([np.allclose(C,Cen) for C in SGCen])[0][0]
1896    Ma,Ta = SGOps[nA]; Mb,Tb = SGOps[nB]
1897    Mc = np.inner(Ma,Mb.T)
1898#    print Ma,Mb,Mc
1899    Tc = (np.add(np.inner(Mb,Ta)+1.,Tb))%1.0
1900#    print Ta,Tb,Tc
1901#    print [np.allclose(M,Mc)&np.allclose(T,Tc) for M,T in SGOps]
1902    nC = np.nonzero([np.allclose(M,Mc)&np.allclose(T,Tc) for M,T in SGOps])[0][0]
1903    #now the cell translation part
1904    if len(Ax)>1:
1905        cellA = Ax[1].split(',')
1906        cellA = [int(a) for a in cellA]
1907    else:
1908        cellA = [0,0,0]
1909    if len(Bx)>1:
1910        cellB = Bx[1].split(',')
1911        cellB = [int(b) for b in cellB]
1912    else:
1913        cellB = [0,0,0]
1914    cellC = np.add(cellA,cellB)
1915    C = str(((nC+1)+(100*cC))*(1-2*iC))+'+'+ \
1916        str(int(cellC[0]))+','+str(int(cellC[1]))+','+str(int(cellC[2]))
1917    return C
1918           
1919def U2Uij(U):
1920    #returns the UIJ vector U11,U22,U33,U12,U13,U23 from tensor U
1921    return [U[0][0],U[1][1],U[2][2],2.*U[0][1],2.*U[0][2],2.*U[1][2]]
1922   
1923def Uij2U(Uij):
1924    #returns the thermal motion tensor U from Uij as numpy array
1925    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]]])
1926
1927def StandardizeSpcName(spcgroup):
1928    '''Accept a spacegroup name where spaces may have not been used
1929    in the names according to the GSAS convention (spaces between symmetry
1930    for each axis) and return the space group name as used in GSAS
1931    '''
1932    rspc = spcgroup.replace(' ','').upper()
1933    # deal with rhombohedral and hexagonal setting designations
1934    rhomb = ''
1935    if rspc[-1:] == 'R':
1936        rspc = rspc[:-1]
1937        rhomb = ' R'
1938    elif rspc[-1:] == 'H': # hexagonal is assumed and thus can be ignored
1939        rspc = rspc[:-1]
1940    # look for a match in the spacegroup lists
1941    for i in spglist.values():
1942        for spc in i:
1943            if rspc == spc.replace(' ','').upper():
1944                return spc + rhomb
1945    # how about the post-2002 orthorhombic names?
1946    for i,spc in sgequiv_2002_orthorhombic:
1947        if rspc == i.replace(' ','').upper():
1948            return spc
1949    # not found
1950    return ''
1951
1952   
1953spglist = {}
1954'''A dictionary of space groups as ordered and named in the pre-2002 International
1955Tables Volume A, except that spaces are used following the GSAS convention to
1956separate the different crystallographic directions.
1957Note that the symmetry codes here will recognize many non-standard space group
1958symbols with different settings. They are ordered by Laue group
1959'''
1960spglist = {
1961    'P1' : ('P 1','P -1',), # 1-2
1962    'P2/m': ('P 2','P 21','P m','P a','P c','P n',
1963        '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
1964    'C2/m':('C 2','C m','C c','C n',
1965        'C 2/m','C 2/c','C 2/n',),
1966    'Pmmm':('P 2 2 2',
1967        'P 2 2 21','P 21 2 2','P 2 21 2',
1968        'P 21 21 2','P 2 21 21','P 21 2 21',
1969        'P 21 21 21',
1970        'P m m 2','P 2 m m','P m 2 m',
1971        'P m c 21','P 21 m a','P b 21 m','P m 21 b','P c m 21','P 21 a m',
1972        'P c c 2','P 2 a a','P b 2 b',
1973        'P m a 2','P 2 m b','P c 2 m','P m 2 a','P b m 2','P 2 c m',
1974        'P c a 21','P 21 a b','P c 21 b','P b 21 a','P b c 21','P 21 c a',
1975        'P n c 2','P 2 n a','P b 2 n','P n 2 b','P c n 2','P 2 a n',
1976        'P m n 21','P 21 m n','P n 21 m','P m 21 n','P n m 21','P 21 n m',
1977        'P b a 2','P 2 c b','P c 2 a',
1978        'P n a 21','P 21 n b','P c 21 n','P n 21 a','P b n 21','P 21 c n',
1979        'P n n 2','P 2 n n','P n 2 n',
1980        'P m m m','P n n n',
1981        'P c c m','P m a a','P b m b',
1982        'P b a n','P n c b','P c n a',
1983        'P m m a','P b m m','P m c m','P m a m','P m m b','P c m m',
1984        'P n n a','P b n n','P n c n','P n a n','P n n b','P c n n',
1985        'P m n a','P b m n','P n c m','P m a n','P n m b','P c n m',
1986        'P c c a','P b a a','P b c b','P b a b','P c c b','P c a a',
1987        'P b a m','P m c b','P c m a',
1988        'P c c n','P n a a','P b n b',
1989        'P b c m','P m c a','P b m a','P c m b','P c a m','P m a b',
1990        'P n n m','P m n n','P n m n',
1991        'P m m n','P n m m','P m n m',
1992        'P b c n','P n c a','P b n a','P c n b','P c a n','P n a b',
1993        'P b c a','P c a b',
1994        'P n m a','P b n m','P m c n','P n a m','P m n b','P c m n',
1995        ),
1996    'Cmmm':('C 2 2 21','C 2 2 2','C m m 2',
1997        'C m c 21','C c m 21','C c c 2','C m 2 m','C 2 m m',
1998        'C m 2 a','C 2 m b','C c 2 m','C 2 c m','C c 2 a','C 2 c b',
1999        'C m c m','C m c a','C c m b',
2000        'C m m m','C c c m','C m m a','C m m b','C c c a','C c c b',),
2001    'Immm':('I 2 2 2','I 21 21 21',
2002        'I m m 2','I m 2 m','I 2 m m',
2003        'I b a 2','I 2 c b','I c 2 a',
2004        'I m a 2','I 2 m b','I c 2 m','I m 2 a','I b m 2','I 2 c m',
2005        'I m m m','I b a m','I m c b','I c m a',
2006        'I b c a','I c a b',
2007        'I m m a','I b m m ','I m c m','I m a m','I m m b','I c m m',),
2008    'Fmmm':('F 2 2 2','F m m m', 'F d d d',
2009        'F m m 2','F m 2 m','F 2 m m',
2010        'F d d 2','F d 2 d','F 2 d d',),
2011    'P4/mmm':('P 4','P 41','P 42','P 43','P -4','P 4/m','P 42/m','P 4/n','P 42/n',
2012        'P 4 2 2','P 4 21 2','P 41 2 2','P 41 21 2','P 42 2 2',
2013        'P 42 21 2','P 43 2 2','P 43 21 2','P 4 m m','P 4 b m','P 42 c m',
2014        'P 42 n m','P 4 c c','P 4 n c','P 42 m c','P 42 b c','P -4 2 m',
2015        'P -4 2 c','P -4 21 m','P -4 21 c','P -4 m 2','P -4 c 2','P -4 b 2',
2016        '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',
2017        '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',
2018        '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',
2019        'P 42/n c m',),
2020    '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',
2021        'I 4 c m','I 41 m d','I 41 c d',
2022        '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',
2023        'I 41/a m d','I 41/a c d'),
2024    'R3-H':('R 3','R -3','R 3 2','R 3 m','R 3 c','R -3 m','R -3 c',),
2025    'P6/mmm': ('P 3','P 31','P 32','P -3','P 3 1 2','P 3 2 1','P 31 1 2',
2026        'P 31 2 1','P 32 1 2','P 32 2 1', 'P 3 m 1','P 3 1 m','P 3 c 1',
2027        'P 3 1 c','P -3 1 m','P -3 1 c','P -3 m 1','P -3 c 1','P 6','P 61',
2028        'P 65','P 62','P 64','P 63','P -6','P 6/m','P 63/m','P 6 2 2',
2029        'P 61 2 2','P 65 2 2','P 62 2 2','P 64 2 2','P 63 2 2','P 6 m m',
2030        'P 6 c c','P 63 c m','P 63 m c','P -6 m 2','P -6 c 2','P -6 2 m',
2031        'P -6 2 c','P 6/m m m','P 6/m c c','P 63/m c m','P 63/m m c',),
2032    'Pm3m': ('P 2 3','P 21 3','P m 3','P n 3','P a 3','P 4 3 2','P 42 3 2',
2033        'P 43 3 2','P 41 3 2','P -4 3 m','P -4 3 n','P m 3 m','P n 3 n',
2034        'P m 3 n','P n 3 m',),
2035    'Im3m':('I 2 3','I 21 3','I m -3','I a -3', 'I 4 3 2','I 41 3 2',
2036        'I -4 3 m', 'I -4 3 d','I m -3 m','I m 3 m','I a -3 d',),
2037    'Fm3m':('F 2 3','F m -3','F d -3','F 4 3 2','F 41 3 2','F -4 3 m',
2038        'F -4 3 c','F m -3 m','F m 3 m','F m -3 c','F d -3 m','F d -3 c',),
2039}
2040
2041ssdict = {}
2042'''A dictionary of superspace group symbols allowed for each entry in spglist
2043(except cubics). Monoclinics are all b-unique setting.
2044'''
2045ssdict = {
2046#1,2
2047    'P 1':['(abg)',],'P -1':['(abg)',],
2048#monoclinic - done
2049#3
2050    'P 2':['(a0g)','(a1/2g)','(0b0)','(0b0)s','(1/2b0)','(0b1/2)',],
2051#4       
2052    'P 21':['(a0g)','(0b0)','(1/2b0)','(0b1/2)',],
2053#5
2054    'C 2':['(a0g)','(0b0)','(0b0)s','(0b1/2)',],
2055#6
2056    'P m':['(a0g)','(a0g)s','(a1/2g)','(0b0)','(1/2b0)','(0b1/2)',],
2057#7
2058    'P a':['(a0g)','(a1/2g)','(0b0)','(0b1/2)',],
2059    'P c':['(a0g)','(a1/2g)','(0b0)','(1/2b0)',],
2060    'P n':['(a0g)','(a1/2g)','(0b0)','(1/2b1/2)',],
2061#8       
2062    'C m':['(a0g)','(a0g)s','(0b0)','(0b1/2)',],
2063#9       
2064    'C c':['(a0g)','(a0g)s','(0b0)',],
2065    'C n':['(a0g)','(a0g)s','(0b0)',],
2066#10       
2067    'P 2/m':['(a0g)','(a0g)0s','(a1/2g)','(0b0)','(0b0)s0','(1/2b0)','(0b1/2)',],
2068#11
2069    'P 21/m':['(a0g)','(a0g)0s','(0b0)','(0b0)s0','(1/2b0)','(0b1/2)',],
2070#12       
2071    'C 2/m':['(a0g)','(a0g)0s','(0b0)','(0b0)s0','(0b1/2)',],
2072#13
2073    'P 2/c':['(a0g)','(a0g)0s','(a1/2g)','(0b0)','(0b0)s0','(1/2b0)',],
2074    'P 2/a':['(a0g)','(a0g)0s','(a1/2g)','(0b0)','(0b0)s0','(0b1/2)',],
2075    'P 2/n':['(a0g)','(a0g)0s','(a1/2g)','(0b0)','(0b0)s0','(1/2b1/2)',],
2076#14
2077    'P 21/c':['(a0g)','(0b0)','(1/2b0)',],
2078    'P 21/a':['(a0g)','(0b0)','(0b1/2)',],
2079    'P 21/n':['(a0g)','(0b0)','(1/2b1/2)',],
2080#15
2081    'C 2/c':['(a0g)','(0b0)','(0b0)s0',],
2082    'C 2/n':['(a0g)','(0b0)','(0b0)s0',],
2083#orthorhombic
2084#16   
2085    'P 2 2 2':['(00g)','(00g)00s','(01/2g)','(1/20g)','(1/21/2g)',
2086        '(a00)','(a00)s00','(a01/2)','(a1/20)','(a1/21/2)',
2087        '(0b0)','(0b0)0s0','(1/2b0)','(0b1/2)','(1/2b1/2)',],
2088#17       
2089    'P 2 2 21':['(00g)','(01/2g)','(1/20g)','(1/21/2g)',
2090        '(a00)','(a00)s00','(a1/20)','(0b0)','(0b0)0s0','(1/2b0)',],
2091    'P 21 2 2':['(a00)','(a01/2)','(a1/20)','(a1/21/2)',
2092        '(0b0)','(0b0)0s0','(1/2b0)','(00g)','(00g)00s','(1/20g)',],
2093    'P 2 21 2':['(0b0)','(0b1/2)','(1/2b0)','(1/2b1/2)',
2094        '(00g)','(00g)00s','(1/20g)','(a00)','(a00)s00','(a1/20)',],
2095#18       
2096    'P 21 21 2':['(00g)','(00g)00s','(a00)','(a01/2)','(0b0)','(0b1/2)',],
2097    'P 2 21 21':['(a00)','(a00)s00','(0b0)','(0b1/2)','(00g)','(01/2g)',],
2098    'P 21 2 21':['(0b0)','(0b0)0s0','(00g)','(01/2g)','(a00)','(a01/2)',],
2099#19       
2100    'P 21 21 21':['(00g)','(a00)','(0b0)',],
2101#20       
2102    'C 2 2 21':['(00g)','(10g)','(01g)','(a00)','(a00)s00','(0b0)','(0b0)0s0',],
2103    'A 21 2 2':['(a00)','(a10)','(a01)','(0b0)','(0b0)0s0','(00g)','(00g)00s',],
2104    'B 2 21 2':['(0b0)','(1b0)','(0b1)','(00g)','(00g)00s','(a00)','(a00)s00',],
2105#21       
2106    'C 2 2 2':['(00g)','(00g)00s','(10g)','(10g)00s','(01g)','(01g)00s',
2107        '(a00)','(a00)s00','(a01/2)','(0b0)','(0b0)0s0','(0b1/2)',],
2108    'A 2 2 2':['(a00)','(a00)s00','(a10)','(a10)s00','(a01)','(a01)s00',
2109        '(0b0)','(0b0)0s0','(0b1/2)','(00g)','(00g)00s','(01/2g)',],
2110    'B 2 2 2':['(0b0)','(0b0)0s0','(1b0)','(1b0)0s0','(0b1)','(0b1)0s0',
2111        '(00g)','(00g)00s','(01/2g)','(a00)','(a00)s00','(a01/2)',],
2112#22       
2113    'F 2 2 2':['(00g)','(00g)00s','(10g)','(01g)',
2114        '(a00)','(a00)s00','(a10)','(a01)',
2115        '(0b0)','(0b0)0s0','(1b0)','(0b1)',],
2116#23       
2117    'I 2 2 2':['(00g)','(00g)00s','(a00)','(a00)s00','(0b0)','(0b0)0s0',],
2118#24       
2119    'I 21 21 21':['(00g)','(00g)00s','(a00','(a00)s00','(0b0)','(0b0)0s0',],
2120#25       
2121    'P m m 2':['(00g)','(00g)s0s','(00g)0ss','(00g)ss0',
2122        '(01/2g)','(01/2g)s0s','(1/20g)','(1/20g)0ss','(1/21/2g)',
2123        '(a00)','(a00)0s0','(a1/20)','(a01/2)','(a01/2)0s0','(a1/21/2)',
2124        '(0b0)','(0b0)s00','(0b1/2)','(0b1/2)s00','(1/2b0)','(1/2b1/2)',],       
2125    'P 2 m m':['(a00)','(a00)ss0','(a00)s0s','(a00)0ss',
2126        '(a01/2)','(a01/2)ss0','(a1/20)','(a1/20)s0s','(a1/21/2)',
2127        '(0b0)','(0b0)00s','(1/2b0)','(0b1/2)','(0b1/2)00s','(1/2b1/2)',
2128        '(00g)','(00g)0s0','(01/2g)','(01/2g)0s0','(1/20g)','(1/21/2g)',],
2129    'P m 2 m':['(0b0)','(0b0)ss0','(0b0)0ss','(0b0)s0s',
2130        '(0b1/2)','(0b1/2)ss0','(1/2b0)','(1/2b0)0ss','(1/2b1/2)',
2131        '(00g)','(00g)s00','(1/20g)','(01/2g)','(01/2g)s00','(1/21/2g)',
2132        '(a00)','(a00)0s0','(a01/2)','(a01/2)0s0','(a1/20)','(a1/21/2)',],       
2133#26       
2134    'P m c 21':['(00g)','(00g)s0s','(01/2g)','(01/2g)s0s','(1/20g)','(1/21/2g)',
2135        '(a00)','(a00)0s0','(a1/20)','(0b0)','(0b0)s00','(0b1/2)',],
2136    'P 21 m a':['(a00)','(a00)ss0','(a01/2)','(a01/2)ss0','(a1/20)','(a1/21/2)',
2137        '(0b0)','(0b0)00s','(1/2b0)','(00g)','(00g)0s0','(01/2g)',],
2138    'P b 21 m':['(0b0)','(0b0)ss0','(0b1/2)','(0b1/2)ss0','(1/2b0)','(1/2b1/2)',
2139        '(00g)','(00g)s00','(1/20g)','(a00)','(a00)0s0','(a01/2)',],
2140    'P m 21 b':['(a00)','(a00)ss0','(a01/2)','(a01/2)ss0','(a1/20)','(a1/21/2)',
2141        '(00g)','(00g)0s0','(01/2g)','(0b0)','(0b0)s00','(0b1/2)',],
2142    'P c m 21':['(00g)','(00g)0ss','(1/20g)','(1/20g)0ss','(01/2g)','(1/21/2g)',
2143        '(0b0)','(0a0)s00','(1/2b0)','(a00)','(a00)0s0','(a01/2)',],
2144    'P 21 a m':['(0b0)','(0b0)ss0','(0b1/2)','(0b1/2)ss0','(1/2b0)','(1/2b1/2)',
2145        '(a00)','(a00)00s','(a1/20)','(00g)','(00g)s00','(1/20g)',],
2146#27       
2147    'P c c 2':['(00g)','(00g)s0s','(00g)0ss','(01/2g)','(1/20g)','(1/21/2g)',
2148        '(a00)','(a00)0s0','(a1/20)','(0b0)','(0b0)s00','(1/2b0)',],
2149    'P 2 a a':['(a00)','(a00)ss0','(a00)s0s','(a01/2)','(a1/20)','(a1/21/2)',
2150        '(0b0)','(0b0)00s','(0b1/2)','(00g)','(00g)0s0','(01/2g)',],
2151    'P b 2 b':['(0b0)','(0b0)0ss','(0b0)ss0','(1/2b0)','(0b1/2)','(1/2b1/2)',
2152        '(00g)','(00g)s00','(1/20g)','(a00)','(a00)00s','(a01/2)',],
2153#28       
2154    'P m a 2':['(00g)','(00g)s0s','(00g)ss0','(00g)0ss','(01/2g)','(01/2g)s0s',
2155        '(a00)','(a01/2)','(a1/20)','(a1/21/2)','(0b0)','(0b0)s00',],
2156    'P 2 m b':[],
2157    'P c 2 m':[],
2158    'P m 2 a':[],
2159    'P b m 2':[],
2160    'P 2 c m':[],
2161#29       
2162    'P c a 21':['(00g)','(00g)0ss','(01/2g)','(1/20g)',
2163        '(a00)','(a00)0s0','(a1/20)','(0b0)','(0b0)s00','(1/2b0)',],
2164    'P 21 a b':[],
2165    'P c 21 b':[],
2166    'P b 21 a':[],
2167    'P b c 21':[],
2168    'P 21 c a':[],
2169#30       
2170    'P c n 2':[],
2171    'P 2 a n':[],
2172    'P n 2 b':[],
2173    'P b 2 n':[],
2174    'P n c 2':[],
2175    'P 2 n a':[],
2176#31       
2177    'P m n 21':[],
2178    'P 21 m n':[],
2179    'P n 21 m':[],
2180    'P m 21 n':[],
2181    'P n m 21':[],
2182    'P 21 n m':[],
2183#32       
2184    'P b a 2':['(00g)','(00g)s0s','(00g)0ss','(00g)ss0','(1/21/2g)qq0',
2185        '(a00)','(a01/2)','(0b0)','(0b1/2)',],
2186    'P 2 c b':['(a00)','(a00)ss0','(a00)s0s','(a00)0ss','(a1/21/2)0qq',
2187        '(0b0)','(1/2b0)','(00g)','(1/20g)',],
2188    'P c 2 a':['(0b0)','(0b0)ss0','(0b0)0ss','(0b0)s0s','(1/2b1/2)q0q',
2189        '(00g)','01/2g)','(a00)','(a1/20)',],
2190#33       
2191    'P n a 21':[],
2192    'P 21 n b':[],
2193    'P c 21 n':[],
2194    'P n 21 a':[],
2195    'P b n 21':[],
2196    'P 21 c n':[],
2197#34       
2198    'P n n 2':['(00g)','(00g)s0s','(00g)0ss','(1/21/2g)qq0',
2199        '(a00)','(a1/21/2)0q0','(a1/21/2)00q','(0b0)','(1/2b1/2)q00','(1/2b1/2)00q',],
2200    'P 2 n n':['(a00)','(a00)ss0','(a00)s0s','(a1/21/2)0qq',
2201        '(0b0)','(1/2b1/2)q00','(1/2b1/2)00q','(00g)','(1/21/2b)0q0','(1/21/2g)q00',],
2202    'P n 2 n':['(0b0)','(0b0)ss0','(0b0)0ss','(1/2b1/2)q0q',
2203        '(00g)','(1/21/2g)0q0','(1/21/2g)q00','(a00)','(a1/21/2)00q','(b1/21/2)0q0',],
2204#35       
2205    'C m m 2':['(00g)','(00g)s0s','(00g)0ss','(00g)ss0','(10g)','(10g)s0s','(10g)0ss','(10g)ss0',
2206        '(01g)','(01g)s0s','(01g)0ss','(01g)ss0','(a00)','(a00)0s0','(a01/2)','(a01/2)0s0',
2207        '(0b0)','(0b0)s00','(0b1/2)','(0b1/2)s00',],
2208    'A 2 m m':['(a00)','(a00)s0s','(a00)0ss','(a00)ss0','(a10)','(a10)s0s','(a10)0ss','(a10)ss0',
2209        '(a01)','(a01)s0s','(a01)0ss','(a01)ss0','(0b0)','(0b0)00s','(1/2b0)','(1/2b0)00s',
2210        '(00g)','(00g)0s0','(01/2g)','(01/2g)0s0',],
2211    'B m 2 m':['(0b0)','(0b0)s0s','(0b0)0ss','(0b0)ss0','(1b0)','(1b0)s0s','(1b0)0ss','(1b0)ss0',
2212        '(0b1)','(0b1)s0s','(0b1)0ss','(0b1)ss0','(a00)','(a00)00s','(a01/2)','(a01/2)00s',
2213        '(00g)','(00g)s00','(1/20g)','(1/20g)s00',],
2214#36
2215    'C m c 21':['(00g)','(00g)s0s','(10g)','(10g)s0s','(a00)','(a00)0s0','(0b0)','(0b0)s00',],
2216    'A 21 m a':['(a00)','(a00)ss0','(a10)','(a10)ss0','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2217    'B m 21 b':['(0b0)','(0b0)ss0','(1b0)','(1b0)ss0','(a00)','(a00)00s','(00g)','(00g)s00',],
2218    'B b 21 m':['(0b0)','(0b0)0ss','(0b1)','(0b1)ss0','(a00)','(a00)00s','(00g)','(00g)s00',],
2219    'C c m 21':['(00g)','(00g)0ss','(01g)','(01g)0ss','(a00)','(a00)0s0','(0b0)','(0b0)s00',],
2220    'A 21 a m':['(a00)','(a00)s0s','(a01)','(a01)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2221#37
2222    'C c c 2':['(00g)','(00g)s0s','(00g)0ss','(10g)','(10g)s0s','(10g)0ss','(01g)','(01g)s0s','(01g)0ss',
2223        '(a00)','(a00)0s0','(0b0)','(0b0)s00',],
2224    'A 2 a a':['(a00)','(a00)ss0','(a00)s0s','(a10)','(a10)ss0','(a10)ss0','(a01)','(a01)ss0','(a01)ss0',
2225        '(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2226    'B b 2 b':['(0b0)','(0b0)0ss','(0b0)ss0','(0b1)','(0b1)0ss','(0b1)ss0','(1b0)','(1b0)0ss','(1b0)ss0',
2227        '(a00)','(a00)00s','(00g)','(00g)s00',],
2228#38
2229    'A m m 2':[],
2230    'B 2 m m':[],
2231    'C m 2 m':[],
2232    'A m 2 m':[],
2233    'B m m 2':[],
2234    'C 2 m m':[],
2235#39
2236    'A b m 2':[],
2237    'B 2 c m':[],
2238    'C m 2 a':[],
2239    'A c 2 m':[],
2240    'B m a 2':[],
2241    'C 2 m b':[],
2242#40       
2243    'A m a 2':[],
2244    'B 2 m b':[],
2245    'C c 2 m':[],
2246    'A m 2 a':[],
2247    'B b m 2':[],
2248    'C 2 c m':[],
2249#41
2250    'A b a 2':[],
2251    'B 2 c b':[],
2252    'C c 2 a':[],
2253    'A c 2 a':[],
2254    'B b a 2':[],
2255    'C 2 c b':[],
2256       
2257#42       
2258    'F m m 2':['(00g)','(00g)s0s','(00g)0ss','(00g)ss0','(10g)','(10g)ss0','(10g)s0s',
2259        '(01g)','(01g)ss0','(01g)0ss','(a00)','(a00)0s0','(a01)','(a01)0s0',
2260        '(0b0)','(0b0)s00','(0b1)','(0b1)s00',],       
2261    'F 2 m m':['(a00)','(a00)ss0','(a00)s0s','(a00)0ss','(a10)','(a10)0ss','(a10)ss0',
2262        '(a01)','(a01)0ss','(a01)s0s','(0b0)','(0b0)00s','(1b0)','(1b0)00s',
2263        '(00g)','(00g)0s0','(10g)','(10g)0s0',],
2264    'F m 2 m':['(0b0)','(0b0)0ss','(0b0)ss0','(0b0)s0s','(0b1)','(0b1)s0s','(0b1)0ss',
2265        '(1b0)','(1b0)s0s','(1b0)ss0','(00g)','(00g)s00','(01g)','(01g)s00',
2266        '(a00)','(a00)00s','(a10)','(a10)00s',],       
2267#43       
2268    'F d d 2':['(00g)','(00g)0ss','(00g)s0s','(a00)','(0b0)',],
2269    'F 2 d d':['(a00)','(a00)s0s','(a00)ss0','(00g)','(0b0)',],       
2270    'F d 2 d':['(0b0)','(0b0)0ss','(0b0)ss0','(a00)','(00g)',],
2271#44
2272    'I m m 2':['(00g)','(00g)ss0','(00g)s0s','(00g)0ss','(a00)','(a00)0s0','(0b0)','(0b0)s00',],
2273    'I 2 m m':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2274    'I m 2 m':['(0b0)','(0b0)s0s','(0b0)0ss','(0b0)ss0','(00g)','(00g)s00','(a00)','(a00)00s',],
2275#45       
2276    'I b a 2':['(00g)','(00g)ss0','(00g)s0s','(00g)0ss','(a00)','(a00)0s0','(0b0)','(0b0)s00',],
2277    'I 2 c b':['(0b0)','(0b0)s0s','(0b0)0ss','(0b0)ss0','(00g)','(00g)s00','(a00)','(a00)00s',],
2278    'I c 2 a':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2279#46       
2280    'I m a 2':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2281    'I 2 m b':['(0b0)','(0b0)s0s','(0b0)0ss','(0b0)ss0','(00g)','(00g)s00','(a00)','(a00)00s',],       
2282    'I c 2 m':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2283    'I m 2 a':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2284    'I b m 2':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
2285    'I 2 c m':['(0b0)','(0b0)s0s','(0b0)0ss','(0b0)ss0','(00g)','(00g)s00','(a00)','(a00)00s',],
2286#47       
2287    'P m m m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(01/2g)','(01/2g)s00','(1/20g)','(1/20g)s00','(1/21/2g)',
2288        '(a00)','(a00)0s0','(a00)00s','(a00)0ss','(a01/2)','(a01/2)0s0','(a1/20)','(a1/20)00s','(a1/21/2)',
2289        '(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s','(1/2b0)','(1/2b0)00s','(0b1/2)','(0b1/2)s00','(1/2b1/2)',],
2290#48 o@i qq0,0qq,q0q ->000
2291    'P n n n':['(00g)','(00g)s00','(00g)0s0','(1/21/2g)',
2292        '(a00)','(a00)0s0','(a00)00s','(a1/21/2)',
2293        '(0b0)','(0b0)s00','(0b0)00s','(1/2b1/2)',],
2294#49       
2295    'P c c m':['(00g)','(00g)s00','(00g)0s0','(01/2g)','(1/20g)','(1/21/2g)',
2296        '(a00)','(a00)0s0','(a00)00s','(a00)0ss','(a1/20)','(a1/20)00s',
2297        '(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s','(1/2b0)','(1/2b0)00s',],       
2298    'P m a a':['(a00)','(a00)0s0','(a00)00s','(a01/2)','(a1/20)','(a1/21/2)',
2299        '(0b0)','(0b0)00s','(0b0)s00','(0b0)s0s','(0b1/2)','(0b1/2)s00',
2300        '(00g)','(00g)0s0','(00g)s00','(00g)ss0','(01/2g)','(01/2g)s00',],       
2301    'P b m b':['(0b0)','(0b0)00s','(0b0)s00','(0b1/2)','(1/2b0)','(1/2b1/2)',
2302        '(00g)','(00g)s00','(00g)0s0','(00g)ss0','(1/20g)','(1/20g)0s0',
2303        '(a00)','(a00)00s','(a00)0s0','(a00)0ss','(a01/2)','(a01/2)0s0',],
2304#50 o@i qq0,0qq,q0q ->000
2305    'P b a n':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(1/21/2g)',
2306        '(a00)','(a00)0s0','(a01/2)','(0b0)','(0b0)s00','(0b1/2)',],
2307    'P n c b':['(a00)','(a00)0s0','(a00)00s','(a00)0ss','(a1/21/2)',
2308        '(0b0)','(0b0)00s','(1/2b0)','(00g)','(00g)0s0','(1/20g)',],
2309    'P c n a':['(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s','(1/2b1/2)',
2310        '(00g)','(00g)s00','(01/2a)','(a00)','(a00)00s','(a1/20)',],
2311#51       
2312    'P m m a':[],
2313    'P b m m':[],
2314    'P m c m':[],
2315    'P m a m':[],
2316    'P m m b':[],
2317    'P c m m':[],
2318#52   o@i qq0,0qq,q0q ->000     
2319    'P n n a':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)00s',
2320        '(0b0)','(0b0)00s','(a1/21/2)','(1/2b1/2)',],
2321    'P b n n':['(a00)','(a00)0s0','(a00)00s','(0b0)','(0b0)s00',
2322        '(00g)','(00g)s00','(1/2b1/2)','(1/21/2g)',],
2323    'P n c n':['(0b0)','(0b0)s00','(0b0)00s','(00g)','(00g)0s0',
2324        '(a00)','(a00)0s0','(1/21/2g)','(a1/21/2)',],
2325    'P n a n':['(0b0)','(0b0)s00','(0b0)00s','(00g)','(00g)0s0',
2326        '(a00)','(a00)0s0','(1/21/2g)','(a1/21/2)',],
2327    'P n n b':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)00s',
2328        '(0b0)','(0b0)00s','(a1/21/2)','(1/2b1/2)',],
2329    'P c n n':['(a00)','(a00)0s0','(a00)00s','(0b0)','(0b0)s00',
2330        '(00g)','(00g)s00','(1/2b1/2)','(1/21/2g)',],
2331#53       
2332    'P m n a':[],
2333    'P b m n':[],
2334    'P n c m':[],
2335    'P m a n':[],
2336    'P n m b':[],
2337    'P c n m':[],
2338#54       
2339    'P c c a':[],
2340    'P b a a':[],
2341    'P b c b':[],
2342    'P b a b':[],
2343    'P c c b':[],
2344    'P c a a':[],
2345#55       
2346    'P b a m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0',
2347        '(a00)','(a00)00s','(a01/2)','(0b0)','(0b0)00s','(0b1/2)'],
2348    'P m c b':['(a00)','(a00)0s0','(a00)00s','(a00)0ss',
2349        '(0b0)','(0b0)s00','(1/2b0)','(00g)','(00g)s00','(1/20g)'],
2350    'P c m a':['(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s',
2351        '(a00)','(a00)0s0','(a1/20)','(00g)','(00g)0s0','(01/2g)'],
2352#56       
2353    'P c c n':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2354        '(0b0)','(0b0)s00'],
2355    'P n a a':['(a00)','(a00)0s0','(a00)00s','(0b0)','(0b0)00s',
2356        '(00g)','(00g)0s0'],
2357    'P b n b':['(0b0)','(0b0)s00','(0b0)00s','(a00)','(a00)00s',
2358        '(00g)','(00g)s00'],
2359#57       
2360    'P b c m':[],
2361    'P m c a':[],
2362    'P b m a':[],
2363    'P c m b':[],
2364    'P c a m':[],
2365    'P m a b':[],
2366#58       
2367    'P n n m':['(00g)','(00g)s00','(00g)0s0','(a00)',
2368        '(a00)00s','(0b0)','(0b0)00s'],
2369    'P m n n':['(00g)','(00g)s00','(a00)','(a00)0s0',
2370        '(a00)00s','(0b0)','(0b0)s00'],
2371    'P n m n':['(00g)','(00g)0s0','(a00)','(a00)0s0',
2372        '(0b0)','(0b0)s00','(0b0)00s',],
2373#59 o@i
2374    'P m m n':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2375        '(a01/2)','(a01/2)0s0','(0b0)','(0b0)s00','(0b1/2)','(0b1/2)s00',],
2376    'P n m m':['(a00)','(a00)0s0','(a00)00s','(a00)0ss','(00g)','(00g)0s0',
2377        '(1/20g)','(1/20g)0s0','(0b0)','(0b0)00s','(1/2b0)','(1/2b0)00s'],
2378    'P m n m':['(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s','(00g)','(00g)s00',
2379        '(01/2g)','(01/2g)s00','(a00)','(a00)00s','(a1/20)','(a1/20)00s'],
2380#60       
2381    'P b c n':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2382        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
2383    'P n c a':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2384        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
2385    'P b n a':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2386        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
2387    'P c n b':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2388        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
2389    'P c a n':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2390        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
2391    'P n a b':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2392        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
2393#61       
2394    'P b c a':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0','(a00)00s',
2395        '(0b0)','(0b0)s00','(0b0)00s'],
2396    'P c a b':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0','(a00)00s',
2397        '(0b0)','(0b0)s00','(0b0)00s'],
2398#62       
2399    'P n m a':['(00g)','(00g)0s0','(a00)','(a00)0s0','(0b0)','(0b0)00s'],
2400    'P b n m':['(00g)','(00g)s00','(a00)','(a00)00s','(0b0)','(0b0)00s'],
2401    'P m c n':['(00g)','(00g)s00','(a00)','(a00)0s0','(0b0)','(0b0)s00'],
2402    'P n a m':['(00g)','(00g)0s0','(a00)','(a00)00s','(0b0)','(0b0)00s'],
2403    'P m n b':['(00g)','(00g)s00','(a00)','(a00)00s','(0b0)','(0b0)s00'],
2404    'P c m n':['(00g)','(00g)0s0','(a00)','(a00)0s0','(0b0)','(0b0)s00'],
2405#63
2406    'C m c m':[],
2407    'A m m a':[],
2408    'B b m m':[],
2409    'B m m b':[],
2410    'C c m m':[],
2411    'A m a m':[],
2412#64       
2413    'C m c a':['(00g)','(00g)s00','(10g)','(10g)s00','(a00)',],
2414    'A b m a':[],
2415    'B b c m':[],
2416    'B m a b':[],
2417    'C c m b':[],
2418    'A c a m':[],
2419#65       
2420    'C m m m':[],
2421    'A m m m':[],
2422    'B m m m':[],
2423#66       
2424    'C c c m':[],
2425    'A m m a':[],
2426    'B b m b':[],
2427#67       
2428    'C m m a':[],
2429    'A b m m':[],
2430    'B m c m':[],
2431    'B m a m':[],
2432    'C m m b':[],
2433    'A c m m':[],
2434#68 o@i
2435    'C c c a':[],
2436    'A b a a':[],
2437    'B b c b':[],
2438    'B b a b':[],
2439    'C c c b':[],
2440    'A c a a':[],
2441#69       
2442    'F m m m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2443        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s',
2444        '(10g)','(10g)s00','(10g)0s0','(10g)ss0','(a10)','(a10)0s0',
2445        '(a10)00s','(a10)0ss','(0b1)','(0b1)s00','(0b1)00s','(0b1)s0s',
2446        '(01g)','(01g)s00','(01g)0s0','(01g)ss0','(a01)','(a01)0s0',
2447        '(a01)00s','(a01)0ss','(1b0)','(1b0)s00','(1b0)00s','(1b0)s0s'],
2448#70 o@i       
2449    'F d d d':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
2450        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s',],
2451       
2452#71
2453    'I m m m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2454        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s',],
2455#72       
2456    'I b a m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2457        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2458    'I m c b':['(a00)','(a00)0s0','(a00)00s','(a00)0ss','(0b0)','(0b0)00s',
2459        '(0b0)s00','(0b0)s0s','(00g)','(00g)0s0','(00g)s00','(00g)ss0'],
2460    'I c m a':['(0b0)','(0b0)00s','(0b0)s00','(0b0)s0s','(00g)','(00g)s00',
2461        '(00g)0s0','(00g)ss0','(a00)','(a00)00s','(a00)0s0','(a00)0ss'],
2462#73       
2463    'I b c a':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2464        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2465    'I c a b':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2466        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2467#74       
2468    'I m m a':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2469        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2470    'I b m m ':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2471        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2472    'I m c 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 a m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2475        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2476    'I m m b':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2477        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2478    'I c m m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
2479        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
2480#tetragonal - done
2481#75
2482    'P 4':['(00g)','(00g)q','(00g)s','(1/21/2g)','(1/21/2g)q',],
2483#76
2484    'P 41':['(00g)','(1/21/2g)',],
2485#77
2486    'P 42':['(00g)','(00g)q','(1/21/2g)','(1/21/2g)q',],
2487#78
2488    'P 43':['(00g)','(1/21/2g)',],
2489#79
2490    'I 4':['(00g)','(00g)q','(00g)s',],
2491#80
2492    'I 41':['(00g)','(00g)q',],
2493#81
2494    'P -4':['(00g)','(1/21/2g)',],
2495#82
2496    'I -4':['(00g)',],
2497#83
2498    'P 4/m':['(00g)','(00g)s0','(1/21/2g)',],
2499#84
2500    'P 42/m':['(00g)','(1/21/2g)',],
2501#85 o@i q0 -> 00
2502    'P 4/n':['(00g)','(00g)s0','(1/21/2g)',], #q0?
2503#86 o@i q0 -> 00
2504    'P 42/n':['(00g)','(1/21/2g)',],      #q0?
2505#87
2506    'I 4/m':['(00g)','(00g)s0',],
2507#88
2508    'I 41/a':['(00g)',],
2509#89
2510    'P 4 2 2':['(00g)','(00g)q00','(00g)s00','(1/21/2g)','(1/21/2g)q00',],
2511#90
2512    'P 4 21 2':['(00g)','(00g)q00','(00g)s00',],
2513#91
2514    'P 41 2 2':['(00g)','(1/21/2g)',],
2515#92
2516    'P 41 21 2':['(00g)',],
2517#93
2518    'P 42 2 2':['(00g)','(00g)q00','(1/21/2g)','(1/21/2g)q00',],
2519#94
2520    'P 42 21 2':['(00g)','(00g)q00',],
2521#95
2522    'P 43 2 2':['(00g)','(1/21/2g)',],
2523#96
2524    'P 43 21 2':['(00g)',],
2525#97
2526    'I 4 2 2':['(00g)','(00g)q00','(00g)s00',],
2527#98
2528    'I 41 2 2':['(00g)','(00g)q00',],
2529#99
2530    'P 4 m m':['(00g)','(00g)ss0','(00g)0ss','(00g)s0s','(1/21/2g)','(1/21/2g)0ss'],
2531#100
2532    'P 4 b m':['(00g)','(00g)ss0','(00g)0ss','(00g)s0s','(1/21/2g)qq0','(1/21/2g)qqs',],
2533#101
2534    'P 42 c m':['(00g)','(00g)0ss','(1/21/2g)','(1/21/2g)0ss',],
2535#102
2536    'P 42 n m':['(00g)','(00g)0ss','(1/21/2g)qq0','(1/21/2g)qqs',],
2537#103
2538    'P 4 c c':['(00g)','(00g)ss0','(1/21/2g)',],
2539#104
2540    'P 4 n c':['(00g)','(00g)ss0','(1/21/2g)qq0',],
2541#105
2542    'P 42 m c':['(00g)','(00g)ss0','(1/21/2g)',],
2543#106
2544    'P 42 b c':['(00g)','(00g)ss0','(1/21/2g)qq0',],
2545#107
2546    'I 4 m m':['(00g)','(00g)ss0','(00g)0ss','(00g)s0s',],
2547#108
2548    'I 4 c m':['(00g)','(00g)ss0','(00g)0ss','(00g)s0s',],
2549#109
2550    'I 41 m d':['(00g)','(00g)ss0',],
2551#110
2552    'I 41 c d':['(00g)','(00g)ss0',],
2553#111
2554    'P -4 2 m':['(00g)','(00g)0ss','(1/21/2g)','(1/21/2g)0ss',],
2555#112
2556    'P -4 2 c':['(00g)','(1/21/2g)',],
2557#113
2558    'P -4 21 m':['(00g)','(00g)0ss',],
2559#114
2560    'P -4 21 c':['(00g)',],
2561#115    00s -> 0ss
2562    'P -4 m 2':['(00g)','(00g)0ss','(1/21/2g)',],
2563#116
2564    'P -4 c 2':['(00g)','(1/21/2g)',],
2565#117    00s -> 0ss
2566    'P -4 b 2':['(00g)','(00g)0s0','(1/21/2g)0q0',],
2567#118
2568    'P -4 n 2':['(00g)','(1/21/2g)0q0',],
2569#119
2570    'I -4 m 2':['(00g)','(00g)0s0',],
2571#120
2572    'I -4 c 2':['(00g)','(00g)0s0',],
2573#121    00s -> 0ss
2574    'I -4 2 m':['(00g)','(00g)0ss',],
2575#122
2576    'I -4 2 d':['(00g)',],
2577#123
2578    'P 4/m m m':['(00g)','(00g)s0s0','(00g)00ss','(00g)s00s',
2579        '(1/21/2g)','(1/21/2g)s0s0','(1/21/2g)00ss','(1/21/2g)s00s',],
2580#124
2581    'P 4/m c c':['(00g)','(00g)s0s0','(1/21/2g)',],
2582#125    o@i q0q0 -> 0000, q0qs -> 00ss
2583    'P 4/n b m':['(00g)','(00g)s0s0','(00g)00ss','(00g)s00s','(1/21/2g)','(1/21/2g)00ss',],
2584#126    o@i q0q0 -> 0000
2585    'P 4/n n c':['(00g)','(00g)s0s0','(1/21/2g)',],
2586#127
2587    'P 4/m b m':['(00g)','(00g)s0s0','(00g)00ss','(00g)s00s',],
2588#128
2589    'P 4/m n c':['(00g)','(00g)s0s0',],
2590#129
2591    'P 4/n m m':['(00g)','(00g)s0s0','(00g)00ss','(00g)s00s',],
2592#130
2593    'P 4/n c c':['(00g)','(00g)s0s0',],
2594#131
2595    'P 42/m m c':['(00g)','(00g)s0s0','(1/21/2g)',],
2596#132
2597    'P 42/m c m':['(00g)','(00g)00ss','(1/21/2g)','(1/21/2g)00ss',],
2598#133    o@i q0q0 -> 0000
2599    'P 42/n b c':['(00g)','(00g)s0s0','(1/21/2g)',],
2600#134    o@i q0q0 -> 0000, q0qs -> 00ss
2601    'P 42/n n m':['(00g)','(00g)00ss','(1/21/2g)','(1/21/2g)00ss',],
2602#135
2603    'P 42/m b c':['(00g)','(00g)s0s0',],
2604#136
2605    'P 42/m n m':['(00g)','(00g)00ss',],
2606#137
2607    'P 42/n m c':['(00g)','(00g)s0s0',],
2608#138
2609    'P 42/n c m':['(00g)','(00g)00ss',],
2610#139
2611    'I 4/m m m':['(00g)','(00g)s0s0','(00g)00ss','(00g)s00s',],
2612#140
2613    'I 4/m c m':['(00g)','(00g)s0s0','(00g)00ss','(00g)s00s',],
2614#141
2615    'I 41/a m d':['(00g)','(00g)s0s0',],
2616#142
2617    'I 41/a c d':['(00g)','(00g)s0s0',],
2618    #trigonal/rhombahedral - done & checked
2619#143
2620    'P 3':['(00g)','(00g)t','(1/31/3g)',],
2621#144
2622    'P 31':['(00g)','(1/31/3g)',],
2623#145
2624    'P 32':['(00g)','(1/31/3g)',],
2625#146
2626    'R 3':['(00g)','(00g)t',],
2627#147
2628    'P -3':['(00g)','(1/31/3g)',],
2629#148
2630    'R -3':['(00g)',],
2631#149
2632    'P 3 1 2':['(00g)','(00g)t00','(1/31/3g)',],
2633#150
2634    'P 3 2 1':['(00g)','(00g)t00',],
2635#151
2636    'P 31 1 2':['(00g)','(1/31/3g)',],
2637#152
2638    'P 31 2 1':['(00g)',],
2639#153
2640    'P 32 1 2':['(00g)','(1/31/3g)',],
2641#154
2642    'P 32 2 1':['(00g)',],
2643#155
2644    'R 3 2':['(00g)','(00g)t0',],
2645#156
2646    'P 3 m 1':['(00g)','(00g)0s0',],
2647#157
2648    'P 3 1 m':['(00g)','(00g)00s','(1/31/3g)','(1/31/3g)00s',],
2649#158
2650    'P 3 c 1':['(00g)',],
2651#159
2652    'P 3 1 c':['(00g)','(1/31/3g)',],
2653#160
2654    'R 3 m':['(00g)','(00g)0s',],
2655#161
2656    'R 3 c':['(00g)',],
2657#162
2658    'P -3 1 m':['(00g)','(00g)00s','(1/31/3g)','(1/31/3g)00s',],
2659#163
2660    'P -3 1 c':['(00g)','(1/31/3g)',],
2661#164
2662    'P -3 m 1':['(00g)','(00g)0s0',],
2663#165
2664    'P -3 c 1':['(00g)',],
2665#166       
2666    'R -3 m':['(00g)','(00g)0s',],
2667#167
2668    'R -3 c':['(00g)',],
2669    #hexagonal - done & checked
2670#168
2671    'P 6':['(00g)','(00g)h','(00g)t','(00g)s',],
2672#169
2673    'P 61':['(00g)',],
2674#170
2675    'P 65':['(00g)',],
2676#171
2677    'P 62':['(00g)','(00g)h',],
2678#172
2679    'P 64':['(00g)','(00g)h',],
2680#173
2681    'P 63':['(00g)','(00g)h',],
2682#174
2683    'P -6':['(00g)',],
2684#175
2685    'P 6/m':['(00g)','(00g)s0',],
2686#176
2687    'P 63/m':['(00g)',],
2688#177
2689    'P 6 2 2':['(00g)','(00g)h00','(00g)t00','(00g)s00',],
2690#178
2691    'P 61 2 2':['(00g)',],
2692#179
2693    'P 65 2 2':['(00g)',],
2694#180
2695    'P 62 2 2':['(00g)','(00g)h00',],
2696#181
2697    'P 64 2 2':['(00g)','(00g)h00',],
2698#182
2699    'P 63 2 2':['(00g)','(00g)h00',],
2700#183
2701    'P 6 m m':['(00g)','(00g)ss0','(00g)0ss','(00g)s0s',],
2702#184
2703    'P 6 c c':['(00g)','(00g)s0s',],
2704#185
2705    'P 63 c m':['(00g)','(00g)0ss',],
2706#186
2707    'P 63 m c':['(00g)','(00g)0ss',],
2708#187
2709    'P -6 m 2':['(00g)','(00g)0s0',],
2710#188
2711    'P -6 c 2':['(00g)',],
2712#189
2713    'P -6 2 m':['(00g)','(00g)00s',],
2714#190
2715    'P -6 2 c':['(00g)',],
2716#191
2717    'P 6/m m m':['(00g)','(00g)s0s0','(00g)00ss','(00g)s00s',],
2718#192
2719    'P 6/m c c':['(00g)','(00g)s00s',],
2720#193
2721    'P 63/m c m':['(00g)','(00g)00ss',],
2722#194
2723    'P 63/m m c':['(00g)','(00g)00ss'],
2724    }
2725
2726#'A few non-standard space groups for test use'
2727nonstandard_sglist = ('P 21 1 1','P 1 21 1','P 1 1 21','R 3 r','R 3 2 h', 
2728                      'R -3 r', 'R 3 2 r','R 3 m h', 'R 3 m r',
2729                      'R 3 c r','R -3 c r','R -3 m r',),
2730
2731#A list of orthorhombic space groups that were renamed in the 2002 Volume A,
2732# along with the pre-2002 name. The e designates a double glide-plane'''
2733sgequiv_2002_orthorhombic= (('A e m 2', 'A b m 2',),
2734                            ('A e a 2', 'A b a 2',),
2735                            ('C m c e', 'C m c a',),
2736                            ('C m m e', 'C m m a',),
2737                            ('C c c e', 'C c c a'),)
2738#Use the space groups types in this order to list the symbols in the
2739#order they are listed in the International Tables, vol. A'''
2740symtypelist = ('triclinic', 'monoclinic', 'orthorhombic', 'tetragonal', 
2741               'trigonal', 'hexagonal', 'cubic')
2742
2743# self-test materials follow. Requires files in directory testinp
2744selftestlist = []
2745'''Defines a list of self-tests'''
2746selftestquiet = True
2747def _ReportTest():
2748    'Report name and doc string of current routine when ``selftestquiet`` is False'
2749    if not selftestquiet:
2750        import inspect
2751        caller = inspect.stack()[1][3]
2752        doc = eval(caller).__doc__
2753        if doc is not None:
2754            print('testing '+__file__+' with '+caller+' ('+doc+')')
2755        else:
2756            print('testing '+__file__()+" with "+caller)
2757def test0():
2758    '''self-test #0: exercise MoveToUnitCell'''
2759    _ReportTest()
2760    msg = "MoveToUnitCell failed"
2761    assert (MoveToUnitCell([1,2,3]) == [0,0,0]).all, msg
2762    assert (MoveToUnitCell([2,-1,-2]) == [0,0,0]).all, msg
2763    assert abs(MoveToUnitCell(np.array([-.1]))[0]-0.9) < 1e-6, msg
2764    assert abs(MoveToUnitCell(np.array([.1]))[0]-0.1) < 1e-6, msg
2765selftestlist.append(test0)
2766
2767def test1():
2768    '''self-test #1: SpcGroup against previous results'''
2769    #'''self-test #1: SpcGroup and SGPrint against previous results'''
2770    _ReportTest()
2771    testdir = ospath.join(ospath.split(ospath.abspath( __file__ ))[0],'testinp')
2772    if ospath.exists(testdir):
2773        if testdir not in sys.path: sys.path.insert(0,testdir)
2774    import spctestinp
2775    def CompareSpcGroup(spc, referr, refdict, reflist): 
2776        'Compare output from GSASIIspc.SpcGroup with results from a previous run'
2777        # if an error is reported, the dictionary can be ignored
2778        msg0 = "CompareSpcGroup failed on space group %s" % spc
2779        result = SpcGroup(spc)
2780        if result[0] == referr and referr > 0: return True
2781        keys = result[1].keys()
2782        #print result[1]['SpGrp']
2783        #msg = msg0 + " in list lengths"
2784        #assert len(keys) == len(refdict.keys()), msg
2785        for key in refdict.keys():
2786            if key == 'SGOps' or  key == 'SGCen':
2787                msg = msg0 + (" in key %s length" % key)
2788                assert len(refdict[key]) == len(result[1][key]), msg
2789                for i in range(len(refdict[key])):
2790                    msg = msg0 + (" in key %s level 0" % key)
2791                    assert np.allclose(result[1][key][i][0],refdict[key][i][0]), msg
2792                    msg = msg0 + (" in key %s level 1" % key)
2793                    assert np.allclose(result[1][key][i][1],refdict[key][i][1]), msg
2794            else:
2795                msg = msg0 + (" in key %s" % key)
2796                assert result[1][key] == refdict[key], msg
2797        msg = msg0 + (" in key %s reflist" % key)
2798        #for (l1,l2) in zip(reflist, SGPrint(result[1])):
2799        #    assert l2.replace('\t','').replace(' ','') == l1.replace(' ',''), 'SGPrint ' +msg
2800        # for now disable SGPrint testing, output has changed
2801        #assert reflist == SGPrint(result[1]), 'SGPrint ' +msg
2802    for spc in spctestinp.SGdat:
2803        CompareSpcGroup(spc, 0, spctestinp.SGdat[spc], spctestinp.SGlist[spc] )
2804selftestlist.append(test1)
2805
2806def test2():
2807    '''self-test #2: SpcGroup against cctbx (sgtbx) computations'''
2808    _ReportTest()
2809    testdir = ospath.join(ospath.split(ospath.abspath( __file__ ))[0],'testinp')
2810    if ospath.exists(testdir):
2811        if testdir not in sys.path: sys.path.insert(0,testdir)
2812    import sgtbxtestinp
2813    def CompareWcctbx(spcname, cctbx_in, debug=0):
2814        'Compare output from GSASIIspc.SpcGroup with results from cctbx.sgtbx'
2815        cctbx = cctbx_in[:] # make copy so we don't delete from the original
2816        spc = (SpcGroup(spcname))[1]
2817        if debug: print spc['SpGrp']
2818        if debug: print spc['SGCen']
2819        latticetype = spcname.strip().upper()[0]
2820        # lattice type of R implies Hexagonal centering", fix the rhombohedral settings
2821        if latticetype == "R" and len(spc['SGCen']) == 1: latticetype = 'P'
2822        assert latticetype == spc['SGLatt'], "Failed: %s does not match Lattice: %s" % (spcname, spc['SGLatt'])
2823        onebar = [1]
2824        if spc['SGInv']: onebar.append(-1)
2825        for (op,off) in spc['SGOps']:
2826            for inv in onebar:
2827                for cen in spc['SGCen']:
2828                    noff = off + cen
2829                    noff = MoveToUnitCell(noff)
2830                    mult = tuple((op*inv).ravel().tolist())
2831                    if debug: print "\n%s: %s + %s" % (spcname,mult,noff)
2832                    for refop in cctbx:
2833                        if debug: print refop
2834                        # check the transform
2835                        if refop[:9] != mult: continue
2836                        if debug: print "mult match"
2837                        # check the translation
2838                        reftrans = list(refop[-3:])
2839                        reftrans = MoveToUnitCell(reftrans)
2840                        if all(abs(noff - reftrans) < 1.e-5):
2841                            cctbx.remove(refop)
2842                            break
2843                    else:
2844                        assert False, "failed on %s:\n\t %s + %s" % (spcname,mult,noff)
2845    for key in sgtbxtestinp.sgtbx:
2846        CompareWcctbx(key, sgtbxtestinp.sgtbx[key])
2847selftestlist.append(test2)
2848
2849def test3(): 
2850    '''self-test #3: exercise SytSym (includes GetOprPtrName, GenAtom, GetKNsym)
2851     for selected space groups against info in IT Volume A '''
2852    _ReportTest()
2853    def ExerciseSiteSym (spc, crdlist):
2854        'compare site symmetries and multiplicities for a specified space group'
2855        msg = "failed on site sym test for %s" % spc
2856        (E,S) = SpcGroup(spc)
2857        assert not E, msg
2858        for t in crdlist:
2859            symb, m = SytSym(t[0],S)
2860            if symb.strip() != t[2].strip() or m != t[1]:
2861                print spc,t[0],m,symb,t[2]
2862            assert m == t[1]
2863            #assert symb.strip() == t[2].strip()
2864
2865    ExerciseSiteSym('p 1',[
2866            ((0.13,0.22,0.31),1,'1'),
2867            ((0,0,0),1,'1'),
2868            ])
2869    ExerciseSiteSym('p -1',[
2870            ((0.13,0.22,0.31),2,'1'),
2871            ((0,0.5,0),1,'-1'),
2872            ])
2873    ExerciseSiteSym('C 2/c',[
2874            ((0.13,0.22,0.31),8,'1'),
2875            ((0.0,.31,0.25),4,'2(y)'),
2876            ((0.25,.25,0.5),4,'-1'),
2877            ((0,0.5,0),4,'-1'),
2878            ])
2879    ExerciseSiteSym('p 2 2 2',[
2880            ((0.13,0.22,0.31),4,'1'),
2881            ((0,0.5,.31),2,'2(z)'),
2882            ((0.5,.31,0.5),2,'2(y)'),
2883            ((.11,0,0),2,'2(x)'),
2884            ((0,0.5,0),1,'222'),
2885            ])
2886    ExerciseSiteSym('p 4/n',[
2887            ((0.13,0.22,0.31),8,'1'),
2888            ((0.25,0.75,.31),4,'2(z)'),
2889            ((0.5,0.5,0.5),4,'-1'),
2890            ((0,0.5,0),4,'-1'),
2891            ((0.25,0.25,.31),2,'4(001)'),
2892            ((0.25,.75,0.5),2,'-4(001)'),
2893            ((0.25,.75,0.0),2,'-4(001)'),
2894            ])
2895    ExerciseSiteSym('p 31 2 1',[
2896            ((0.13,0.22,0.31),6,'1'),
2897            ((0.13,0.0,0.833333333),3,'2(100)'),
2898            ((0.13,0.13,0.),3,'2(110)'),
2899            ])
2900    ExerciseSiteSym('R 3 c',[
2901            ((0.13,0.22,0.31),18,'1'),
2902            ((0.0,0.0,0.31),6,'3'),
2903            ])
2904    ExerciseSiteSym('R 3 c R',[
2905            ((0.13,0.22,0.31),6,'1'),
2906            ((0.31,0.31,0.31),2,'3(111)'),
2907            ])
2908    ExerciseSiteSym('P 63 m c',[
2909            ((0.13,0.22,0.31),12,'1'),
2910            ((0.11,0.22,0.31),6,'m(100)'),
2911            ((0.333333,0.6666667,0.31),2,'3m(100)'),
2912            ((0,0,0.31),2,'3m(100)'),
2913            ])
2914    ExerciseSiteSym('I a -3',[
2915            ((0.13,0.22,0.31),48,'1'),
2916            ((0.11,0,0.25),24,'2(x)'),
2917            ((0.11,0.11,0.11),16,'3(111)'),
2918            ((0,0,0),8,'-3(111)'),
2919            ])
2920selftestlist.append(test3)
2921
2922if __name__ == '__main__':
2923    # run self-tests
2924    selftestquiet = False
2925    for test in selftestlist:
2926        test()
2927    print "OK"
Note: See TracBrowser for help on using the repository browser.