source: trunk/GSASIIspc.py @ 2466

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

implement user entered starting Marquardt lambda value (order of magnitude only)
finish magnetic space group symbol determination & magnetic moment flags - all checked against Litvin tables.

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