source: trunk/GSASIIspc.py @ 2458

Last change on this file since 2458 was 2458, checked in by vondreele, 6 years ago

Mag space group work

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