source: trunk/GSASIIspc.py @ 2473

Last change on this file since 2473 was 2473, checked in by vondreele, 5 years ago

work on magnetic structures - import from EXP, plotting, LS refine I/O, mag. form factors, etc.

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