source: trunk/GSASIIspc.py @ 2461

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

magnetic space group determination done

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