source: trunk/GSASIIspc.py @ 1615

Last change on this file since 1615 was 1615, checked in by vondreele, 9 years ago

more work on incommensurate wave input to LS
fix FillAtomLookup? problem in G2restrGUI

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