source: trunk/GSASIIspc.py @ 2467

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

modify 2D strain Dcalc to be dmin+(dmax-dmin)/4. per Yan Gao
begin plot of magnetic moments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Author Revision URL Id
File size: 163.8 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-14 19:09:49 +0000 (Wed, 14 Sep 2016) $
12# $Author: vondreele $
13# $Revision: 2467 $
14# $URL: trunk/GSASIIspc.py $
15# $Id: GSASIIspc.py 2467 2016-09-14 19:09:49Z 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: 2467 $")
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   
1767################################################################################
1768#### Site symmetry tables
1769################################################################################
1770   
1771OprPtrName = {
1772    '-6643':[   2,' 1bar ', 1],'6479' :[  10,'  2z  ', 2],'-6479':[   9,'  mz  ', 3],
1773    '6481' :[   7,'  my  ', 4],'-6481':[   6,'  2y  ', 5],'6641' :[   4,'  mx  ', 6],
1774    '-6641':[   3,'  2x  ', 7],'6591' :[  28,' m+-0 ', 8],'-6591':[  27,' 2+-0 ', 9],
1775    '6531' :[  25,' m110 ',10],'-6531':[  24,' 2110 ',11],'6537' :[  61,'  4z  ',12],
1776    '-6537':[  62,' -4z  ',13],'975'  :[  68,' 3+++1',14],'6456' :[ 114,'  3z1 ',15],
1777    '-489' :[  73,' 3+-- ',16],'483'  :[  78,' 3-+- ',17],'-969' :[  83,' 3--+ ',18],
1778    '819'  :[  22,' m+0- ',19],'-819' :[  21,' 2+0- ',20],'2431' :[  16,' m0+- ',21],
1779    '-2431':[  15,' 20+- ',22],'-657' :[  19,' m101 ',23],'657'  :[  18,' 2101 ',24],
1780    '1943' :[  48,' -4x  ',25],'-1943':[  47,'  4x  ',26],'-2429':[  13,' m011 ',27],
1781    '2429' :[  12,' 2011 ',28],'639'  :[  55,' -4y  ',29],'-639' :[  54,'  4y  ',30],
1782    '-6484':[ 146,' 2010 ', 4],'6484' :[ 139,' m010 ', 5],'-6668':[ 145,' 2100 ', 6],
1783    '6668' :[ 138,' m100 ', 7],'-6454':[ 148,' 2120 ',18],'6454' :[ 141,' m120 ',19],
1784    '-6638':[ 149,' 2210 ',20],'6638' :[ 142,' m210 ',21],              #search ends here
1785    '2223' :[  68,' 3+++2',39],
1786    '6538' :[ 106,'  6z1 ',40],'-2169':[  83,' 3--+2',41],'2151' :[  73,' 3+--2',42],
1787    '2205' :[  79,'-3-+-2',43],'-2205':[  78,' 3-+-2',44],'489'  :[  74,'-3+--1',45],
1788    '801'  :[  53,'  4y1 ',46],'1945' :[  47,'  4x3 ',47],'-6585':[  62,' -4z3 ',48],
1789    '6585' :[  61,'  4z3 ',49],'6584' :[ 114,'  3z2 ',50],'6666' :[ 106,'  6z5 ',51],
1790    '6643' :[   1,' Iden ',52],'-801' :[  55,' -4y1 ',53],'-1945':[  48,' -4x3 ',54],
1791    '-6666':[ 105,' -6z5 ',55],'-6538':[ 105,' -6z1 ',56],'-2223':[  69,'-3+++2',57],
1792    '-975' :[  69,'-3+++1',58],'-6456':[ 113,' -3z1 ',59],'-483' :[  79,'-3-+-1',60],
1793    '969'  :[  84,'-3--+1',61],'-6584':[ 113,' -3z2 ',62],'2169' :[  84,'-3--+2',63],
1794    '-2151':[  74,'-3+--2',64],'0':[0,' ????',0]
1795    }
1796                                 
1797KNsym = {
1798    '0'         :'    1   ','1'         :'   -1   ','64'        :'    2(x)','32'        :'    m(x)',
1799    '97'        :'  2/m(x)','16'        :'    2(y)','8'         :'    m(y)','25'        :'  2/m(y)',
1800    '2'         :'    2(z)','4'         :'    m(z)','7'         :'  2/m(z)','134217728' :'   2(yz)',
1801    '67108864'  :'   m(yz)','201326593' :' 2/m(yz)','2097152'   :'  2(0+-)','1048576'   :'  m(0+-)',
1802    '3145729'   :'2/m(0+-)','8388608'   :'   2(xz)','4194304'   :'   m(xz)','12582913'  :' 2/m(xz)',
1803    '524288'    :'  2(+0-)','262144'    :'  m(+0-)','796433'    :'2/m(+0-)','1024'      :'   2(xy)',
1804    '512'       :'   m(xy)','1537'      :' 2/m(xy)','256'       :'  2(+-0)','128'       :'  m(+-0)',
1805    '385'       :'2/m(+-0)','76'        :'  mm2(x)','52'        :'  mm2(y)','42'        :'  mm2(z)',
1806    '135266336' :' mm2(yz)','69206048'  :'mm2(0+-)','8650760'   :' mm2(xz)','4718600'   :'mm2(+0-)',
1807    '1156'      :' mm2(xy)','772'       :'mm2(+-0)','82'        :'  222   ','136314944' :'  222(x)',
1808    '8912912'   :'  222(y)','1282'      :'  222(z)','127'       :'  mmm   ','204472417' :'  mmm(x)',
1809    '13369369'  :'  mmm(y)','1927'      :'  mmm(z)','33554496'  :'  4(100)','16777280'  :' -4(100)',
1810    '50331745'  :'4/m(100)','169869394' :'422(100)','84934738'  :'-42m 100','101711948' :'4mm(100)',
1811    '254804095' :'4/mmm100','536870928 ':'  4(010)','268435472' :' -4(010)','805306393' :'4/m (10)',
1812    '545783890' :'422(010)','272891986' :'-42m 010','541327412' :'4mm(010)','818675839' :'4/mmm010',
1813    '2050'      :'  4(001)','4098'      :' -4(001)','6151'      :'4/m(001)','3410'      :'422(001)',
1814    '4818'      :'-42m 001','2730'      :'4mm(001)','8191'      :'4/mmm001','8192'      :'  3(111)',
1815    '8193'      :' -3(111)','2629888'   :' 32(111)','1319040'   :' 3m(111)','3940737'   :'-3m(111)',
1816    '32768'     :'  3(+--)','32769'     :' -3(+--)','10519552'  :' 32(+--)','5276160'   :' 3m(+--)',
1817    '15762945'  :'-3m(+--)','65536'     :'  3(-+-)','65537'     :' -3(-+-)','134808576' :' 32(-+-)',
1818    '67437056'  :' 3m(-+-)','202180097' :'-3m(-+-)','131072'    :'  3(--+)','131073'    :' -3(--+)',
1819    '142737664' :' 32(--+)','71434368'  :' 3m(--+)','214040961' :'-3m(--+)','237650'    :'   23   ',
1820    '237695'    :'   m3   ','715894098' :'   432  ','358068946' :'  -43m  ','1073725439':'   m3m  ',
1821    '68157504'  :' mm2d100','4456464'   :' mm2d010','642'       :' mm2d001','153092172' :'-4m2 100',
1822    '277348404' :'-4m2 010','5418'      :'-4m2 001','1075726335':'  6/mmm ','1074414420':'-6m2 100',
1823    '1075070124':'-6m2 120','1075069650':'   6mm  ','1074414890':'   622  ','1073758215':'   6/m  ',
1824    '1073758212':'   -6   ','1073758210':'    6   ','1073759865':'-3m(100)','1075724673':'-3m(120)',
1825    '1073758800':' 3m(100)','1075069056':' 3m(120)','1073759272':' 32(100)','1074413824':' 32(120)',
1826    '1073758209':'   -3   ','1073758208':'    3   ','1074135143':'mmm(100)','1075314719':'mmm(010)',
1827    '1073743751':'mmm(110)','1074004034':' mm2z100','1074790418':' mm2z010','1073742466':' mm2z110',
1828    '1074004004':'mm2(100)','1074790412':'mm2(010)','1073742980':'mm2(110)','1073872964':'mm2(120)',
1829    '1074266132':'mm2(210)','1073742596':'mm2(+-0)','1073872930':'222(100)','1074266122':'222(010)',
1830    '1073743106':'222(110)','1073741831':'2/m(001)','1073741921':'2/m(100)','1073741849':'2/m(010)',
1831    '1073743361':'2/m(110)','1074135041':'2/m(120)','1075314689':'2/m(210)','1073742209':'2/m(+-0)',
1832    '1073741828':' m(001) ','1073741888':' m(100) ','1073741840':' m(010) ','1073742336':' m(110) ',
1833    '1074003968':' m(120) ','1074790400':' m(210) ','1073741952':' m(+-0) ','1073741826':' 2(001) ',
1834    '1073741856':' 2(100) ','1073741832':' 2(010) ','1073742848':' 2(110) ','1073872896':' 2(120) ',
1835    '1074266112':' 2(210) ','1073742080':' 2(+-0) ','1073741825':'   -1   '
1836    }
1837
1838NXUPQsym = {
1839    '    1   ':(28,29,28,28),'   -1   ':( 1,29,28, 0),'    2(x)':(12,18,12,25),'    m(x)':(25,18,12,25),
1840    '  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),
1841    '    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),
1842    '   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),
1843    '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),
1844    '  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),
1845    '   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),
1846    '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),
1847    ' mm2(yz)':(10,13, 0,-1),'mm2(0+-)':(11,13, 0,-1),' mm2(xz)':( 8,12, 0,-1),'mm2(+0-)':( 9,12, 0,-1),
1848    ' mm2(xy)':( 6,11, 0,-1),'mm2(+-0)':( 7,11, 0,-1),'  222   ':( 1,10, 0,-1),'  222(x)':( 1,13, 0,-1),
1849    '  222(y)':( 1,12, 0,-1),'  222(z)':( 1,11, 0,-1),'  mmm   ':( 1,10, 0,-1),'  mmm(x)':( 1,13, 0,-1),
1850    '  mmm(y)':( 1,12, 0,-1),'  mmm(z)':( 1,11, 0,-1),'  4(100)':(12, 4,12, 0),' -4(100)':( 1, 4,12, 0),
1851    '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),
1852    '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),
1853    '422(010)':( 1, 3, 0,-1),'-42m 010':( 1, 3, 0,-1),'4mm(010)':(13, 3, 0,-1),'4/mmm010':(1, 3, 0,-1,),
1854    '  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),
1855    '-42m 001':( 1, 2, 0,-1),'4mm(001)':(14, 2, 0,-1),'4/mmm001':( 1, 2, 0,-1),'  3(111)':( 2, 5, 2, 0),
1856    ' -3(111)':( 1, 5, 2, 0),' 32(111)':( 1, 5, 0, 2),' 3m(111)':( 2, 5, 0, 2),'-3m(111)':( 1, 5, 0,-1),
1857    '  3(+--)':( 5, 8, 5, 0),' -3(+--)':( 1, 8, 5, 0),' 32(+--)':( 1, 8, 0, 5),' 3m(+--)':( 5, 8, 0, 5),
1858    '-3m(+--)':( 1, 8, 0,-1),'  3(-+-)':( 4, 7, 4, 0),' -3(-+-)':( 1, 7, 4, 0),' 32(-+-)':( 1, 7, 0, 4),
1859    ' 3m(-+-)':( 4, 7, 0, 4),'-3m(-+-)':( 1, 7, 0,-1),'  3(--+)':( 3, 6, 3, 0),' -3(--+)':( 1, 6, 3, 0),
1860    ' 32(--+)':( 1, 6, 0, 3),' 3m(--+)':( 3, 6, 0, 3),'-3m(--+)':( 1, 6, 0,-1),'   23   ':( 1, 1, 0, 0),
1861    '   m3   ':( 1, 1, 0, 0),'   432  ':( 1, 1, 0, 0),'  -43m  ':( 1, 1, 0, 0),'   m3m  ':( 1, 1, 0, 0),
1862    ' mm2d100':(12,13, 0,-1),' mm2d010':(13,12, 0,-1),' mm2d001':(14,11, 0,-1),'-4m2 100':( 1, 4, 0,-1),
1863    '-4m2 010':( 1, 3, 0,-1),'-4m2 001':( 1, 2, 0,-1),'  6/mmm ':( 1, 9, 0,-1),'-6m2 100':( 1, 9, 0,-1),
1864    '-6m2 120':( 1, 9, 0,-1),'   6mm  ':(14, 9, 0,-1),'   622  ':( 1, 9, 0,-1),'   6/m  ':( 1, 9,14,-1),
1865    '   -6   ':( 1, 9,14, 0),'    6   ':(14, 9,14, 0),'-3m(100)':( 1, 9, 0,-1),'-3m(120)':( 1, 9, 0,-1),
1866    ' 3m(100)':(14, 9, 0,14),' 3m(120)':(14, 9, 0,14),' 32(100)':( 1, 9, 0,14),' 32(120)':( 1, 9, 0,14),
1867    '   -3   ':( 1, 9,14, 0),'    3   ':(14, 9,14, 0),'mmm(100)':( 1,14, 0,-1),'mmm(010)':( 1,15, 0,-1),
1868    'mmm(110)':( 1,11, 0,-1),' mm2z100':(14,14, 0,-1),' mm2z010':(14,15, 0,-1),' mm2z110':(14,11, 0,-1),
1869    'mm2(100)':(12,14, 0,-1),'mm2(010)':(13,15, 0,-1),'mm2(110)':( 6,11, 0,-1),'mm2(120)':(15,14, 0,-1),
1870    'mm2(210)':(16,15, 0,-1),'mm2(+-0)':( 7,11, 0,-1),'222(100)':( 1,14, 0,-1),'222(010)':( 1,15, 0,-1),
1871    '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),
1872    '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),
1873    ' m(001) ':(23,16,14,23),' m(100) ':(26,25,12,26),' m(010) ':(27,28,13,27),' m(110) ':(18,19, 6,18),
1874    ' m(120) ':(24,27,15,24),' m(210) ':(25,26,16,25),' m(+-0) ':(17,20, 7,17),' 2(001) ':(14,16,14,23),
1875    ' 2(100) ':(12,25,12,26),' 2(010) ':(13,28,13,27),' 2(110) ':( 6,19, 6,18),' 2(120) ':(15,27,15,24),
1876    ' 2(210) ':(16,26,16,25),' 2(+-0) ':( 7,20, 7,17),'   -1   ':( 1,29,28, 0)
1877    }
1878       
1879CSxinel = [[],      # 0th empty - indices are Fortran style
1880    [[0,0,0],[ 0.0, 0.0, 0.0]],      #1  0  0  0
1881    [[1,1,1],[ 1.0, 1.0, 1.0]],      #2  X  X  X
1882    [[1,1,1],[ 1.0, 1.0,-1.0]],      #3  X  X -X
1883    [[1,1,1],[ 1.0,-1.0, 1.0]],      #4  X -X  X
1884    [[1,1,1],[ 1.0,-1.0,-1.0]],      #5 -X  X  X
1885    [[1,1,0],[ 1.0, 1.0, 0.0]],      #6  X  X  0
1886    [[1,1,0],[ 1.0,-1.0, 0.0]],      #7  X -X  0
1887    [[1,0,1],[ 1.0, 0.0, 1.0]],      #8  X  0  X
1888    [[1,0,1],[ 1.0, 0.0,-1.0]],      #9  X  0 -X
1889    [[0,1,1],[ 0.0, 1.0, 1.0]],      #10  0  Y  Y
1890    [[0,1,1],[ 0.0, 1.0,-1.0]],      #11 0  Y -Y
1891    [[1,0,0],[ 1.0, 0.0, 0.0]],      #12  X  0  0
1892    [[0,1,0],[ 0.0, 1.0, 0.0]],      #13  0  Y  0
1893    [[0,0,1],[ 0.0, 0.0, 1.0]],      #14  0  0  Z
1894    [[1,1,0],[ 1.0, 2.0, 0.0]],      #15  X 2X  0
1895    [[1,1,0],[ 2.0, 1.0, 0.0]],      #16 2X  X  0
1896    [[1,1,2],[ 1.0, 1.0, 1.0]],      #17  X  X  Z
1897    [[1,1,2],[ 1.0,-1.0, 1.0]],      #18  X -X  Z
1898    [[1,2,1],[ 1.0, 1.0, 1.0]],      #19  X  Y  X
1899    [[1,2,1],[ 1.0, 1.0,-1.0]],      #20  X  Y -X
1900    [[1,2,2],[ 1.0, 1.0, 1.0]],      #21  X  Y  Y
1901    [[1,2,2],[ 1.0, 1.0,-1.0]],      #22  X  Y -Y
1902    [[1,2,0],[ 1.0, 1.0, 0.0]],      #23  X  Y  0
1903    [[1,0,2],[ 1.0, 0.0, 1.0]],      #24  X  0  Z
1904    [[0,1,2],[ 0.0, 1.0, 1.0]],      #25  0  Y  Z
1905    [[1,1,2],[ 1.0, 2.0, 1.0]],      #26  X 2X  Z
1906    [[1,1,2],[ 2.0, 1.0, 1.0]],      #27 2X  X  Z
1907    [[1,2,3],[ 1.0, 1.0, 1.0]],      #28  X  Y  Z
1908    ]
1909
1910CSuinel = [[],      # 0th empty - indices are Fortran style
1911    [[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
1912    [[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
1913    [[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
1914    [[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
1915    [[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
1916    [[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
1917    [[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
1918    [[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
1919    [[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
1920    [[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
1921    [[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
1922    [[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
1923    [[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
1924    [[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
1925    [[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
1926    [[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
1927    [[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
1928    [[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
1929    [[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
1930    [[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
1931    [[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
1932    [[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
1933    [[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
1934    [[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
1935    [[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
1936    [[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
1937    [[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
1938    [[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
1939    [[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
1940    ]
1941   
1942################################################################################
1943#### Site symmetry routines
1944################################################################################
1945   
1946def GetOprPtrName(key):
1947    'Needs a doc string'
1948    return OprPtrName[key]
1949
1950def GetKNsym(key):
1951    'Needs a doc string'
1952    return KNsym[key]       
1953
1954def GetNXUPQsym(siteSym):
1955    '''       
1956    The codes XUPQ are for lookup of symmetry constraints for position(X), thermal parm(U) & magnetic moments (P & Q)
1957    '''
1958    return NXUPQsym[siteSym]
1959
1960def GetCSxinel(siteSym): 
1961    "returns Xyz terms, multipliers, GUI flags"
1962    indx = GetNXUPQsym(siteSym)
1963    return CSxinel[indx[0]]
1964   
1965def GetCSuinel(siteSym):
1966    "returns Uij terms, multipliers, GUI flags & Uiso2Uij multipliers"
1967    indx = GetNXUPQsym(siteSym)
1968    return CSuinel[indx[1]]
1969   
1970def GetCSpqinel(siteSym): 
1971    "returns Mxyz terms, multipliers, GUI flags"
1972    indx = GetNXUPQsym(siteSym)
1973    return CSxinel[indx[2]],CSxinel[indx[3]]
1974   
1975def getTauT(tau,sop,ssop,XYZ):
1976    ssopinv = nl.inv(ssop[0])
1977    mst = ssopinv[3][:3]
1978    epsinv = ssopinv[3][3]
1979    sdet = nl.det(sop[0])
1980    ssdet = nl.det(ssop[0])
1981    dtau = mst*(XYZ-sop[1])-epsinv*ssop[1][3]
1982    dT = 1.0
1983    if np.any(dtau%.5):
1984        dT = np.tan(np.pi*np.sum(dtau%.5))
1985    tauT = np.inner(mst,XYZ-sop[1])+epsinv*(tau-ssop[1][3])
1986    return sdet,ssdet,dtau,dT,tauT
1987   
1988def OpsfromStringOps(A,SGData,SSGData):
1989    SGOps = SGData['SGOps']
1990    SSGOps = SSGData['SSGOps']
1991    Ax = A.split('+')
1992    Ax[0] = int(Ax[0])
1993    iC = 1
1994    if Ax[0] < 0:
1995        iC = -1
1996    Ax[0] = abs(Ax[0])
1997    nA = Ax[0]%100-1
1998    return SGOps[nA],SSGOps[nA],iC
1999   
2000def GetSSfxuinel(waveType,nH,XYZ,SGData,SSGData,debug=False):
2001   
2002    def orderParms(CSI):
2003        parms = [0,]
2004        for csi in CSI:
2005            for i in [0,1,2]:
2006                if csi[i] not in parms:
2007                    parms.append(csi[i])
2008        for csi in CSI:
2009            for i in [0,1,2]:
2010                csi[i] = parms.index(csi[i])
2011        return CSI
2012       
2013    def fracCrenel(tau,Toff,Twid):
2014        Tau = (tau-Toff[:,np.newaxis])%1.
2015        A = np.where(Tau<Twid[:,np.newaxis],1.,0.)
2016        return A
2017       
2018    def fracFourier(tau,nH,fsin,fcos):
2019        SA = np.sin(2.*nH*np.pi*tau)
2020        CB = np.cos(2.*nH*np.pi*tau)
2021        A = SA[np.newaxis,np.newaxis,:]*fsin[:,:,np.newaxis]
2022        B = CB[np.newaxis,np.newaxis,:]*fcos[:,:,np.newaxis]
2023        return A+B
2024       
2025    def posFourier(tau,nH,psin,pcos):
2026        SA = np.sin(2*nH*np.pi*tau)
2027        CB = np.cos(2*nH*np.pi*tau)
2028        A = SA[np.newaxis,np.newaxis,:]*psin[:,:,np.newaxis]
2029        B = CB[np.newaxis,np.newaxis,:]*pcos[:,:,np.newaxis]
2030        return A+B   
2031
2032    def posSawtooth(tau,Toff,slopes):
2033        Tau = (tau-Toff)%1.
2034        A = slopes[:,np.newaxis]*Tau
2035        return A
2036   
2037    def posZigZag(tau,Tmm,XYZmax):
2038        DT = Tmm[1]-Tmm[0]
2039        slopeUp = 2.*XYZmax/DT
2040        slopeDn = 2.*XYZmax/(1.-DT)
2041        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])
2042        return A
2043
2044    def posBlock(tau,Tmm,XYZmax):
2045        A = np.array([np.where(Tmm[0] < t <= Tmm[1],XYZmax,-XYZmax) for t in tau])
2046        return A
2047       
2048    def DoFrac():
2049        delt2 = np.eye(2)*0.001
2050        FSC = np.ones(2,dtype='i')
2051        VFSC = np.ones(2)
2052        CSI = [np.zeros((2),dtype='i'),np.zeros(2)]
2053        if 'Crenel' in waveType:
2054            dF = np.zeros_like(tau)
2055        else:
2056            dF = fracFourier(tau,nH,delt2[:1],delt2[1:]).squeeze()
2057        dFT = np.zeros_like(dF)
2058        dFTP = []
2059        for i in SdIndx:
2060            sop = Sop[i]
2061            ssop = SSop[i]           
2062            sdet,ssdet,dtau,dT,tauT = getTauT(tau,sop,ssop,XYZ)
2063            fsc = np.ones(2,dtype='i')
2064            if 'Crenel' in waveType:
2065                dFT = np.zeros_like(tau)
2066                fsc = [1,1]
2067            else:   #Fourier
2068                dFT = fracFourier(tauT,nH,delt2[:1],delt2[1:]).squeeze()
2069                dFT = nl.det(sop[0])*dFT
2070                dFT = dFT[:,np.argsort(tauT)]
2071                dFT[0] *= ssdet
2072                dFT[1] *= sdet
2073                dFTP.append(dFT)
2074           
2075                if np.any(dtau%.5) and ('1/2' in SSGData['modSymb'] or '1' in SSGData['modSymb']):
2076                    fsc = [1,1]
2077                    CSI = [[[1,0],[1,0]],[[1.,0.],[1/dT,0.]]]
2078                    FSC = np.zeros(2,dtype='i')
2079                    return CSI,dF,dFTP
2080                else:
2081                    for i in range(2):
2082                        if np.allclose(dF[i,:],dFT[i,:],atol=1.e-6):
2083                            fsc[i] = 1
2084                        else:
2085                            fsc[i] = 0
2086                    FSC &= fsc
2087                    if debug: print SSMT2text(ssop).replace(' ',''),sdet,ssdet,epsinv,fsc
2088        n = -1
2089        for i,F in enumerate(FSC):
2090            if F:
2091                n += 1
2092                CSI[0][i] = n+1
2093                CSI[1][i] = 1.0
2094       
2095        return CSI,dF,dFTP
2096       
2097    def DoXYZ():
2098        delt4 = np.ones(4)*0.001
2099        delt5 = np.ones(5)*0.001
2100        delt6 = np.eye(6)*0.001
2101        if 'Fourier' in waveType:
2102            dX = posFourier(tau,nH,delt6[:3],delt6[3:]) #+np.array(XYZ)[:,np.newaxis,np.newaxis]
2103              #3x6x12 modulated position array (X,Spos,tau)& force positive
2104            CSI = [np.zeros((6,3),dtype='i'),np.zeros((6,3))]
2105        elif waveType == 'Sawtooth':
2106            dX = posSawtooth(tau,delt4[0],delt4[1:])
2107            CSI = [np.array([[1,0,0],[2,0,0],[3,0,0],[4,0,0]]),
2108                np.array([[1.0,.0,.0],[1.0,.0,.0],[1.0,.0,.0],[1.0,.0,.0]])]
2109        elif waveType in ['ZigZag','Block']:
2110            if waveType == 'ZigZag':
2111                dX = posZigZag(tau,delt5[:2],delt5[2:])
2112            else:
2113                dX = posBlock(tau,delt5[:2],delt5[2:])
2114            CSI = [np.array([[1,0,0],[2,0,0],[3,0,0],[4,0,0],[5,0,0]]),
2115                np.array([[1.0,.0,.0],[1.0,.0,.0],[1.0,.0,.0],[1.0,.0,.0],[1.0,.0,.0]])]
2116        XSC = np.ones(6,dtype='i')
2117        dXTP = []
2118        for i in SdIndx:
2119            sop = Sop[i]
2120            ssop = SSop[i]
2121            sdet,ssdet,dtau,dT,tauT = getTauT(tau,sop,ssop,XYZ)
2122            xsc = np.ones(6,dtype='i')
2123            if 'Fourier' in waveType:
2124                dXT = posFourier(np.sort(tauT),nH,delt6[:3],delt6[3:])   #+np.array(XYZ)[:,np.newaxis,np.newaxis]
2125            elif waveType == 'Sawtooth':
2126                dXT = posSawtooth(tauT,delt4[0],delt4[1:])+np.array(XYZ)[:,np.newaxis,np.newaxis]
2127            elif waveType == 'ZigZag':
2128                dXT = posZigZag(tauT,delt5[:2],delt5[2:])+np.array(XYZ)[:,np.newaxis,np.newaxis]
2129            elif waveType == 'Block':
2130                dXT = posBlock(tauT,delt5[:2],delt5[2:])+np.array(XYZ)[:,np.newaxis,np.newaxis]
2131            dXT = np.inner(sop[0],dXT.T)    # X modulations array(3x6x49) -> array(3x49x6)
2132            dXT = np.swapaxes(dXT,1,2)      # back to array(3x6x49)
2133            dXT[:,:3,:] *= (ssdet*sdet)            # modify the sin component
2134            dXTP.append(dXT)
2135            if waveType == 'Fourier':
2136                for i in range(3):
2137                    if not np.allclose(dX[i,i,:],dXT[i,i,:]):
2138                        xsc[i] = 0
2139                    if not np.allclose(dX[i,i+3,:],dXT[i,i+3,:]):
2140                        xsc[i+3] = 0
2141                if np.any(dtau%.5) and ('1/2' in SSGData['modSymb'] or '1' in SSGData['modSymb']):
2142                    xsc[3:6] = 0
2143                    CSI = [[[1,0,0],[2,0,0],[3,0,0], [1,0,0],[2,0,0],[3,0,0]],
2144                        [[1.,0.,0.],[1.,0.,0.],[1.,0.,0.], [1.,0.,0.],[1.,0.,0.],[1.,0.,0.]]]                   
2145                    if '(x)' in siteSym:
2146                        CSI[1][3:] = [1./dT,0.,0.],[-dT,0.,0.],[-dT,0.,0.]
2147                        if 'm' in siteSym and len(SdIndx) == 1:
2148                            CSI[1][3:] = [-dT,0.,0.],[1./dT,0.,0.],[1./dT,0.,0.]
2149                    elif '(y)' in siteSym:
2150                        CSI[1][3:] = [-dT,0.,0.],[1./dT,0.,0.],[-dT,0.,0.]
2151                        if 'm' in siteSym and len(SdIndx) == 1:
2152                            CSI[1][3:] = [1./dT,0.,0.],[-dT,0.,0.],[1./dT,0.,0.]
2153                    elif '(z)' in siteSym:
2154                        CSI[1][3:] = [-dT,0.,0.],[-dT,0.,0.],[1./dT,0.,0.]
2155                        if 'm' in siteSym and len(SdIndx) == 1:
2156                            CSI[1][3:] = [1./dT,0.,0.],[1./dT,0.,0.],[-dT,0.,0.]
2157                if '4/mmm' in laue:
2158                    if np.any(dtau%.5) and '1/2' in SSGData['modSymb']:
2159                        if '(xy)' in siteSym:
2160                            CSI[0] = [[1,0,0],[1,0,0],[2,0,0], [1,0,0],[1,0,0],[2,0,0]]
2161                            CSI[1][3:] = [[1./dT,0.,0.],[1./dT,0.,0.],[-dT,0.,0.]]
2162                    if '(xy)' in siteSym or '(+-0)' in siteSym:
2163                        mul = 1
2164                        if '(+-0)' in siteSym:
2165                            mul = -1
2166                        if np.allclose(dX[0,0,:],dXT[1,0,:]):
2167                            CSI[0][3:5] = [[11,0,0],[11,0,0]]
2168                            CSI[1][3:5] = [[1.,0,0],[mul,0,0]]
2169                            xsc[3:5] = 0
2170                        if np.allclose(dX[0,3,:],dXT[0,4,:]):
2171                            CSI[0][:2] = [[12,0,0],[12,0,0]]
2172                            CSI[1][:2] = [[1.,0,0],[mul,0,0]]
2173                            xsc[:2] = 0
2174            XSC &= xsc
2175            if debug: print SSMT2text(ssop).replace(' ',''),sdet,ssdet,epsinv,xsc
2176        if waveType == 'Fourier':
2177            n = -1
2178            if debug: print XSC
2179            for i,X in enumerate(XSC):
2180                if X:
2181                    n += 1
2182                    CSI[0][i][0] = n+1
2183                    CSI[1][i][0] = 1.0
2184       
2185        return CSI,dX,dXTP
2186       
2187    def DoUij():
2188        tau = np.linspace(0,1,49,True)
2189        delt12 = np.eye(12)*0.0001
2190        dU = posFourier(tau,nH,delt12[:6],delt12[6:])                  #Uij modulations - 6x12x12 array
2191        CSI = [np.zeros((12,3),dtype='i'),np.zeros((12,3))]
2192        USC = np.ones(12,dtype='i')
2193        dUTP = []
2194        for i in SdIndx:
2195            sop = Sop[i]
2196            ssop = SSop[i]
2197            sdet,ssdet,dtau,dT,tauT = getTauT(tau,sop,ssop,XYZ)
2198            usc = np.ones(12,dtype='i')
2199            dUT = posFourier(tauT,nH,delt12[:6],delt12[6:])                  #Uij modulations - 6x12x49 array
2200            dUijT = np.rollaxis(np.rollaxis(np.array(Uij2U(dUT)),3),3)    #convert dUT to 12x49x3x3
2201            dUijT = np.rollaxis(np.inner(np.inner(sop[0],dUijT),sop[0].T),3) #transform by sop - 3x3x12x49
2202            dUT = np.array(U2Uij(dUijT))    #convert to 6x12x49
2203            dUT = dUT[:,:,np.argsort(tauT)]
2204            dUT[:,:6,:] *=(ssdet*sdet)
2205            dUTP.append(dUT)
2206            if np.any(dtau%.5) and ('1/2' in SSGData['modSymb'] or '1' in SSGData['modSymb']):
2207                CSI = [[[1,0,0],[2,0,0],[3,0,0],[4,0,0],[5,0,0],[6,0,0], 
2208                [1,0,0],[2,0,0],[3,0,0],[4,0,0],[5,0,0],[6,0,0]],
2209                [[1.,0.,0.],[1.,0.,0.],[1.,0.,0.], [1.,0.,0.],[1.,0.,0.],[1.,0.,0.],
2210                [1./dT,0.,0.],[1./dT,0.,0.],[1./dT,0.,0.], [1.,0.,0.],[1.,0.,0.],[1.,0.,0.]]]
2211                if 'mm2(x)' in siteSym:
2212                    CSI[1][9:] = [0.,0.,0.],[-dT,0.,0.],[0.,0.,0.]
2213                    USC = [1,1,1,0,1,0,1,1,1,0,1,0]
2214                elif '(xy)' in siteSym:
2215                    CSI[0] = [[1,0,0],[1,0,0],[2,0,0],[3,0,0],[4,0,0],[4,0,0],
2216                        [1,0,0],[1,0,0],[2,0,0],[3,0,0],[4,0,0],[4,0,0]]
2217                    CSI[1][9:] = [[1./dT,0.,0.],[-dT,0.,0.],[-dT,0.,0.]]
2218                    USC = [1,1,1,1,1,1,1,1,1,1,1,1]                             
2219                elif '(x)' in siteSym:
2220                    CSI[1][9:] = [-dT,0.,0.],[-dT,0.,0.],[1./dT,0.,0.]
2221                elif '(y)' in siteSym:
2222                    CSI[1][9:] = [-dT,0.,0.],[1./dT,0.,0.],[-dT,0.,0.]
2223                elif '(z)' in siteSym:
2224                    CSI[1][9:] = [1./dT,0.,0.],[-dT,0.,0.],[-dT,0.,0.]
2225                for i in range(6):
2226                    if not USC[i]:
2227                        CSI[0][i] = [0,0,0]
2228                        CSI[1][i] = [0.,0.,0.]
2229                        CSI[0][i+6] = [0,0,0]
2230                        CSI[1][i+6] = [0.,0.,0.]
2231            else:                       
2232                for i in range(6):
2233                    if not np.allclose(dU[i,i,:],dUT[i,i,:]):  #sin part
2234                        usc[i] = 0
2235                    if not np.allclose(dU[i,i+6,:],dUT[i,i+6,:]):   #cos part
2236                        usc[i+6] = 0
2237                if np.any(dUT[1,0,:]):
2238                    if '4/m' in siteSym:
2239                        CSI[0][6:8] = [[12,0,0],[12,0,0]]
2240                        if ssop[1][3]:
2241                            CSI[1][6:8] = [[1.,0.,0.],[-1.,0.,0.]]
2242                            usc[9] = 1
2243                        else:
2244                            CSI[1][6:8] = [[1.,0.,0.],[1.,0.,0.]]
2245                            usc[9] = 0
2246                    elif '4' in siteSym:
2247                        CSI[0][6:8] = [[12,0,0],[12,0,0]]
2248                        CSI[0][:2] = [[11,0,0],[11,0,0]]
2249                        if ssop[1][3]:
2250                            CSI[1][:2] = [[1.,0.,0.],[-1.,0.,0.]]
2251                            CSI[1][6:8] = [[1.,0.,0.],[-1.,0.,0.]]
2252                            usc[2] = 0
2253                            usc[8] = 0
2254                            usc[3] = 1
2255                            usc[9] = 1
2256                        else:
2257                            CSI[1][:2] = [[1.,0.,0.],[1.,0.,0.]]
2258                            CSI[1][6:8] = [[1.,0.,0.],[1.,0.,0.]]
2259                            usc[2] = 1
2260                            usc[8] = 1
2261                            usc[3] = 0               
2262                            usc[9] = 0
2263                    elif 'xy' in siteSym or '+-0' in siteSym:
2264                        if np.allclose(dU[0,0,:],dUT[0,1,:]*sdet):
2265                            CSI[0][4:6] = [[12,0,0],[12,0,0]]
2266                            CSI[0][6:8] = [[11,0,0],[11,0,0]]
2267                            CSI[1][4:6] = [[1.,0.,0.],[sdet,0.,0.]]
2268                            CSI[1][6:8] = [[1.,0.,0.],[sdet,0.,0.]]
2269                            usc[4:6] = 0
2270                            usc[6:8] = 0
2271                       
2272                if debug: print SSMT2text(ssop).replace(' ',''),sdet,ssdet,epsinv,usc
2273            USC &= usc
2274        if debug: print USC
2275        if not np.any(dtau%.5):
2276            n = -1
2277            for i,U in enumerate(USC):
2278                if U:
2279                    n += 1
2280                    CSI[0][i][0] = n+1
2281                    CSI[1][i][0] = 1.0
2282
2283        return CSI,dU,dUTP
2284       
2285    if debug: print 'super space group: ',SSGData['SSpGrp']
2286    CSI = {'Sfrac':[[[1,0],[2,0]],[[1.,0.],[1.,0.]]],
2287        'Spos':[[[1,0,0],[2,0,0],[3,0,0], [4,0,0],[5,0,0],[6,0,0]],
2288            [[1.,0.,0.],[1.,0.,0.],[1.,0.,0.], [1.,0.,0.],[1.,0.,0.],[1.,0.,0.]]],    #sin & cos
2289        'Sadp':[[[1,0,0],[2,0,0],[3,0,0],[4,0,0],[5,0,0],[6,0,0], 
2290            [7,0,0],[8,0,0],[9,0,0],[10,0,0],[11,0,0],[12,0,0]],
2291            [[1.,0.,0.],[1.,0.,0.],[1.,0.,0.], [1.,0.,0.],[1.,0.,0.],[1.,0.,0.],
2292            [1.,0.,0.],[1.,0.,0.],[1.,0.,0.], [1.,0.,0.],[1.,0.,0.],[1.,0.,0.]]],
2293        'Smag':[[[1,0,0],[2,0,0],[3,0,0], [4,0,0],[5,0,0],[6,0,0]],
2294            [[1.,0.,0.],[1.,0.,0.],[1.,0.,0.], [1.,0.,0.],[1.,0.,0.],[1.,0.,0.]]],}
2295    xyz = np.array(XYZ)%1.
2296    xyzt = np.array(XYZ+[0,])%1.
2297    SGOps = copy.deepcopy(SGData['SGOps'])
2298    laue = SGData['SGLaue']
2299    siteSym = SytSym(XYZ,SGData)[0].strip()
2300    if debug: print 'siteSym: ',siteSym
2301    if siteSym == '1':   #"1" site symmetry
2302        if debug:
2303            return CSI,None,None,None,None
2304        else:
2305            return CSI
2306    elif siteSym == '-1':   #"-1" site symmetry
2307        CSI['Sfrac'][0] = [[1,0],[0,0]]
2308        CSI['Spos'][0] = [[1,0,0],[2,0,0],[3,0,0], [0,0,0],[0,0,0],[0,0,0]]
2309        CSI['Sadp'][0] = [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0], 
2310        [1,0,0],[2,0,0],[3,0,0],[4,0,0],[5,0,0],[6,0,0]]
2311        if debug:
2312            return CSI,None,None,None,None
2313        else:
2314            return CSI
2315    SSGOps = copy.deepcopy(SSGData['SSGOps'])
2316    #expand ops to include inversions if any
2317    if SGData['SGInv']:
2318        for op,sop in zip(SGData['SGOps'],SSGData['SSGOps']):
2319            SGOps.append([-op[0],-op[1]%1.])
2320            SSGOps.append([-sop[0],-sop[1]%1.])
2321    #build set of sym ops around special position       
2322    SSop = []
2323    Sop = []
2324    Sdtau = []
2325    for iop,Op in enumerate(SGOps):         
2326        nxyz = (np.inner(Op[0],xyz)+Op[1])%1.
2327        if np.allclose(xyz,nxyz,1.e-4) and iop and MT2text(Op).replace(' ','') != '-X,-Y,-Z':
2328            SSop.append(SSGOps[iop])
2329            Sop.append(SGOps[iop])
2330            ssopinv = nl.inv(SSGOps[iop][0])
2331            mst = ssopinv[3][:3]
2332            epsinv = ssopinv[3][3]
2333            Sdtau.append(np.sum(mst*(XYZ-SGOps[iop][1])-epsinv*SSGOps[iop][1][3]))
2334    SdIndx = np.argsort(np.array(Sdtau))     # just to do in sensible order
2335    if debug: print 'special pos super operators: ',[SSMT2text(ss).replace(' ','') for ss in SSop]
2336    #setup displacement arrays
2337    tau = np.linspace(-1,1,49,True)
2338    #make modulation arrays - one parameter at a time
2339    #site fractions
2340    CSI['Sfrac'],dF,dFTP = DoFrac()
2341    #positions
2342    CSI['Spos'],dX,dXTP = DoXYZ()       
2343    #anisotropic thermal motion
2344    CSI['Sadp'],dU,dUTP = DoUij()
2345    CSI['Spos'][0] = orderParms(CSI['Spos'][0])
2346    CSI['Sadp'][0] = orderParms(CSI['Sadp'][0])           
2347    if debug:
2348        return CSI,tau,[dF,dFTP],[dX,dXTP],[dU,dUTP]
2349    else:
2350        return CSI
2351   
2352def MustrainNames(SGData):
2353    'Needs a doc string'
2354    laue = SGData['SGLaue']
2355    uniq = SGData['SGUniq']
2356    if laue in ['m3','m3m']:
2357        return ['S400','S220']
2358    elif laue in ['6/m','6/mmm','3m1']:
2359        return ['S400','S004','S202']
2360    elif laue in ['31m','3']:
2361        return ['S400','S004','S202','S211']
2362    elif laue in ['3R','3mR']:
2363        return ['S400','S220','S310','S211']
2364    elif laue in ['4/m','4/mmm']:
2365        return ['S400','S004','S220','S022']
2366    elif laue in ['mmm']:
2367        return ['S400','S040','S004','S220','S202','S022']
2368    elif laue in ['2/m']:
2369        SHKL = ['S400','S040','S004','S220','S202','S022']
2370        if uniq == 'a':
2371            SHKL += ['S013','S031','S211']
2372        elif uniq == 'b':
2373            SHKL += ['S301','S103','S121']
2374        elif uniq == 'c':
2375            SHKL += ['S130','S310','S112']
2376        return SHKL
2377    else:
2378        SHKL = ['S400','S040','S004','S220','S202','S022']
2379        SHKL += ['S310','S103','S031','S130','S301','S013']
2380        SHKL += ['S211','S121','S112']
2381        return SHKL
2382       
2383def HStrainVals(HSvals,SGData):
2384    laue = SGData['SGLaue']
2385    uniq = SGData['SGUniq']
2386    DIJ = np.zeros(6)
2387    if laue in ['m3','m3m']:
2388        DIJ[:3] = [HSvals[0],HSvals[0],HSvals[0]]
2389    elif laue in ['6/m','6/mmm','3m1','31m','3']:
2390        DIJ[:4] = [HSvals[0],HSvals[0],HSvals[1],HSvals[0]]
2391    elif laue in ['3R','3mR']:
2392        DIJ = [HSvals[0],HSvals[0],HSvals[0],HSvals[1],HSvals[1],HSvals[1]]
2393    elif laue in ['4/m','4/mmm']:
2394        DIJ[:3] = [HSvals[0],HSvals[0],HSvals[1]]
2395    elif laue in ['mmm']:
2396        DIJ[:3] = [HSvals[0],HSvals[1],HSvals[2]]
2397    elif laue in ['2/m']:
2398        DIJ[:3] = [HSvals[0],HSvals[1],HSvals[2]]
2399        if uniq == 'a':
2400            DIJ[5] = HSvals[3]
2401        elif uniq == 'b':
2402            DIJ[4] = HSvals[3]
2403        elif uniq == 'c':
2404            DIJ[3] = HSvals[3]
2405    else:
2406        DIJ = [HSvals[0],HSvals[1],HSvals[2],HSvals[3],HSvals[4],HSvals[5]]
2407    return DIJ
2408
2409def HStrainNames(SGData):
2410    'Needs a doc string'
2411    laue = SGData['SGLaue']
2412    uniq = SGData['SGUniq']
2413    if laue in ['m3','m3m']:
2414        return ['D11','eA']         #add cubic strain term
2415    elif laue in ['6/m','6/mmm','3m1','31m','3']:
2416        return ['D11','D33']
2417    elif laue in ['3R','3mR']:
2418        return ['D11','D12']
2419    elif laue in ['4/m','4/mmm']:
2420        return ['D11','D33']
2421    elif laue in ['mmm']:
2422        return ['D11','D22','D33']
2423    elif laue in ['2/m']:
2424        Dij = ['D11','D22','D33']
2425        if uniq == 'a':
2426            Dij += ['D23']
2427        elif uniq == 'b':
2428            Dij += ['D13']
2429        elif uniq == 'c':
2430            Dij += ['D12']
2431        return Dij
2432    else:
2433        Dij = ['D11','D22','D33','D12','D13','D23']
2434        return Dij
2435   
2436def MustrainCoeff(HKL,SGData):
2437    'Needs a doc string'
2438    #NB: order of terms is the same as returned by MustrainNames
2439    laue = SGData['SGLaue']
2440    uniq = SGData['SGUniq']
2441    h,k,l = HKL
2442    Strm = []
2443    if laue in ['m3','m3m']:
2444        Strm.append(h**4+k**4+l**4)
2445        Strm.append(3.0*((h*k)**2+(h*l)**2+(k*l)**2))
2446    elif laue in ['6/m','6/mmm','3m1']:
2447        Strm.append(h**4+k**4+2.0*k*h**3+2.0*h*k**3+3.0*(h*k)**2)
2448        Strm.append(l**4)
2449        Strm.append(3.0*((h*l)**2+(k*l)**2+h*k*l**2))
2450    elif laue in ['31m','3']:
2451        Strm.append(h**4+k**4+2.0*k*h**3+2.0*h*k**3+3.0*(h*k)**2)
2452        Strm.append(l**4)
2453        Strm.append(3.0*((h*l)**2+(k*l)**2+h*k*l**2))
2454        Strm.append(4.0*h*k*l*(h+k))
2455    elif laue in ['3R','3mR']:
2456        Strm.append(h**4+k**4+l**4)
2457        Strm.append(3.0*((h*k)**2+(h*l)**2+(k*l)**2))
2458        Strm.append(2.0*(h*l**3+l*k**3+k*h**3)+2.0*(l*h**3+k*l**3+l*k**3))
2459        Strm.append(4.0*(k*l*h**2+h*l*k**2+h*k*l**2))
2460    elif laue in ['4/m','4/mmm']:
2461        Strm.append(h**4+k**4)
2462        Strm.append(l**4)
2463        Strm.append(3.0*(h*k)**2)
2464        Strm.append(3.0*((h*l)**2+(k*l)**2))
2465    elif laue in ['mmm']:
2466        Strm.append(h**4)
2467        Strm.append(k**4)
2468        Strm.append(l**4)
2469        Strm.append(3.0*(h*k)**2)
2470        Strm.append(3.0*(h*l)**2)
2471        Strm.append(3.0*(k*l)**2)
2472    elif laue in ['2/m']:
2473        Strm.append(h**4)
2474        Strm.append(k**4)
2475        Strm.append(l**4)
2476        Strm.append(3.0*(h*k)**2)
2477        Strm.append(3.0*(h*l)**2)
2478        Strm.append(3.0*(k*l)**2)
2479        if uniq == 'a':
2480            Strm.append(2.0*k*l**3)
2481            Strm.append(2.0*l*k**3)
2482            Strm.append(4.0*k*l*h**2)
2483        elif uniq == 'b':
2484            Strm.append(2.0*l*h**3)
2485            Strm.append(2.0*h*l**3)
2486            Strm.append(4.0*h*l*k**2)
2487        elif uniq == 'c':
2488            Strm.append(2.0*h*k**3)
2489            Strm.append(2.0*k*h**3)
2490            Strm.append(4.0*h*k*l**2)
2491    else:
2492        Strm.append(h**4)
2493        Strm.append(k**4)
2494        Strm.append(l**4)
2495        Strm.append(3.0*(h*k)**2)
2496        Strm.append(3.0*(h*l)**2)
2497        Strm.append(3.0*(k*l)**2)
2498        Strm.append(2.0*k*h**3)
2499        Strm.append(2.0*h*l**3)
2500        Strm.append(2.0*l*k**3)
2501        Strm.append(2.0*h*k**3)
2502        Strm.append(2.0*l*h**3)
2503        Strm.append(2.0*k*l**3)
2504        Strm.append(4.0*k*l*h**2)
2505        Strm.append(4.0*h*l*k**2)
2506        Strm.append(4.0*k*h*l**2)
2507    return Strm
2508   
2509def Muiso2Shkl(muiso,SGData,cell):
2510    "this is to convert isotropic mustrain to generalized Shkls"
2511    import GSASIIlattice as G2lat
2512    A = G2lat.cell2AB(cell)[0]
2513   
2514    def minMus(Shkl,muiso,H,SGData,A):
2515        U = np.inner(A.T,H)
2516        S = np.array(MustrainCoeff(U,SGData))
2517        Sum = np.sqrt(np.sum(np.multiply(S,Shkl[:,np.newaxis]),axis=0))
2518        rad = np.sqrt(np.sum((Sum[:,np.newaxis]*H)**2,axis=1))
2519        return (muiso-rad)**2
2520       
2521    laue = SGData['SGLaue']
2522    PHI = np.linspace(0.,360.,60,True)
2523    PSI = np.linspace(0.,180.,60,True)
2524    X = np.outer(npsind(PHI),npsind(PSI))
2525    Y = np.outer(npcosd(PHI),npsind(PSI))
2526    Z = np.outer(np.ones(np.size(PHI)),npcosd(PSI))
2527    HKL = np.dstack((X,Y,Z))
2528    if laue in ['m3','m3m']:
2529        S0 = [1000.,1000.]
2530    elif laue in ['6/m','6/mmm','3m1']:
2531        S0 = [1000.,1000.,1000.]
2532    elif laue in ['31m','3']:
2533        S0 = [1000.,1000.,1000.,1000.]
2534    elif laue in ['3R','3mR']:
2535        S0 = [1000.,1000.,1000.,1000.]
2536    elif laue in ['4/m','4/mmm']:
2537        S0 = [1000.,1000.,1000.,1000.]
2538    elif laue in ['mmm']:
2539        S0 = [1000.,1000.,1000.,1000.,1000.,1000.]
2540    elif laue in ['2/m']:
2541        S0 = [1000.,1000.,1000.,0.,0.,0.,0.,0.,0.]
2542    else:
2543        S0 = [1000.,1000.,1000.,1000.,1000., 1000.,1000.,1000.,1000.,1000., 
2544            1000.,1000.,0.,0.,0.]
2545    S0 = np.array(S0)
2546    HKL = np.reshape(HKL,(-1,3))
2547    result = so.leastsq(minMus,S0,(np.ones(HKL.shape[0])*muiso,HKL,SGData,A))
2548    return result[0]
2549       
2550def PackRot(SGOps):
2551    IRT = []
2552    for ops in SGOps:
2553        M = ops[0]
2554        irt = 0
2555        for j in range(2,-1,-1):
2556            for k in range(2,-1,-1):
2557                irt *= 3
2558                irt += M[k][j]
2559        IRT.append(int(irt))
2560    return IRT
2561       
2562def SytSym(XYZ,SGData):
2563    '''
2564    Generates the number of equivalent positions and a site symmetry code for a specified coordinate and space group
2565
2566    :param XYZ: an array, tuple or list containing 3 elements: x, y & z
2567    :param SGData: from SpcGroup
2568    :Returns: a two element tuple:
2569
2570     * The 1st element is a code for the site symmetry (see GetKNsym)
2571     * The 2nd element is the site multiplicity
2572
2573    '''
2574    SymName = ''
2575    Mult = 1
2576    Isym = 0
2577    if SGData['SGLaue'] in ['3','3m1','31m','6/m','6/mmm']:
2578        Isym = 1073741824
2579    Jdup = 0
2580    Xeqv = GenAtom(XYZ,SGData,True)
2581    IRT = PackRot(SGData['SGOps'])
2582    L = -1
2583    for ic,cen in enumerate(SGData['SGCen']):
2584        for invers in range(int(SGData['SGInv']+1)):
2585            for io,ops in enumerate(SGData['SGOps']):
2586                irtx = (1-2*invers)*IRT[io]
2587                L += 1
2588                if not Xeqv[L][1]:
2589                    Jdup += 1
2590                    jx = GetOprPtrName(str(irtx))
2591                    if jx[2] < 39:
2592                        Isym += 2**(jx[2]-1)
2593    if Isym == 1073741824: Isym = 0
2594    Mult = len(SGData['SGOps'])*len(SGData['SGCen'])*(int(SGData['SGInv'])+1)/Jdup
2595         
2596    return GetKNsym(str(Isym)),Mult
2597   
2598def ElemPosition(SGData):
2599    ''' Under development.
2600    Object here is to return a list of symmetry element types and locations suitable
2601    for say drawing them.
2602    So far I have the element type... getting all possible locations without lookup may be impossible!
2603    '''
2604    SymElements = []
2605    Inv = SGData['SGInv']
2606    Cen = SGData['SGCen']
2607    eleSym = {-3:['','-1'],-2:['',-6],-1:['2','-4'],0:['3','-3'],1:['4','m'],2:['6',''],3:['1','']}
2608    # get operators & expand if centrosymmetric
2609    Ops = SGData['SGOps']
2610    opM = np.array([op[0].T for op in Ops])
2611    opT = np.array([op[1] for op in Ops])
2612    if Inv:
2613        opM = np.concatenate((opM,-opM))
2614        opT = np.concatenate((opT,-opT))
2615    opMT = zip(opM,opT)
2616    for M,T in opMT[1:]:        #skip I
2617        Dt = int(nl.det(M))
2618        Tr = int(np.trace(M))
2619        Dt = -(Dt-1)/2
2620        Es = eleSym[Tr][Dt]
2621        if Dt:              #rotation-inversion
2622            I = np.eye(3)
2623            if Tr == 1:     #mirrors/glides
2624                if np.any(T):       #glide
2625                    M2 = np.inner(M,M)
2626                    MT = np.inner(M,T)+T
2627                    print 'glide',Es,MT
2628                    print M2
2629                else:               #mirror
2630                    print 'mirror',Es,T
2631                    print I-M
2632                X = [-1,-1,-1]
2633            elif Tr == -3:  # pure inversion
2634                X = np.inner(nl.inv(I-M),T)
2635                print 'inversion',Es,X
2636            else:           #other rotation-inversion
2637                M2 = np.inner(M,M)
2638                MT = np.inner(M,T)+T
2639                print 'rot-inv',Es,MT
2640                print M2
2641                X = [-1,-1,-1]
2642        else:               #rotations
2643            print 'rotation',Es
2644            X = [-1,-1,-1]
2645        #SymElements.append([Es,X])
2646       
2647    return #SymElements
2648   
2649def ApplyStringOps(A,SGData,X,Uij=[]):
2650    'Needs a doc string'
2651    SGOps = SGData['SGOps']
2652    SGCen = SGData['SGCen']
2653    Ax = A.split('+')
2654    Ax[0] = int(Ax[0])
2655    iC = 0
2656    if Ax[0] < 0:
2657        iC = 1
2658    Ax[0] = abs(Ax[0])
2659    nA = Ax[0]%100-1
2660    cA = Ax[0]/100
2661    Cen = SGCen[cA]
2662    M,T = SGOps[nA]
2663    if len(Ax)>1:
2664        cellA = Ax[1].split(',')
2665        cellA = np.array([int(a) for a in cellA])
2666    else:
2667        cellA = np.zeros(3)
2668    newX = Cen+(1-2*iC)*(np.inner(M,X).T+T)+cellA
2669    if len(Uij):
2670        U = Uij2U(Uij)
2671        U = np.inner(M,np.inner(U,M).T)
2672        newUij = U2Uij(U)
2673        return [newX,newUij]
2674    else:
2675        return newX
2676       
2677def StringOpsProd(A,B,SGData):
2678    """
2679    Find A*B where A & B are in strings '-' + '100*c+n' + '+ijk'
2680    where '-' indicates inversion, c(>0) is the cell centering operator,
2681    n is operator number from SgOps and ijk are unit cell translations (each may be <0).
2682    Should return resultant string - C. SGData - dictionary using entries:
2683
2684       *  'SGCen': cell centering vectors [0,0,0] at least
2685       *  'SGOps': symmetry operations as [M,T] so that M*x+T = x'
2686
2687    """
2688    SGOps = SGData['SGOps']
2689    SGCen = SGData['SGCen']
2690    #1st split out the cell translation part & work on the operator parts
2691    Ax = A.split('+'); Bx = B.split('+')
2692    Ax[0] = int(Ax[0]); Bx[0] = int(Bx[0])
2693    iC = 0
2694    if Ax[0]*Bx[0] < 0:
2695        iC = 1
2696    Ax[0] = abs(Ax[0]); Bx[0] = abs(Bx[0])
2697    nA = Ax[0]%100-1;  nB = Bx[0]%100-1
2698    cA = Ax[0]/100;  cB = Bx[0]/100
2699    Cen = (SGCen[cA]+SGCen[cB])%1.0
2700    cC = np.nonzero([np.allclose(C,Cen) for C in SGCen])[0][0]
2701    Ma,Ta = SGOps[nA]; Mb,Tb = SGOps[nB]
2702    Mc = np.inner(Ma,Mb.T)
2703#    print Ma,Mb,Mc
2704    Tc = (np.add(np.inner(Mb,Ta)+1.,Tb))%1.0
2705#    print Ta,Tb,Tc
2706#    print [np.allclose(M,Mc)&np.allclose(T,Tc) for M,T in SGOps]
2707    nC = np.nonzero([np.allclose(M,Mc)&np.allclose(T,Tc) for M,T in SGOps])[0][0]
2708    #now the cell translation part
2709    if len(Ax)>1:
2710        cellA = Ax[1].split(',')
2711        cellA = [int(a) for a in cellA]
2712    else:
2713        cellA = [0,0,0]
2714    if len(Bx)>1:
2715        cellB = Bx[1].split(',')
2716        cellB = [int(b) for b in cellB]
2717    else:
2718        cellB = [0,0,0]
2719    cellC = np.add(cellA,cellB)
2720    C = str(((nC+1)+(100*cC))*(1-2*iC))+'+'+ \
2721        str(int(cellC[0]))+','+str(int(cellC[1]))+','+str(int(cellC[2]))
2722    return C
2723           
2724def U2Uij(U):
2725    #returns the UIJ vector U11,U22,U33,U12,U13,U23 from tensor U
2726    return [U[0][0],U[1][1],U[2][2],U[0][1],U[0][2],U[1][2]]
2727   
2728def Uij2U(Uij):
2729    #returns the thermal motion tensor U from Uij as numpy array
2730    return np.array([[Uij[0],Uij[3],Uij[4]],[Uij[3],Uij[1],Uij[5]],[Uij[4],Uij[5],Uij[2]]])
2731
2732def StandardizeSpcName(spcgroup):
2733    '''Accept a spacegroup name where spaces may have not been used
2734    in the names according to the GSAS convention (spaces between symmetry
2735    for each axis) and return the space group name as used in GSAS
2736    '''
2737    rspc = spcgroup.replace(' ','').upper()
2738    # deal with rhombohedral and hexagonal setting designations
2739    rhomb = ''
2740    if rspc[-1:] == 'R':
2741        rspc = rspc[:-1]
2742        rhomb = ' R'
2743    elif rspc[-1:] == 'H': # hexagonal is assumed and thus can be ignored
2744        rspc = rspc[:-1]
2745    # look for a match in the spacegroup lists
2746    for i in spglist.values():
2747        for spc in i:
2748            if rspc == spc.replace(' ','').upper():
2749                return spc + rhomb
2750    # how about the post-2002 orthorhombic names?
2751    for i,spc in sgequiv_2002_orthorhombic:
2752        if rspc == i.replace(' ','').upper():
2753            return spc
2754    # not found
2755    return ''
2756
2757   
2758spglist = {}
2759'''A dictionary of space groups as ordered and named in the pre-2002 International
2760Tables Volume A, except that spaces are used following the GSAS convention to
2761separate the different crystallographic directions.
2762Note that the symmetry codes here will recognize many non-standard space group
2763symbols with different settings. They are ordered by Laue group
2764'''
2765spglist = {
2766    'P1' : ('P 1','P -1',), # 1-2
2767    'C1' : ('C 1','C -1',),
2768    'P2/m': ('P 2','P 21','P m','P a','P c','P n',
2769        '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
2770    'C2/m':('C 2','C m','C c','C n',
2771        'C 2/m','C 2/c','C 2/n',),
2772    'Pmmm':('P 2 2 2',
2773        'P 2 2 21','P 21 2 2','P 2 21 2',
2774        'P 21 21 2','P 2 21 21','P 21 2 21',
2775        'P 21 21 21',
2776        'P m m 2','P 2 m m','P m 2 m',
2777        'P m c 21','P 21 m a','P b 21 m','P m 21 b','P c m 21','P 21 a m',
2778        'P c c 2','P 2 a a','P b 2 b',
2779        'P m a 2','P 2 m b','P c 2 m','P m 2 a','P b m 2','P 2 c m',
2780        'P c a 21','P 21 a b','P c 21 b','P b 21 a','P b c 21','P 21 c a',
2781        'P n c 2','P 2 n a','P b 2 n','P n 2 b','P c n 2','P 2 a n',
2782        'P m n 21','P 21 m n','P n 21 m','P m 21 n','P n m 21','P 21 n m',
2783        'P b a 2','P 2 c b','P c 2 a',
2784        'P n a 21','P 21 n b','P c 21 n','P n 21 a','P b n 21','P 21 c n',
2785        'P n n 2','P 2 n n','P n 2 n',
2786        'P m m m','P n n n',
2787        'P c c m','P m a a','P b m b',
2788        'P b a n','P n c b','P c n a',
2789        'P m m a','P b m m','P m c m','P m a m','P m m b','P c m m',
2790        'P n n a','P b n n','P n c n','P n a n','P n n b','P c n n',
2791        'P m n a','P b m n','P n c m','P m a n','P n m b','P c n m',
2792        'P c c a','P b a a','P b c b','P b a b','P c c b','P c a a',
2793        'P b a m','P m c b','P c m a',
2794        'P c c n','P n a a','P b n b',
2795        'P b c m','P m c a','P b m a','P c m b','P c a m','P m a b',
2796        'P n n m','P m n n','P n m n',
2797        'P m m n','P n m m','P m n m',
2798        'P b c n','P n c a','P b n a','P c n b','P c a n','P n a b',
2799        'P b c a','P c a b',
2800        'P n m a','P b n m','P m c n','P n a m','P m n b','P c m n',
2801        ),
2802    'Cmmm':('C 2 2 21','C 2 2 2','C m m 2',
2803        'C m c 21','C c m 21','C c c 2','C m 2 m','C 2 m m',
2804        'C m 2 a','C 2 m b','C c 2 m','C 2 c m','C c 2 a','C 2 c b',
2805        'C m c m','C m c a','C c m b',
2806        'C m m m','C c c m','C m m a','C m m b','C c c a','C c c b',),
2807    'Immm':('I 2 2 2','I 21 21 21',
2808        'I m m 2','I m 2 m','I 2 m m',
2809        'I b a 2','I 2 c b','I c 2 a',
2810        'I m a 2','I 2 m b','I c 2 m','I m 2 a','I b m 2','I 2 c m',
2811        'I m m m','I b a m','I m c b','I c m a',
2812        'I b c a','I c a b',
2813        'I m m a','I b m m ','I m c m','I m a m','I m m b','I c m m',),
2814    'Fmmm':('F 2 2 2','F m m m', 'F d d d',
2815        'F m m 2','F m 2 m','F 2 m m',
2816        'F d d 2','F d 2 d','F 2 d d',),
2817    'P4/mmm':('P 4','P 41','P 42','P 43','P -4','P 4/m','P 42/m','P 4/n','P 42/n',
2818        'P 4 2 2','P 4 21 2','P 41 2 2','P 41 21 2','P 42 2 2',
2819        'P 42 21 2','P 43 2 2','P 43 21 2','P 4 m m','P 4 b m','P 42 c m',
2820        'P 42 n m','P 4 c c','P 4 n c','P 42 m c','P 42 b c','P -4 2 m',
2821        'P -4 2 c','P -4 21 m','P -4 21 c','P -4 m 2','P -4 c 2','P -4 b 2',
2822        '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',
2823        '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',
2824        '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',
2825        'P 42/n c m',),
2826    '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',
2827        'I 4 c m','I 41 m d','I 41 c d',
2828        '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',
2829        'I 41/a m d','I 41/a c d'),
2830    'R3-H':('R 3','R -3','R 3 2','R 3 m','R 3 c','R -3 m','R -3 c',),
2831    'P6/mmm': ('P 3','P 31','P 32','P -3','P 3 1 2','P 3 2 1','P 31 1 2',
2832        'P 31 2 1','P 32 1 2','P 32 2 1', 'P 3 m 1','P 3 1 m','P 3 c 1',
2833        'P 3 1 c','P -3 1 m','P -3 1 c','P -3 m 1','P -3 c 1','P 6','P 61',
2834        'P 65','P 62','P 64','P 63','P -6','P 6/m','P 63/m','P 6 2 2',
2835        'P 61 2 2','P 65 2 2','P 62 2 2','P 64 2 2','P 63 2 2','P 6 m m',
2836        'P 6 c c','P 63 c m','P 63 m c','P -6 m 2','P -6 c 2','P -6 2 m',
2837        'P -6 2 c','P 6/m m m','P 6/m c c','P 63/m c m','P 63/m m c',),
2838    'Pm3m': ('P 2 3','P 21 3','P m 3','P n 3','P a 3','P 4 3 2','P 42 3 2',
2839        'P 43 3 2','P 41 3 2','P -4 3 m','P -4 3 n','P m 3 m','P n 3 n',
2840        'P m 3 n','P n 3 m',),
2841    'Im3m':('I 2 3','I 21 3','I m -3','I a -3', 'I 4 3 2','I 41 3 2',
2842        'I -4 3 m', 'I -4 3 d','I m -3 m','I m 3 m','I a -3 d',),
2843    'Fm3m':('F 2 3','F m -3','F d -3','F 4 3 2','F 41 3 2','F -4 3 m',
2844        'F -4 3 c','F m -3 m','F m 3 m','F m -3 c','F d -3 m','F d -3 c',),
2845}
2846
2847ssdict = {}
2848'''A dictionary of superspace group symbols allowed for each entry in spglist
2849(except cubics). Monoclinics are all b-unique setting.
2850'''
2851ssdict = {
2852#1,2
2853    'P 1':['(abg)',],'P -1':['(abg)',],
2854    'C 1':['(abg)',],'C -1':['(abg)',],
2855#monoclinic - done
2856#3
2857    'P 2':['(a0g)','(a1/2g)','(0b0)','(0b0)s','(1/2b0)','(0b1/2)',],
2858#4       
2859    'P 21':['(a0g)','(0b0)','(1/2b0)','(0b1/2)',],
2860#5
2861    'C 2':['(a0g)','(0b0)','(0b0)s','(0b1/2)',],
2862#6
2863    'P m':['(a0g)','(a0g)s','(a1/2g)','(0b0)','(1/2b0)','(0b1/2)',],
2864#7
2865    'P a':['(a0g)','(a1/2g)','(0b0)','(0b1/2)',],
2866    'P c':['(a0g)','(a1/2g)','(0b0)','(1/2b0)',],
2867    'P n':['(a0g)','(a1/2g)','(0b0)','(1/2b1/2)',],
2868#8       
2869    'C m':['(a0g)','(a0g)s','(0b0)','(0b1/2)',],
2870#9       
2871    'C c':['(a0g)','(a0g)s','(0b0)',],
2872    'C n':['(a0g)','(a0g)s','(0b0)',],
2873#10       
2874    'P 2/m':['(a0g)','(a0g)0s','(a1/2g)','(0b0)','(0b0)s0','(1/2b0)','(0b1/2)',],
2875#11
2876    'P 21/m':['(a0g)','(a0g)0s','(0b0)','(0b0)s0','(1/2b0)','(0b1/2)',],
2877#12       
2878    'C 2/m':['(a0g)','(a0g)0s','(0b0)','(0b0)s0','(0b1/2)',],
2879#13
2880    'P 2/c':['(a0g)','(a0g)0s','(a1/2g)','(0b0)','(0b0)s0','(1/2b0)',],
2881    'P 2/a':['(a0g)','(a0g)0s','(a1/2g)','(0b0)','(0b0)s0','(0b1/2)',],
2882    'P 2/n':['(a0g)','(a0g)0s','(a1/2g)','(0b0)','(0b0)s0','(1/2b1/2)',],
2883#14
2884    'P 21/c':['(a0g)','(0b0)','(1/2b0)',],
2885    'P 21/a':['(a0g)','(0b0)','(0b1/2)',],
2886    'P 21/n':['(a0g)','(0b0)','(1/2b1/2)',],
2887#15
2888    'C 2/c':['(a0g)','(0b0)','(0b0)s0',],
2889    'C 2/n':['(a0g)','(0b0)','(0b0)s0',],
2890#orthorhombic
2891#16   
2892    'P 2 2 2':['(00g)','(00g)00s','(01/2g)','(1/20g)','(1/21/2g)',
2893        '(a00)','(a00)s00','(a01/2)','(a1/20)','(a1/21/2)',
2894        '(0b0)','(0b0)0s0','(1/2b0)','(0b1/2)','(1/2b1/2)',],
2895#17       
2896    'P 2 2 21':['(00g)','(01/2g)','(1/20g)','(1/21/2g)',
2897        '(a00)','(a00)s00','(a1/20)','(0b0)','(0b0)0s0','(1/2b0)',],
2898    'P 21 2 2':['(a00)','(a01/2)','(a1/20)','(a1/21/2)',
2899        '(0b0)','(0b0)0s0','(1/2b0)','(00g)','(00g)00s','(1/20g)',],
2900    'P 2 21 2':['(0b0)','(0b1/2)','(1/2b0)','(1/2b1/2)',
2901        '(00g)','(00g)00s','(1/20g)','(a00)','(a00)s00','(a1/20)',],
2902#18       
2903    'P 21 21 2':['(00g)','(00g)00s','(a00)','(a01/2)','(0b0)','(0b1/2)',],
2904    'P 2 21 21':['(a00)','(a00)s00','(0b0)','(0b1/2)','(00g)','(01/2g)',],
2905    'P 21 2 21':['(0b0)','(0b0)0s0','(00g)','(01/2g)','(a00)','(a01/2)',],
2906#19       
2907    'P 21 21 21':['(00g)','(a00)','(0b0)',],
2908#20       
2909    'C 2 2 21':['(00g)','(10g)','(01g)','(a00)','(a00)s00','(0b0)','(0b0)0s0',],
2910    'A 21 2 2':['(a00)','(a10)','(a01)','(0b0)','(0b0)0s0','(00g)','(00g)00s',],
2911    'B 2 21 2':['(0b0)','(1b0)','(0b1)','(00g)','(00g)00s','(a00)','(a00)s00',],
2912#21       
2913    'C 2 2 2':['(00g)','(00g)00s','(10g)','(10g)00s','(01g)','(01g)00s',
2914        '(a00)','(a00)s00','(a01/2)','(0b0)','(0b0)0s0','(0b1/2)',],
2915    'A 2 2 2':['(a00)','(a00)s00','(a10)','(a10)s00','(a01)','(a01)s00',
2916        '(0b0)','(0b0)0s0','(1/2b0)','(00g)','(00g)00s','(1/20g)',],
2917    'B 2 2 2':['(0b0)','(0b0)0s0','(1b0)','(1b0)0s0','(0b1)','(0b1)0s0',
2918        '(00g)','(00g)00s','(01/2g)','(a00)','(a00)s00','(a1/20)',],
2919#22       
2920    'F 2 2 2':['(00g)','(00g)00s','(10g)','(01g)',
2921        '(a00)','(a00)s00','(a10)','(a01)',
2922        '(0b0)','(0b0)0s0','(1b0)','(0b1)',],
2923#23       
2924    'I 2 2 2':['(00g)','(00g)00s','(a00)','(a00)s00','(0b0)','(0b0)0s0',],
2925#24       
2926    'I 21 21 21':['(00g)','(00g)00s','(a00)','(a00)s00','(0b0)','(0b0)0s0',],
2927#25       
2928    'P m m 2':['(00g)','(00g)s0s','(00g)0ss','(00g)ss0',
2929        '(01/2g)','(01/2g)s0s','(1/20g)','(1/20g)0ss','(1/21/2g)',
2930        '(a00)','(a00)0s0','(a1/20)','(a01/2)','(a01/2)0s0','(a1/21/2)',
2931        '(0b0)','(0b0)s00','(0b1/2)','(0b1/2)s00','(1/2b0)','(1/2b1/2)',],       
2932    'P 2 m m':['(a00)','(a00)ss0','(a00)s0s','(a00)0ss',
2933        '(a01/2)','(a01/2)ss0','(a1/20)','(a1/20)s0s','(a1/21/2)',
2934        '(0b0)','(0b0)00s','(1/2b0)','(0b1/2)','(0b1/2)00s','(1/2b1/2)',
2935        '(00g)','(00g)0s0','(01/2g)','(01/2g)0s0','(1/20g)','(1/21/2g)',],
2936    'P m 2 m':['(0b0)','(0b0)ss0','(0b0)0ss','(0b0)s0s',
2937        '(0b1/2)','(0b1/2)ss0','(1/2b0)','(1/2b0)0ss','(1/2b1/2)',
2938        '(00g)','(00g)s00','(1/20g)','(01/2g)','(01/2g)s00','(1/21/2g)',
2939        '(a00)','(a00)0s0','(a01/2)','(a01/2)0s0','(a1/20)','(a1/21/2)',],       
2940#26       
2941    'P m c 21':['(00g)','(00g)s0s','(01/2g)','(01/2g)s0s','(1/20g)','(1/21/2g)',
2942        '(a00)','(a00)0s0','(a1/20)','(0b0)','(0b0)s00','(0b1/2)',],
2943    'P 21 m a':['(a00)','(a00)ss0','(a01/2)','(a01/2)ss0','(a1/20)','(a1/21/2)',
2944        '(0b0)','(0b0)00s','(1/2b0)','(00g)','(00g)0s0','(01/2g)',],
2945    'P b 21 m':['(0b0)','(0b0)ss0','(0b1/2)','(0b1/2)ss0','(1/2b0)','(1/2b1/2)',
2946        '(00g)','(00g)s00','(1/20g)','(a00)','(a00)0s0','(a01/2)',],
2947    'P m 21 b':['(a00)','(a00)ss0','(a01/2)','(a01/2)ss0','(a1/20)','(a1/21/2)',
2948        '(00g)','(00g)0s0','(01/2g)','(0b0)','(0b0)s00','(0b1/2)',],
2949    'P c m 21':['(00g)','(00g)0ss','(1/20g)','(1/20g)0ss','(01/2g)','(1/21/2g)',
2950        '(0b0)','(0b0)s00','(1/2b0)','(a00)','(a00)0s0','(a01/2)',],
2951    'P 21 a m':['(0b0)','(0b0)ss0','(0b1/2)','(0b1/2)ss0','(1/2b0)','(1/2b1/2)',
2952        '(a00)','(a00)00s','(a1/20)','(00g)','(00g)s00','(1/20g)',],
2953#27       
2954    'P c c 2':['(00g)','(00g)s0s','(00g)0ss','(01/2g)','(1/20g)','(1/21/2g)',
2955        '(a00)','(a00)0s0','(a1/20)','(0b0)','(0b0)s00','(1/2b0)',],
2956    'P 2 a a':['(a00)','(a00)ss0','(a00)s0s','(a01/2)','(a1/20)','(a1/21/2)',
2957        '(0b0)','(0b0)00s','(0b1/2)','(00g)','(00g)0s0','(01/2g)',],
2958    'P b 2 b':['(0b0)','(0b0)0ss','(0b0)ss0','(1/2b0)','(0b1/2)','(1/2b1/2)',
2959        '(00g)','(00g)s00','(1/20g)','(a00)','(a00)00s','(a01/2)',],
2960#28       
2961    'P m a 2':['(00g)','(00g)s0s','(00g)ss0','(00g)0ss','(01/2g)','(01/2g)s0s',
2962        '(0b1/2)','(0b1/2)s00','(a01/2)','(a00)','(0b0)','(0b0)0s0','(a1/20)','(a1/21/2)'],
2963    'P 2 m b':['(a00)','(a00)s0s','(a00)ss0','(a00)0ss','(a01/2)','(a01/2)s0s',
2964        '(1/20g)','(1/20g)s00','(1/2b0)','(0b0)','(00g)','(00g)0s0','(0b1/2)','(1/2b1/2)'],
2965    'P c 2 m':['(0b0)','(0b0)s0s','(0b0)ss0','(0b0)0ss','(1/2b0)','(1/2b0)s0s',
2966        '(a1/20)','(a1/20)s00','(01/2g)','(00g)','(a00)','(a00)0s0','(1/20g)','(1/21/2g)'],
2967    'P m 2 a':['(0b0)','(0b0)s0s','(0b0)ss0','(0b0)0ss','(0b1/2)','(0b1/2)s0s',
2968        '(01/2g)','(01/2g)s00','(a1/20)','(a00)','(00g)','(00g)0s0','(a01/2)','(a1/21/2)'],
2969    'P b m 2':['(00g)','(00g)s0s','(00g)ss0','(00g)0ss','(1/20g)','(1/20g)s0s',
2970        '(a01/2)','(a01/2)s00','(0b1/2)','(0b0)','(a00)','(a00)0s0','(1/2b0)','(1/2b1/2)'],
2971    'P 2 c m':['(a00)','(a00)s0s','(a00)ss0','(a00)0ss','(a1/20)','(a1/20)s0s',
2972        '(1/2b0)','(1/2b0)s00','(1/20g)','(00g)','(0b0)','(0b0)0s0','(01/2g)','(1/21/2g)'],
2973#29       
2974    'P c a 21':['(00g)','(00g)0ss','(01/2g)','(1/20g)',
2975        '(a00)','(a00)0s0','(a1/20)','(0b0)','(0b0)s00','(1/2b0)',],
2976    'P 21 a b':['(a00)','(a00)s0s','(a01/2)','(a1/20)',
2977        '(0b0)','(0b0)00s','(0b1/2)','(00g)','(00g)0s0','(01/2g)',],
2978    'P c 21 b':['(0b0)','(0b0)ss0','(1/2b0)','(0b1/2)',
2979        '(00g)','(00g)s00','(1/20g)','(a00)','(a00)00s','(a01/2)',],
2980    'P b 21 a':['(0b0)','(0b0)0ss','(0b1/2)','(1/2b0)',
2981        '(a00)','(a00)00s','(a1/20)','(00g)','(00g)s00','(1/20g)',],
2982    'P b c 21':['(00g)','(00g)s0s','(1/20g)','(01/2g)',
2983        '(0b0)','(0b0)s00','(0b1/2)','(a00)','(a00)0s0','(a1/20)',],
2984    'P 21 c a':['(a00)','(a00)ss0','(a1/20)','(a01/2)',
2985        '(00g)','(00g)0s0','(1/20g)','(0b0)','(0b0)00s','(0b1/2)',],
2986#30       
2987    'P c n 2':['(00g)','(00g)s0s','(01/2g)','(a00)','(0b0)','(0b0)s00',
2988        '(a1/20)','(1/2b1/2)q00',],
2989    'P 2 a n':['(a00)','(a00)ss0','(a01/2)','(0b0)','(00g)','(00g)0s0',
2990        '(0b1/2)','(1/21/2g)0q0',],
2991    'P n 2 b':['(0b0)','(0b0)0ss','(1/2b0)','(00g)','(a00)','(a00)00s',
2992        '(1/20g)','(a1/21/2)00q',],
2993    'P b 2 n':['(0b0)','(0b0)ss0','(0b1/2)','(a00)','(00g)','(00g)s00',
2994        '(a01/2)','(1/21/2g)0ss',],
2995    'P n c 2':['(00g)','(00g)0ss','(1/20g)','(0b0)','(a00)','(a00)0s0',
2996        '(1/2b0)','(a1/21/2)s0s',],
2997    'P 2 n a':['(a00)','(a00)s0s','(a1/20)','(00g)','(0b0)','(0b0)00s',
2998        '(01/2g)','(1/2b1/2)ss0',],
2999#31       
3000    'P m n 21':['(00g)','(00g)s0s','(01/2g)','(01/2g)s0s','(a00)','(0b0)',
3001        '(0b0)s00','(a1/20)',],
3002    'P 21 m n':['(a00)','(a00)ss0','(a01/2)','(a01/2)ss0','(0b0)','(00g)',
3003        '(00g)0s0','(0b1/2)',],
3004    'P n 21 m':['(0b0)','(0b0)0ss','(1/2b0)','(1/2b0)0ss','(00g)','(a00)',
3005        '(a00)00s','(1/20g)',],
3006    'P m 21 n':['(0b0)','(0b0)ss0','(0b1/2)','(0b1/2)ss0','(a00)','(00g)',
3007        '(00g)s00','(a01/2)',],
3008    'P n m 21':['(00g)','(00g)0ss','(1/20g)','(1/20g)0ss','(0b0)','(a00)',
3009        '(a00)0s0','(1/2b0)',],
3010    'P 21 n m':['(a00)','(a00)s0s','(a1/20)','(a1/20)s0s','(00g)','(0b0)',
3011        '(0b0)00s','(01/2g)',],
3012#32       
3013    'P b a 2':['(00g)','(00g)s0s','(00g)0ss','(00g)ss0','(1/21/2g)qq0',
3014        '(a00)','(a01/2)','(0b0)','(0b1/2)',],
3015    'P 2 c b':['(a00)','(a00)ss0','(a00)s0s','(a00)0ss','(a1/21/2)0qq',
3016        '(0b0)','(1/2b0)','(00g)','(1/20g)',],
3017    'P c 2 a':['(0b0)','(0b0)ss0','(0b0)0ss','(0b0)s0s','(1/2b1/2)q0q',
3018        '(00g)','01/2g)','(a00)','(a1/20)',],
3019#33       
3020    'P b n 21':['(00g)','(00g)s0s','(1/21/2g)qq0','(a00)','(0b0)',],
3021    'P 21 c n':['(a00)','(a00)ss0','(a1/21/2)0qq','(0b0)','(00g)',],
3022    'P n 21 a':['(0b0)','(0b0)0ss','(1/2b1/2)q0q','(00g)','(a00)',],
3023    'P c 21 n':['(0b0)','(0b0)ss0','(1/2b1/2)q0q','(a00)','(00g)',],
3024    'P n a 21':['(00g)','(00g)0ss','(1/21/2g)qq0','(0b0)','(a00)',],
3025    'P 21 n b':['(a00)','(a00)s0s','(a1/21/2)0qq','(00g)','(0b0)',],
3026#34       
3027    'P n n 2':['(00g)','(00g)s0s','(00g)0ss','(1/21/2g)qq0',
3028        '(a00)','(a1/21/2)0q0','(a1/21/2)00q','(0b0)','(1/2b1/2)q00','(1/2b1/2)00q',],
3029    'P 2 n n':['(a00)','(a00)ss0','(a00)s0s','(a1/21/2)0qq',
3030        '(0b0)','(1/2b1/2)q00','(1/2b1/2)00q','(00g)','(1/21/2g)0q0','(1/21/2g)q00',],
3031    'P n 2 n':['(0b0)','(0b0)ss0','(0b0)0ss','(1/2b1/2)q0q',
3032        '(00g)','(1/21/2g)0q0','(1/21/2g)q00','(a00)','(a1/21/2)00q','(a1/21/2)0q0',],
3033#35       
3034    'C m m 2':['(00g)','(00g)s0s','(00g)ss0','(10g)','(10g)s0s','(10g)ss0',
3035        '(0b0)','(0b0)s00','(0b1/2)','(0b1/2)s00',],
3036    'A 2 m m':['(a00)','(a00)ss0','(a00)0ss','(a10)','(a10)ss0','(a10)0ss',
3037        '(00g)','(00g)0s0','(1/20g)','(1/20g)0s0',],
3038    'B m 2 m':['(0b0)','(0b0)0ss','(0b0)s0s','(0b1)','(0b1)0ss','(0b1)s0s',
3039        '(a00)','(a00)00s','(a1/20)','(a1/20)00s',],
3040#36
3041    'C m c 21':['(00g)','(00g)s0s','(10g)','(10g)s0s','(a00)','(a00)0s0','(0b0)','(0b0)s00',],
3042    'A 21 m a':['(a00)','(a00)ss0','(a10)','(a10)ss0','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
3043    'B m 21 b':['(0b0)','(0b0)ss0','(1b0)','(1b0)ss0','(a00)','(a00)00s','(00g)','(00g)s00',],
3044    'B b 21 m':['(0b0)','(0b0)0ss','(0b1)','(0b1)ss0','(a00)','(a00)00s','(00g)','(00g)s00',],
3045    'C c m 21':['(00g)','(00g)0ss','(01g)','(01g)0ss','(a00)','(a00)0s0','(0b0)','(0b0)s00',],
3046    'A 21 a m':['(a00)','(a00)s0s','(a01)','(a01)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
3047#37
3048    'C c c 2':['(00g)','(00g)s0s','(00g)0ss','(10g)','(10g)s0s','(10g)0ss','(01g)','(01g)s0s','(01g)0ss',
3049        '(a00)','(a00)0s0','(0b0)','(0b0)s00',],
3050    'A 2 a a':['(a00)','(a00)ss0','(a00)s0s','(a10)','(a10)ss0','(a10)ss0','(a01)','(a01)ss0','(a01)ss0',
3051        '(0b0)','(0b0)00s','(00g)','(00g)0s0',],
3052    'B b 2 b':['(0b0)','(0b0)0ss','(0b0)ss0','(0b1)','(0b1)0ss','(0b1)ss0','(1b0)','(1b0)0ss','(1b0)ss0',
3053        '(a00)','(a00)00s','(00g)','(00g)s00',],
3054#38
3055    'A m m 2':['(a00)','(a00)0s0','(a10)','(a10)0s0','(00g)','(00g)0s0',
3056        '(00g)ss0','(00g)0ss','(1/20g)','(1/20g)0ss','(0b0)','(0b0)s00','(1/2b0)',],
3057    'B 2 m m':['(0b0)','(0b0)00s','(0b1)','(0b1)00s','(a00)','(a00)00s',
3058        '(a00)0ss','(a00)s0s','(a1/20)','(a1/20)s0s','(00g)','(00g)0s0','(01/2g)',],
3059    'C m 2 m':['(00g)','(00g)s00','(10g)','(10g)s00','(0b0)','(0b0)s00',
3060        '(0b0)s0s','(0b0)ss0','(0b1/2)','(0b1/2)ss0','(a00)','(a00)00s','(a01/2)',],
3061    'A m 2 m':['(a00)','(a00)00s','(a01)','(a01)00s','(0b0)','(0b0)00s',
3062        '(0b0)s0s','(0b0)0ss','(1/2b0)','(1/2b0)0ss','(00g)','(00g)s00','(1/20g)',],
3063    'B m m 2':['(0b0)','(0b0)s00','(0b1)','(0b1)s00','(a00)','(a00)0s0',
3064        '(a00)0ss','(a00)ss0','(01/2g)','(01/2g)s0s','(a00)','(a00)0s0','(a1/20)',],
3065    'C 2 m m':['(00g)','(00g)0s0','(10g)','(10g)0s0','(00g)','(00g)s00',
3066        '(0b0)s0s','(0b0)0ss','(a01/2)','(a01/2)ss0','(0b0)','(0b0)00s','(0b1/2)',],
3067#39
3068    'A b m 2':['(a00)','(a00)0s0','(a01)','(a01)0s0','(00g)','(00g)s0s',
3069        '(00g)ss0','(00g)0ss','(1/20g)','(1/20g)0ss','(0b0)','(0b0)s00','(1/2b0)',],
3070    'B 2 c m':['(0b0)','(0b0)00s','(1b0)','(1b0)00s','(a00)','(a00)ss0',
3071        '(a00)0ss','(a00)s0s','(a1/20)','(a1/20)s0s','(00g)','(00g)0s0','(01/2g)',],
3072    'C m 2 a':['(00g)','(00g)s00','(01g)','(01g)s00','(0b0)','(0b0)0ss',
3073        '(0b0)s0s','(0b0)ss0','(0b1/2)','(0b1/2)ss0','(a00)','(a00)00s','(a01/2)',],
3074    'A c 2 m':['(a00)','(a00)00s','(a10)','(a10)00s','(0b0)','(0b0)ss0',
3075        '(0b0)s0s','(0b0)0ss','(1/2b0)','(1/2b0)0ss','(00g)','(00g)s00','(1/20g)',],
3076    'B m a 2':['(0b0)','(0b0)s00','(0b1)','(0b1)s00','(00g)','(00g)s0s',
3077        '(00g)0ss','(00g)ss0','(01/2g)','(01/2g)ss0','(a00)','(a00)00s','(a1/20)',],
3078    'C 2 m b':['(00g)','(00g)0s0','(10g)','(10g)0s0','(a00)','(a00)0ss',
3079        '(a00)ss0','(a00)s0s','(a01/2)','(a01/2)s0s','(0b0)','(0b0)0s0','(0b1/2)',],
3080#40       
3081    'A m a 2':['(a00)','(a01)','(00g)','(00g)s0s','(00g)ss0','(00g)0ss','(0b0)','(0b0)s00',],
3082    'B 2 m b':['(0b0)','(1b0)','(a00)','(a00)ss0','(a00)0ss','(a00)s0s','(00g)','(00g)0s0',],
3083    'C c 2 m':['(00g)','(01g)','(0b0)','(0b0)0ss','(0b0)s0s','(0b0)ss0','(a00)','(a00)00s',],
3084    'A m 2 a':['(a00)','(a10)','(0b0)','(0b0)ss0','(0b0)s0s','(0b0)0ss','(00g)','(00g)s00',],
3085    'B b m 2':['(0b0)','(0b1)','(00g)','(00g)0ss','(00g)ss0','(00g)s0s','(a00)','(a00)0s0',],
3086    'C 2 c m':['(00g)','(10g)','(a00)','(a00)s0s','(a00)0ss','(a00)ss0','(0b0)','(0b0)00s',],
3087#41
3088    'A b a 2':['(a00)','(a01)','(00g)','(00g)s0s','(00g)ss0','(00g)0ss','(0b0)','(0b0)s00',],
3089    'B 2 c b':['(0b0)','(1b0)','(a00)','(a00)ss0','(a00)0ss','(a00)s0s','(00g)','(00g)0s0',],
3090    'C c 2 a':['(00g)','(01g)','(0b0)','(0b0)0ss','(0b0)s0s','(0b0)ss0','(a00)','(a00)00s',],
3091    'A c 2 a':['(a00)','(a10)','(0b0)','(0b0)ss0','(0b0)s0s','(0b0)0ss','(00g)','(00g)s00',],
3092    'B b a 2':['(0b0)','(0b1)','(00g)','(00g)0ss','(00g)ss0','(00g)s0s','(a00)','(a00)0s0',],
3093    'C 2 c b':['(00g)','(10g)','(a00)','(a00)s0s','(a00)0ss','(a00)ss0','(0b0)','(0b0)00s',],
3094       
3095#42       
3096    'F m m 2':['(00g)','(00g)s0s','(00g)0ss','(00g)ss0','(10g)','(10g)ss0','(10g)s0s',
3097        '(01g)','(01g)ss0','(01g)0ss','(a00)','(a00)0s0','(a01)','(a01)0s0',
3098        '(0b0)','(0b0)s00','(0b1)','(0b1)s00',],       
3099    'F 2 m m':['(a00)','(a00)ss0','(a00)s0s','(a00)0ss','(a10)','(a10)0ss','(a10)ss0',
3100        '(a01)','(a01)0ss','(a01)s0s','(0b0)','(0b0)00s','(1b0)','(1b0)00s',
3101        '(00g)','(00g)0s0','(10g)','(10g)0s0',],
3102    'F m 2 m':['(0b0)','(0b0)0ss','(0b0)ss0','(0b0)s0s','(0b1)','(0b1)s0s','(0b1)0ss',
3103        '(1b0)','(1b0)s0s','(1b0)ss0','(00g)','(00g)s00','(01g)','(01g)s00',
3104        '(a00)','(a00)00s','(a10)','(a10)00s',],       
3105#43       
3106    'F d d 2':['(00g)','(00g)0ss','(00g)s0s','(a00)','(0b0)',],
3107    'F 2 d d':['(a00)','(a00)s0s','(a00)ss0','(00g)','(0b0)',],       
3108    'F d 2 d':['(0b0)','(0b0)0ss','(0b0)ss0','(a00)','(00g)',],
3109#44
3110    'I m m 2':['(00g)','(00g)ss0','(00g)s0s','(00g)0ss','(a00)','(a00)0s0','(0b0)','(0b0)s00',],
3111    'I 2 m m':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
3112    'I m 2 m':['(0b0)','(0b0)s0s','(0b0)0ss','(0b0)ss0','(00g)','(00g)s00','(a00)','(a00)00s',],
3113#45       
3114    'I b a 2':['(00g)','(00g)ss0','(00g)s0s','(00g)0ss','(a00)','(a00)0s0','(0b0)','(0b0)s00',],
3115    'I 2 c b':['(0b0)','(0b0)s0s','(0b0)0ss','(0b0)ss0','(00g)','(00g)s00','(a00)','(a00)00s',],
3116    'I c 2 a':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
3117#46       
3118    'I m a 2':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
3119    'I 2 m b':['(0b0)','(0b0)s0s','(0b0)0ss','(0b0)ss0','(00g)','(00g)s00','(a00)','(a00)00s',],       
3120    'I c 2 m':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
3121    'I m 2 a':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
3122    'I b m 2':['(a00)','(00g)0ss','(00g)ss0','(00g)s0s','(0b0)','(0b0)00s','(00g)','(00g)0s0',],
3123    'I 2 c m':['(0b0)','(0b0)s0s','(0b0)0ss','(0b0)ss0','(00g)','(00g)s00','(a00)','(a00)00s',],
3124#47       
3125    'P m m m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(01/2g)','(01/2g)s00','(1/20g)','(1/20g)s00','(1/21/2g)',
3126        '(a00)','(a00)0s0','(a00)00s','(a00)0ss','(a01/2)','(a01/2)0s0','(a1/20)','(a1/20)00s','(a1/21/2)',
3127        '(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s','(1/2b0)','(1/2b0)00s','(0b1/2)','(0b1/2)s00','(1/2b1/2)',],
3128#48 o@i qq0,0qq,q0q ->000
3129    'P n n n':['(00g)','(00g)s00','(00g)0s0','(1/21/2g)',
3130        '(a00)','(a00)0s0','(a00)00s','(a1/21/2)',
3131        '(0b0)','(0b0)s00','(0b0)00s','(1/2b1/2)',],
3132#49       
3133    'P c c m':['(00g)','(00g)s00','(00g)0s0','(01/2g)','(1/20g)','(1/21/2g)',
3134        '(a00)','(a00)0s0','(a00)00s','(a00)0ss','(a1/20)','(a1/20)00s',
3135        '(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s','(1/2b0)','(1/2b0)00s',],       
3136    'P m a a':['(a00)','(a00)0s0','(a00)00s','(a01/2)','(a1/20)','(a1/21/2)',
3137        '(0b0)','(0b0)00s','(0b0)s00','(0b0)s0s','(0b1/2)','(0b1/2)s00',
3138        '(00g)','(00g)0s0','(00g)s00','(00g)ss0','(01/2g)','(01/2g)s00',],       
3139    'P b m b':['(0b0)','(0b0)00s','(0b0)s00','(0b1/2)','(1/2b0)','(1/2b1/2)',
3140        '(00g)','(00g)s00','(00g)0s0','(00g)ss0','(1/20g)','(1/20g)0s0',
3141        '(a00)','(a00)00s','(a00)0s0','(a00)0ss','(a01/2)','(a01/2)0s0',],
3142#50 o@i qq0,0qq,q0q ->000
3143    'P b a n':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(1/21/2g)',
3144        '(a00)','(a00)0s0','(a01/2)','(0b0)','(0b0)s00','(0b1/2)',],
3145    'P n c b':['(a00)','(a00)0s0','(a00)00s','(a00)0ss','(a1/21/2)',
3146        '(0b0)','(0b0)00s','(1/2b0)','(00g)','(00g)0s0','(1/20g)',],
3147    'P c n a':['(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s','(1/2b1/2)',
3148        '(00g)','(00g)s00','(01/2g)','(a00)','(a00)00s','(a1/20)',],
3149#51       
3150    'P m m a':['(00g)','(00g)s00','(00g)ss0','(00g)0s0','(0b0)','(0b0)s00',
3151        '(0b0)s0s','(0b0)00s','(a00)','(a00)0s0','(01/2g)','(01/2g)s00',
3152        '(0b1/2)','(0b1/2)s00','(a01/2)','(a01/2)0s0','(1/2b0)','(1/2b1/2)',],
3153    'P b m m':['(a00)','(a00)0s0','(a00)0ss','(a00)00s','(00g)','(00g)0s0',
3154        '(00g)ss0','(00g)s00','(0b0)','(0b0)00s','(a01/2)','(a01/2)0s0',
3155        '(1/20g)','(1/20g)0s0','(1/2b0)','(1/2b0)00s','(01/2g)','(1/21/2g)',],
3156    'P m c m':['(0b0)','(0b0)00s','(0b0)s0s','(0b0)s00','(a00)','(a00)00s',
3157        '(a00)0ss','(a00)0s0','(00g)','(00g)s00','(1/2b0)','(1/2b0)00s',
3158        '(a1/20)','(a1/20)00s','(01/2g)','(01/2g)s00','(a01/2)','(a1/21/2)',],
3159    'P m a m':['(0b0)','(0b0)s00','(0b0)s0s','(0b0)00s','(00g)','(00g)s00',
3160        '(00g)ss0','(00g)0s0','(a00)','(a00)00s','(0b1/2)','(0b1/2)s00',
3161        '(01/2g)','(01/2g)s00','(a1/20)','(a1/20)00s','(1/20g)','(1/21/2g)',],
3162    'P m m b':['(00g)','(00g)0s0','(00g)ss0','(00g)s00','(a00)','(a00)0s0',
3163        '(a00)0ss','(a00)00s','(0b0)','(0b0)s00','(a00)','(a00)0s0',
3164        '(a01/2)','(a01/2)0s0','(0b1/2)','(0b1/2)s00','(a1/20)','(a1/21/2)',],
3165    'P c m m':['(a00)','(a00)00s','(a00)0ss','(a00)0s0','(0b0)','(0b0)00s',
3166        '(0b0)s0s','(0b0)s00','(00g)','(00g)0s0','(0b0)','(0b0)00s',
3167        '(1/2b0)','(1/2b0)00s','(1/20g)','(1/20g)0s0','(0b1/2)','(1/2b1/2)',],
3168#52   o@i qq0,0qq,q0q ->000     
3169    'P n n a':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)00s',
3170        '(0b0)','(0b0)00s','(a1/21/2)','(1/2b1/2)',],
3171    'P b n n':['(a00)','(a00)0s0','(a00)00s','(0b0)','(0b0)s00',
3172        '(00g)','(00g)s00','(1/2b1/2)','(1/21/2g)',],
3173    'P n c n':['(0b0)','(0b0)s00','(0b0)00s','(00g)','(00g)0s0',
3174        '(a00)','(a00)0s0','(1/21/2g)','(a1/21/2)',],
3175    'P n a n':['(0b0)','(0b0)s00','(0b0)00s','(00g)','(00g)0s0',
3176        '(a00)','(a00)0s0','(1/21/2g)','(a1/21/2)',],
3177    'P n n b':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)00s',
3178        '(0b0)','(0b0)00s','(a1/21/2)','(1/2b1/2)',],
3179    'P c n n':['(a00)','(a00)0s0','(a00)00s','(0b0)','(0b0)s00',
3180        '(00g)','(00g)s00','(1/2b1/2)','(1/21/2g)',],
3181#53       
3182    'P m n a':['(00g)','(00g)s00','(a00)','(a00)00s','(0b0)','(0b0)00s',
3183        '(0b0)s0s','(0b0)s00','(01/2g)','(01/2g)s00','(a1/20)',],
3184    'P b m n':['(a00)','(a00)0s0','(0b0)','(0b0)s00','(00g)','(00g)s00',
3185        '(00g)ss0','(00g)0s0','(a01/2)','(a01/2)0s0','(0b1/2)',],
3186    'P n c m':['(0b0)','(0b0)00s','(00g)','(00g)0s0','(a00)','(a00)0s0',
3187        '(a00)0ss','(a00)00s','(1/2b0)','(1/2b0)00s','(1/20g)',],
3188    'P m a n':['(0b0)','(0b0)s00','(a00)','(a00)0s0','(00g)','(00g)0s0',
3189        '(00g)ss0','(00g)s00','(0b1/2)','(0b1/2)s00','(a01/2)',],
3190    'P n m b':['(00g)','(00g)0s0','(0b0)','(0b0)00s','(a00)','(a00)00s',
3191        '(a00)0ss','(a00)0s0','(1/20g)','(1/20g)0s0','(1/2b0)',],
3192    'P c n m':['(a00)','(a00)00s','(00g)','(00g)s00','(0b0)','(0b0)s00',
3193        '(0b0)s0s','(0b0)00s','(a1/20)','(a1/20)00s','(01/2g)',],
3194#54       
3195    'P c c a':['(00g)','(00g)s00','(0b0)','(0b0)s00','(a00)','(a00)0s0',
3196        '(a00)0ss','(a00)00s','(01/2g)','(1/2b0)',],
3197    'P b a a':['(a00)','(a00)0s0','(00g)','(00g)0s0','(0b0)','(0b0)00s',
3198        '(0b0)s0s','(0b0)s00','(a01/2)','(01/2g)',],
3199    'P b c b':['(0b0)','(0b0)00s','(a00)','(a00)00s','(00g)','(00g)s00',
3200        '(00g)ss0','(00g)0s0','(1/2b0)','(a01/2)',],
3201    'P b a b':['(0b0)','(0b0)s00','(00g)','(00g)s00','(a00)','(a00)00s',
3202        '(a00)0ss','(a00)0s0','(0b1/2)','(1/20g)',],
3203    'P c c b':['(00g)','(00g)0s0','(a00)','(a00)0s0','(0b0)','(0b0)s00',
3204        '(0b0)s0s','(0b0)00s','(1/20g)','(a1/20)',],
3205    'P c a a':['(a00)','(a00)00s','(0b0)','(0b0)00s','(00g)','(00g)0s0',
3206        '(00g)ss0','(00g)s00','(a1/20)','(0b1/2)',],
3207#55       
3208    'P b a m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0',
3209        '(a00)','(a00)00s','(a01/2)','(0b0)','(0b0)00s','(0b1/2)'],
3210    'P m c b':['(a00)','(a00)0s0','(a00)00s','(a00)0ss',
3211        '(0b0)','(0b0)s00','(1/2b0)','(00g)','(00g)s00','(1/20g)'],
3212    'P c m a':['(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s',
3213        '(a00)','(a00)0s0','(a1/20)','(00g)','(00g)0s0','(01/2g)'],
3214#56       
3215    'P c c n':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
3216        '(0b0)','(0b0)s00'],
3217    'P n a a':['(a00)','(a00)0s0','(a00)00s','(0b0)','(0b0)00s',
3218        '(00g)','(00g)0s0'],
3219    'P b n b':['(0b0)','(0b0)s00','(0b0)00s','(a00)','(a00)00s',
3220        '(00g)','(00g)s00'],
3221#57       
3222    'P c a m':['(00g)','(00g)0s0','(a00)','(a00)00s','(0b0)','(0b0)s00',
3223        '(0b0)ss0','(0b0)00s','(01/2g)','(a1/20)','(a1/20)00s',],
3224    'P m a b':['(a00)','(a00)00s','(0b0)','(0b0)s00','(00g)','(00g)0s0',
3225        '(00g)s0s','(00g)s00','(a01/2)','(0b1/2)','(0b1/2)s00',],
3226    'P c m b':['(0b0)','(0b0)s00','(00g)','(00g)0s0','(a00)','(a00)00s',
3227        '(a00)0ss','(a00)0s0','(1/2b0)','(1/20g)','(1/20g)0s0',],
3228    'P b m a':['(0b0)','(0b0)00s','(a00)','(a00)0s0','(00g)','(00g)s00',
3229        '(00g)ss0','(00g)0s0','(0b1/2)','(a01/2)','(a01/2)0s0',],
3230    'P m c a':['(a00)','(a00)0s0','(00g)','(00g)s00','(0b0)','(0b0)00s',
3231        '(0b0)s0s','(0b0)s00','(a1/20)','(01/2g)','(01/2g)s00'],
3232    'P b c m':['(00g)','(00g)s00','(0b0)','(0b0)00s','(a00)','(a00)0s0',
3233        '(a00)0ss','(a00)00s','(1/20g)','(1/2b0)','(1/2b0)00s',],
3234#58       
3235    'P n n m':['(00g)','(00g)s00','(00g)0s0','(a00)',
3236        '(a00)00s','(0b0)','(0b0)00s'],
3237    'P m n n':['(00g)','(00g)s00','(a00)','(a00)0s0',
3238        '(a00)00s','(0b0)','(0b0)s00'],
3239    'P n m n':['(00g)','(00g)0s0','(a00)','(a00)0s0',
3240        '(0b0)','(0b0)s00','(0b0)00s',],
3241#59 o@i
3242    'P m m n':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
3243        '(a01/2)','(a01/2)0s0','(0b0)','(0b0)s00','(0b1/2)','(0b1/2)s00',],
3244    'P n m m':['(a00)','(a00)0s0','(a00)00s','(a00)0ss','(00g)','(00g)0s0',
3245        '(1/20g)','(1/20g)0s0','(0b0)','(0b0)00s','(1/2b0)','(1/2b0)00s'],
3246    'P m n m':['(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s','(00g)','(00g)s00',
3247        '(01/2g)','(01/2g)s00','(a00)','(a00)00s','(a1/20)','(a1/20)00s'],
3248#60       
3249    'P b c n':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
3250        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
3251    'P n c a':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
3252        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
3253    'P b n a':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
3254        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
3255    'P c n b':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
3256        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
3257    'P c a n':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
3258        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
3259    'P n a b':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0',
3260        '(a00)00s','(0b0)','(0b0)s00','(0b0)00s'],
3261#61       
3262    'P b c a':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0','(a00)00s',
3263        '(0b0)','(0b0)s00','(0b0)00s'],
3264    'P c a b':['(00g)','(00g)s00','(00g)0s0','(a00)','(a00)0s0','(a00)00s',
3265        '(0b0)','(0b0)s00','(0b0)00s'],
3266#62       
3267    'P n m a':['(00g)','(00g)0s0','(a00)','(a00)0s0','(0b0)','(0b0)00s'],
3268    'P b n m':['(00g)','(00g)s00','(a00)','(a00)00s','(0b0)','(0b0)00s'],
3269    'P m c n':['(00g)','(00g)s00','(a00)','(a00)0s0','(0b0)','(0b0)s00'],
3270    'P n a m':['(00g)','(00g)0s0','(a00)','(a00)00s','(0b0)','(0b0)00s'],
3271    'P m n b':['(00g)','(00g)s00','(a00)','(a00)00s','(0b0)','(0b0)s00'],
3272    'P c m n':['(00g)','(00g)0s0','(a00)','(a00)0s0','(0b0)','(0b0)s00'],
3273#63
3274    'C m c m':['(00g)','(00g)s00','(10g)','(10g)s00','(a00)','(a00)00s','(a00)0ss','(a00)0s0','(0b0)','(0b0)00s','(0b0)s0s','(0b0)s00',],
3275    'A m m a':['(a00)','(a00)0s0','(a10)','(a10)0s0','(0b0)','(0b0)s00','(0b0)s0s','(00g)00s','(00g)','(00g)s00','(00g)ss0','(00g)0s0',],
3276    'B b m m':['(0b0)','(0b0)00s','(0b1)','(0b1)00s','(00g)','(00g)0s0','(00g)ss0','(00g)s00','(a00)','(a00)0s0','(a00)0ss','(a00)00s',],
3277    'B m m b':['(0b0)','(0b0)s00','(1b0)','(1b0)s00','(a00)','(a00)0s0','(a00)0ss','(a00)00s','(00g)','(00g)0s0','(00g)ss0','(00g)s00',],
3278    'C c m m':['(00g)','(00g)0s0','(01g)','(01g)0s0','(0b0)','(0b0)00s','(0b0)s0s','(0b0)s00','(a00)','(a00)00s','(a00)0ss','(a00)0s0',],
3279    'A m a m':['(a00)','(a00)00s','(a01)','(a01)00s','(00g)','(00g)s00','(00g)ss0','(00g)0s0','(0b0)','(0b0)s00','(0b0)s0s','(0b0)00s',],
3280#64       
3281    'C m c a':['(00g)','(00g)s00','(10g)','(10g)s00','(0b0)','(0b0)00s','(0b0)s0s','(0b0)s00','(a00)','(a00)00s','(a00)0ss','(a00)0s0',],
3282    'A b m a':['(a00)','(a00)0s0','(a10)','(a10)0s0','(00g)','(00g)s00','(00g)ss0','(00g)0s0','(0b0)','(0b0)s00','(0b0)s0s','(0b0)00s',],
3283    'B b c m':['(0b0)','(0b0)00s','(0b1)','(0b1)00s','(a00)','(a00)0s0','(a00)0ss','(a00)00s','(00g)','(00g)0s0','(00g)ss0','(00g)s00',],
3284    'B m a b':['(0b0)','(0b0)s00','(1b0)','(1b0)s00','(00g)','(00g)0s0','(00g)ss0','(00g)s00','(a00)','(a00)0s0','(a00)0ss','(a00)00s',],
3285    'C c m b':['(00g)','(00g)0s0','(01g)','(01g)0s0','(a00)','(a00)00s','(a00)0ss','(a00)0s0','(0b0)','(0b0)00s','(0b0)s0s','(0b0)s00',],
3286    'A c a m':['(a00)','(a00)00s','(a01)','(a01)00s','(0b0)','(0b0)s00','(0b0)s0s','(0b0)00s','(00g)','(00g)s00','(00g)ss0','(00g)0s0',],
3287#65       
3288    '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',],
3289    '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',],
3290    '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',],
3291#66       
3292    'C c c m':['(00g)','(00g)s00','(10g)','(10g)s00','(0b0)','(0b0)00s','(0b0)s0s','(0b0)s00',],
3293    'A m m a':['(a00)','(a00)0s0','(a10)','(a10)0s0','(00g)','(00g)s00','(00g)ss0','(00g)0s0',],
3294    'B b m b':['(0b0)','(0b0)00s','(0b1)','(0b1)00s','(a00)','(a00)0s0','(a00)0ss','(a00)00s',],
3295#67       
3296    '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',],
3297    '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',],
3298    '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',],
3299    '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',],
3300    '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',],
3301    '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',],
3302#68 o@i
3303    'C c c a':['(00g)','(00g)s00','(10g)','(01g)','(10g)s00','(01g)s00',
3304        '(a00)','(a00)s00','(a00)ss0','(a00)0s0','(0b0)','(0b0)s00','(0b0)ss0','(0b0)0s0'],
3305    'A b a a':['(a00)','(a00)s00','(a10)','(a01)','(a10)s00','(a01)s00',
3306        '(0b0)','(0b0)s00','(0b0)ss0','(0b0)0s0','(00g)','(00g)s00','(00g)ss0','(00g)0s0'],
3307    'B b c b':['(0b0)','(0b0)s00','(0b1)','(1b0)','(0b1)s00','(1b0)s00',
3308        '(00g)','(00g)s00','(00g)ss0','(0b0)0s0','(a00)','(a00)s00','(a00)ss0','(a00)0s0'],
3309    'B b a b':['(0b0)','(0b0)s00','(1b0)','(0b1)','(1b0)s00','(0b1)s00',
3310        '(a00)','(a00)s00','(a00)ss0','(a00)0s0','(00g)','(00g)s00','(00g)ss0','(00g)0s0'],
3311    'C c c b':['(00g)','(00g)ss0','(01g)','(10g)','(01g)s00','(10g)s00',
3312        '(0b0)','(0b0)s00','(0b0)ss0','(0b0)0s0','(a00)','(a00)s00','(a00)ss0','(a00)0s0'],
3313    'A c a a':['(a00)','(a00)ss0','(a01)','(a10)','(a01)s00','(a10)s00',
3314        '(00g)','(00g)s00','(00g)ss0','(00g)0s0','(0b0)','(0b0)s00','(0b0)ss0','(0b0)0s0'],
3315#69       
3316    'F m m m':['(00g)','(00g)s00','(00g)ss0','(a00)','(a00)s00',
3317        '(a00)ss0','(0b0)','(0b0)s00','(0b0)ss0',
3318        '(10g)','(10g)s00','(10g)ss0','(a10)','(a10)0s0',
3319        '(a10)00s','(a10)0ss','(0b1)','(0b1)s00','(0b1)00s','(0b1)s0s',
3320        '(01g)','(01g)s00','(01g)ss0','(a01)','(a01)0s0',
3321        '(a01)00s','(a01)0ss','(1b0)','(1b0)s00','(1b0)00s','(1b0)s0s'],
3322#70 o@i       
3323    'F d d d':['(00g)','(00g)s00','(a00)','(a00)s00','(0b0)','(0b0)s00'],       
3324#71
3325    'I m m m':['(00g)','(00g)s00','(00g)ss0','(a00)','(a00)0s0',
3326        '(a00)ss0','(0b0)','(0b0)s00','(0b0)ss0'],
3327#72       
3328    'I b 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 c b':['(a00)','(a00)0s0','(a00)00s','(a00)0ss','(0b0)','(0b0)00s',
3331        '(0b0)s00','(0b0)s0s','(00g)','(00g)0s0','(00g)s00','(00g)ss0'],
3332    'I c m a':['(0b0)','(0b0)00s','(0b0)s00','(0b0)s0s','(00g)','(00g)s00',
3333        '(00g)0s0','(00g)ss0','(a00)','(a00)00s','(a00)0s0','(a00)0ss'],
3334#73       
3335    'I b c a':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
3336        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
3337    'I c a b':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
3338        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
3339#74       
3340    'I m m a':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
3341        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
3342    'I b m m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
3343        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
3344    'I m c m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
3345        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
3346    'I m a m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
3347        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
3348    'I m m b':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
3349        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
3350    'I c m m':['(00g)','(00g)s00','(00g)0s0','(00g)ss0','(a00)','(a00)0s0',
3351        '(a00)00s','(a00)0ss','(0b0)','(0b0)s00','(0b0)00s','(0b0)s0s'],
3352#tetragonal - done & checked
3353#75
3354    'P 4':['(00g)','(00g)q','(00g)s','(1/21/2g)','(1/21/2g)q',],
3355#76
3356    'P 41':['(00g)','(1/21/2g)',],
3357#77
3358    'P 42':['(00g)','(00g)q','(1/21/2g)','(1/21/2g)q',],
3359#78
3360    'P 43':['(00g)','(1/21/2g)',],
3361#79
3362    'I 4':['(00g)','(00g)q','(00g)s',],
3363#80
3364    'I 41':['(00g)','(00g)q',],
3365#81
3366    'P -4':['(00g)','(1/21/2g)',],
3367#82
3368    'I -4':['(00g)',],
3369#83
3370    'P 4/m':['(00g)','(00g)s0','(1/21/2g)',],
3371#84
3372    'P 42/m':['(00g)','(1/21/2g)',],
3373#85 o@i q0 -> 00
3374    'P 4/n':['(00g)','(00g)s0','(1/21/2g)',], #q0?
3375#86 o@i q0 -> 00
3376    'P 42/n':['(00g)','(1/21/2g)',],      #q0?
3377#87
3378    'I 4/m':['(00g)','(00g)s0',],
3379#88
3380    'I 41/a':['(00g)',],
3381#89
3382    'P 4 2 2':['(00g)','(00g)q00','(00g)s00','(1/21/2g)','(1/21/2g)q00',],
3383#90
3384    'P 4 21 2':['(00g)','(00g)q00','(00g)s00',],
3385#91
3386    'P 41 2 2':['(00g)','(1/21/2g)',],
3387#92
3388    'P 41 21 2':['(00g)',],
3389#93
3390    'P 42 2 2':['(00g)','(00g)q00','(1/21/2g)','(1/21/2g)q00',],
3391#94
3392    'P 42 21 2':['(00g)','(00g)q00',],
3393#95
3394    'P 43 2 2':['(00g)','(1/21/2g)',],
3395#96
3396    'P 43 21 2':['(00g)',],
3397#97
3398    'I 4 2 2':['(00g)','(00g)q00','(00g)s00',],
3399#98
3400    'I 41 2 2':['(00g)','(00g)q00',],
3401#99
3402    'P 4 m m':['(00g)','(00g)ss0','(00g)0ss','(00g)s0s','(1/21/2g)','(1/21/2g)0ss'],
3403#100
3404    'P 4 b m':['(00g)','(00g)ss0','(00g)0ss','(00g)s0s','(1/21/2g)qq0','(1/21/2g)qqs',],
3405#101
3406    'P 42 c m':['(00g)','(00g)0ss','(1/21/2g)','(1/21/2g)0ss',],
3407#102
3408    'P 42 n m':['(00g)','(00g)0ss','(1/21/2g)qq0','(1/21/2g)qqs',],
3409#103
3410    'P 4 c c':['(00g)','(00g)ss0','(1/21/2g)',],
3411#104
3412    'P 4 n c':['(00