source: trunk/GSASIIspc.py @ 2492

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

fix handling of Lande g factor
fix Mag structure factor calcs - now OK for all tests

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