source: trunk/GSASIIspc.py @ 2546

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

cleanup of all GSASII main routines - remove unused variables, dead code, etc.

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