Changeset 763


Ignore:
Timestamp:
Sep 26, 2012 1:34:54 AM (9 years ago)
Author:
vondreele
Message:

change peak search algorithm - now much faster & more complete

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/GSASIImath.py

    r762 r763  
     1<<<<<<< .mine
    12# -*- coding: utf-8 -*-
    23#GSASIImath - major mathematics routines
     
    2425import GSASIIlattice as G2lat
    2526import GSASIIspc as G2spc
    26 import scipy.optimize as so
    27 import scipy.linalg as sl
    2827import numpy.fft as fft
    2928
     
    807806    return mapData
    808807   
     808def SearchMap(data):
     809    rollMap = lambda rho,roll: np.roll(np.roll(np.roll(rho,roll[0],axis=0),roll[1],axis=1),roll[2],axis=2)
     810   
     811    norm = 1./(np.sqrt(3.)*np.sqrt(2.*np.pi)**3)
     812   
     813    def noDuplicate(xyz,peaks,Amat):
     814        XYZ = np.inner(Amat,xyz)
     815        if True in [np.allclose(XYZ,np.inner(Amat,peak),atol=0.5) for peak in peaks]:
     816            print ' Peak',xyz,' <0.5A from another peak'
     817            return False
     818        return True
     819                           
     820    def fixSpecialPos(xyz,SGData,Amat):
     821        equivs = G2spc.GenAtom(xyz,SGData,Move=True)
     822        X = []
     823        xyzs = [equiv[0] for equiv in equivs]
     824        for x in xyzs:
     825            if np.sqrt(np.sum(np.inner(Amat,xyz-x)**2,axis=0))<0.5:
     826                X.append(x)
     827        if len(X) > 1:
     828            return np.average(X,axis=0)
     829        else:
     830            return xyz
     831       
     832    def rhoCalc(parms,rX,rY,rZ,res,SGLaue):
     833        Mag,x0,y0,z0,sig = parms
     834        return norm*Mag*np.exp(-((x0-rX)**2+(y0-rY)**2+(z0-rZ)**2)/(2.*sig**2))/(sig*res**3)
     835       
     836    def peakFunc(parms,rX,rY,rZ,rho,res,SGLaue):
     837        Mag,x0,y0,z0,sig = parms
     838        M = rho-rhoCalc(parms,rX,rY,rZ,res,SGLaue)
     839        return M
     840       
     841    def peakHess(parms,rX,rY,rZ,rho,res,SGLaue):
     842        Mag,x0,y0,z0,sig = parms
     843        dMdv = np.zeros(([5,]+list(rX.shape)))
     844        delt = .01
     845        for i in range(5):
     846            parms[i] -= delt
     847            rhoCm = rhoCalc(parms,rX,rY,rZ,res,SGLaue)
     848            parms[i] += 2.*delt
     849            rhoCp = rhoCalc(parms,rX,rY,rZ,res,SGLaue)
     850            parms[i] -= delt
     851            dMdv[i] = (rhoCp-rhoCm)/(2.*delt)
     852        rhoC = rhoCalc(parms,rX,rY,rZ,res,SGLaue)
     853        Vec = np.sum(np.sum(np.sum(dMdv*(rho-rhoC),axis=3),axis=2),axis=1)
     854        dMdv = np.reshape(dMdv,(5,rX.size))
     855        Hess = np.inner(dMdv,dMdv)
     856       
     857        return Vec,Hess
     858       
     859    generalData = data['General']
     860    phaseName = generalData['Name']
     861    SGData = generalData['SGData']
     862    Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
     863    drawingData = data['Drawing']
     864    peaks = []
     865    mags = []
     866    dzeros = []
     867    try:
     868        mapData = generalData['Map']
     869        contLevel = mapData['cutOff']*mapData['rhoMax']/100.
     870        rho = copy.copy(mapData['rho'])     #don't mess up original
     871        mapHalf = np.array(rho.shape)/2
     872        res = mapData['Resolution']
     873        incre = np.array(rho.shape,dtype=np.float)
     874        step = max(1.0,1./res)+1
     875        steps = np.array(3*[step,])
     876    except KeyError:
     877        print '**** ERROR - Fourier map not defined'
     878        return peaks,mags
     879    rhoMask = ma.array(rho,mask=(rho<contLevel))
     880    indices = (-1,0,1)
     881    rolls = np.array([[h,k,l] for h in indices for k in indices for l in indices])
     882    for roll in rolls:
     883        if np.any(roll):
     884            rhoMask = ma.array(rhoMask,mask=(rhoMask-rollMap(rho,roll)<=0.))
     885    indx = np.transpose(rhoMask.nonzero())
     886    peaks = indx/incre
     887    mags = rhoMask[rhoMask.nonzero()]
     888    for i,[ind,peak,mag] in enumerate(zip(indx,peaks,mags)):
     889        rho = rollMap(rho,ind)
     890        rMM = mapHalf-steps
     891        rMP = mapHalf+steps+1
     892        rhoPeak = rho[rMM[0]:rMP[0],rMM[1]:rMP[1],rMM[2]:rMP[2]]
     893        peakInt = np.sum(rhoPeak)*res**3
     894        rX,rY,rZ = np.mgrid[rMM[0]:rMP[0],rMM[1]:rMP[1],rMM[2]:rMP[2]]
     895        x0 = [peakInt,mapHalf[0],mapHalf[1],mapHalf[2],2.0]          #magnitude, position & width(sig)
     896        result = HessianLSQ(peakFunc,x0,Hess=peakHess,
     897            args=(rX,rY,rZ,rhoPeak,res,SGData['SGLaue']),ftol=.01,maxcyc=10)
     898        x1 = result[0]
     899        if not np.any(x1 < 0):
     900            mag = x1[0]
     901            peak = (np.array(x1[1:4])-ind)/incre
     902        peak = fixSpecialPos(peak,SGData,Amat)
     903        rho = rollMap(rho,-ind)       
     904    dzeros = np.sqrt(np.sum(np.inner(Amat,peaks)**2,axis=0))
     905    return np.array(peaks),np.array([mags,]).T,np.array([dzeros,]).T
     906   
     907def sortArray(data,pos,reverse=False):
     908    #data is a list of items
     909    #sort by pos in list; reverse if True
     910    T = []
     911    for i,M in enumerate(data):
     912        T.append((M[pos],i))
     913    D = dict(zip(T,data))
     914    T.sort()
     915    if reverse:
     916        T.reverse()
     917    X = []
     918    for key in T:
     919        X.append(D[key])
     920    return X
     921               
     922def PeaksUnique(data,Ind):
     923
     924    def noDuplicate(xyz,peaks,Amat):
     925        if True in [np.allclose(np.inner(Amat,xyz),np.inner(Amat,peak),atol=0.5) for peak in peaks]:
     926            return False
     927        return True
     928                           
     929    generalData = data['General']
     930    cell = generalData['Cell'][1:7]
     931    Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
     932    A = G2lat.cell2A(cell)
     933    SGData = generalData['SGData']
     934    mapPeaks = data['Map Peaks']
     935    Indx = {}
     936    XYZ = {}
     937    for ind in Ind:
     938        XYZ[ind] = np.array(mapPeaks[ind][1:4])
     939        Indx[ind] = True
     940    for ind in Ind:
     941        if Indx[ind]:
     942            xyz = XYZ[ind]
     943            for jnd in Ind:
     944                if ind != jnd and Indx[jnd]:                       
     945                    Equiv = G2spc.GenAtom(XYZ[jnd],SGData,Move=True)
     946                    xyzs = np.array([equiv[0] for equiv in Equiv])
     947                    Indx[jnd] = noDuplicate(xyz,xyzs,Amat)
     948    Ind = []
     949    for ind in Indx:
     950        if Indx[ind]:
     951            Ind.append(ind)
     952    return Ind
     953   
     954def prodQQ(QA,QB):
     955    ''' Grassman quaternion product
     956        QA,QB quaternions; q=r+ai+bj+ck
     957    '''
     958    D = np.zeros(4)
     959    D[0] = QA[0]*QB[0]-QA[1]*QB[1]-QA[2]*QB[2]-QA[3]*QB[3]
     960    D[1] = QA[0]*QB[1]+QA[1]*QB[0]+QA[2]*QB[3]-QA[3]*QB[2]
     961    D[2] = QA[0]*QB[2]-QA[1]*QB[3]+QA[2]*QB[0]+QA[3]*QB[1]
     962    D[3] = QA[0]*QB[3]+QA[1]*QB[2]-QA[2]*QB[1]+QA[3]*QB[0]
     963    return D
     964   
     965def normQ(QA):
     966    ''' get length of quaternion & normalize it
     967        q=r+ai+bj+ck
     968    '''
     969    n = np.sqrt(np.sum(np.array(QA)**2))
     970    return QA/n
     971   
     972def invQ(Q):
     973    '''
     974        get inverse of quaternion
     975        q=r+ai+bj+ck; q* = r-ai-bj-ck
     976    '''
     977    return Q*np.array([1,-1,-1,-1])
     978   
     979def prodQVQ(Q,V):
     980    ''' compute the quaternion vector rotation qvq-1 = v'
     981        q=r+ai+bj+ck
     982    '''
     983    VP = np.zeros(3)
     984    T2 = Q[0]*Q[1]
     985    T3 = Q[0]*Q[2]
     986    T4 = Q[0]*Q[3]
     987    T5 = -Q[1]*Q[1]
     988    T6 = Q[1]*Q[2]
     989    T7 = Q[1]*Q[3]
     990    T8 = -Q[2]*Q[2]
     991    T9 = Q[2]*Q[3]
     992    T10 = -Q[3]*Q[3]
     993    VP[0] = 2.*((T8+T10)*V[0]+(T6-T4)*V[1]+(T3+T7)*V[2])+V[0]
     994    VP[1] = 2.*((T4+T6)*V[0]+(T5+T10)*V[1]+(T9-T2)*V[2])+V[1]
     995    VP[2] = 2.*((T7-T3)*V[0]+(T2+T9)*V[1]+(T5+T8)*V[2])+V[2]
     996    return VP   
     997   
     998def Q2Mat(Q):
     999    ''' make rotation matrix from quaternion
     1000        q=r+ai+bj+ck
     1001    '''
     1002    aa = Q[0]**2
     1003    ab = Q[0]*Q[1]
     1004    ac = Q[0]*Q[2]
     1005    ad = Q[0]*Q[3]
     1006    bb = Q[1]**2
     1007    bc = Q[1]*Q[2]
     1008    bd = Q[1]*Q[3]
     1009    cc = Q[2]**2
     1010    cd = Q[2]*Q[3]
     1011    dd = Q[3]**2
     1012    M = [[aa+bb-cc-dd, 2.*(bc-ad),  2.*(ac+bd)],
     1013        [2*(ad+bc),   aa-bb+cc-dd,  2.*(cd-ab)],
     1014        [2*(bd-ac),    2.*(ab+cd), aa-bb-cc+dd]]
     1015    return np.array(M)
     1016   
     1017def AV2Q(A,V):
     1018    ''' convert angle (radians -pi to pi) & vector to quaternion
     1019        q=r+ai+bj+ck
     1020    '''
     1021    Q = np.zeros(4)
     1022    d = np.sqrt(np.sum(np.array(V)**2))
     1023    if d:
     1024        V /= d
     1025    else:
     1026        return [1.,0.,0.,0.]    #identity
     1027    p = A/2.
     1028    Q[0] = np.cos(p)
     1029    s = np.sin(p)
     1030    Q[1:4] = V*s
     1031    return Q
     1032   
     1033def AVdeg2Q(A,V):
     1034    ''' convert angle (degrees -180 to 180) & vector to quaternion
     1035        q=r+ai+bj+ck
     1036    '''
     1037    Q = np.zeros(4)
     1038    d = np.sqrt(np.sum(np.array(V)**2))
     1039    if d:
     1040        V /= d
     1041    else:
     1042        return [1.,0.,0.,0.]    #identity
     1043    p = A/2.
     1044    Q[0] = cosd(p)
     1045    S = sind(p)
     1046    Q[1:4] = V*S
     1047    return Q
     1048   
     1049=======
     1050# -*- coding: utf-8 -*-
     1051#GSASIImath - major mathematics routines
     1052########### SVN repository information ###################
     1053# $Date$
     1054# $Author$
     1055# $Revision$
     1056# $URL$
     1057# $Id$
     1058########### SVN repository information ###################
     1059import sys
     1060import os
     1061import os.path as ospath
     1062import random as rn
     1063import numpy as np
     1064import numpy.linalg as nl
     1065import numpy.ma as ma
     1066import cPickle
     1067import time
     1068import math
     1069import copy
     1070import GSASIIpath
     1071GSASIIpath.SetVersionNumber("$Revision$")
     1072import GSASIIElem as G2el
     1073import GSASIIlattice as G2lat
     1074import GSASIIspc as G2spc
     1075import scipy.optimize as so
     1076import scipy.linalg as sl
     1077import numpy.fft as fft
     1078
     1079sind = lambda x: np.sin(x*np.pi/180.)
     1080cosd = lambda x: np.cos(x*np.pi/180.)
     1081tand = lambda x: np.tan(x*np.pi/180.)
     1082asind = lambda x: 180.*np.arcsin(x)/np.pi
     1083acosd = lambda x: 180.*np.arccos(x)/np.pi
     1084atan2d = lambda y,x: 180.*np.arctan2(y,x)/np.pi
     1085
     1086def HessianLSQ(func,x0,Hess,args=(),ftol=1.49012e-8,xtol=1.49012e-8, maxcyc=0):
     1087   
     1088    """
     1089    Minimize the sum of squares of a set of equations.
     1090
     1091    ::
     1092   
     1093                    Nobs
     1094        x = arg min(sum(func(y)**2,axis=0))
     1095                    y=0
     1096
     1097    Parameters
     1098    ----------
     1099    func : callable
     1100        should take at least one (possibly length N vector) argument and
     1101        returns M floating point numbers.
     1102    x0 : ndarray
     1103        The starting estimate for the minimization of length N
     1104    Hess : callable
     1105        A required function or method to compute the weighted vector and Hessian for func.
     1106        It must be a symmetric NxN array
     1107    args : tuple
     1108        Any extra arguments to func are placed in this tuple.
     1109    ftol : float
     1110        Relative error desired in the sum of squares.
     1111    xtol : float
     1112        Relative error desired in the approximate solution.
     1113    maxcyc : int
     1114        The maximum number of cycles of refinement to execute, if -1 refine
     1115        until other limits are met (ftol, xtol)
     1116
     1117    Returns
     1118    -------
     1119    x : ndarray
     1120        The solution (or the result of the last iteration for an unsuccessful
     1121        call).
     1122    cov_x : ndarray
     1123        Uses the fjac and ipvt optional outputs to construct an
     1124        estimate of the jacobian around the solution.  ``None`` if a
     1125        singular matrix encountered (indicates very flat curvature in
     1126        some direction).  This matrix must be multiplied by the
     1127        residual standard deviation to get the covariance of the
     1128        parameter estimates -- see curve_fit.
     1129    infodict : dict
     1130        a dictionary of optional outputs with the key s::
     1131
     1132            - 'fvec' : the function evaluated at the output
     1133
     1134
     1135    Notes
     1136    -----
     1137
     1138    """
     1139               
     1140    x0 = np.array(x0, ndmin=1)      #might be redundant?
     1141    n = len(x0)
     1142    if type(args) != type(()):
     1143        args = (args,)
     1144       
     1145    icycle = 0
     1146    One = np.ones((n,n))
     1147    lam = 0.001
     1148    lamMax = lam
     1149    nfev = 0
     1150    while icycle < maxcyc:
     1151        lamMax = max(lamMax,lam)
     1152        M = func(x0,*args)
     1153        nfev += 1
     1154        chisq0 = np.sum(M**2)
     1155        Yvec,Amat = Hess(x0,*args)
     1156        Adiag = np.sqrt(np.diag(Amat))
     1157        psing = np.where(np.abs(Adiag) < 1.e-14,True,False)
     1158        if np.any(psing):                #hard singularity in matrix
     1159            return [x0,None,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'psing':psing}]
     1160        Anorm = np.outer(Adiag,Adiag)
     1161        Yvec /= Adiag
     1162        Amat /= Anorm       
     1163        while True:
     1164            Lam = np.eye(Amat.shape[0])*lam
     1165            Amatlam = Amat*(One+Lam)
     1166            try:
     1167                Xvec = nl.solve(Amatlam,Yvec)
     1168            except nl.LinAlgError:
     1169                print 'ouch #1'
     1170                psing = list(np.where(np.diag(nl.qr(Amatlam)[1]) < 1.e-14)[0])
     1171                return [x0,None,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'psing':psing}]
     1172            Xvec /= Adiag
     1173            M2 = func(x0+Xvec,*args)
     1174            nfev += 1
     1175            chisq1 = np.sum(M2**2)
     1176            if chisq1 > chisq0:
     1177                lam *= 10.
     1178            else:
     1179                x0 += Xvec
     1180                lam /= 10.
     1181                break
     1182        if (chisq0-chisq1)/chisq0 < ftol:
     1183            break
     1184        icycle += 1
     1185    M = func(x0,*args)
     1186    nfev += 1
     1187    Yvec,Amat = Hess(x0,*args)
     1188    try:
     1189        Bmat = nl.inv(Amat)
     1190        return [x0,Bmat,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'psing':[]}]
     1191    except nl.LinAlgError:
     1192        print 'ouch #2 linear algebra error in LS'
     1193        psing = []
     1194        if maxcyc:
     1195            psing = list(np.where(np.diag(nl.qr(Amat)[1]) < 1.e-14)[0])
     1196        return [x0,None,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'psing':psing}]
     1197   
     1198def getVCov(varyNames,varyList,covMatrix):
     1199    vcov = np.zeros((len(varyNames),len(varyNames)))
     1200    for i1,name1 in enumerate(varyNames):
     1201        for i2,name2 in enumerate(varyNames):
     1202            try:
     1203                vcov[i1][i2] = covMatrix[varyList.index(name1)][varyList.index(name2)]
     1204            except ValueError:
     1205                vcov[i1][i2] = 0.0
     1206    return vcov
     1207
     1208def getMass(generalData):
     1209    mass = 0.
     1210    for i,elem in enumerate(generalData['AtomTypes']):
     1211        mass += generalData['NoAtoms'][elem]*generalData['AtomMass'][i]
     1212    return mass   
     1213
     1214def getDensity(generalData):
     1215   
     1216    mass = getMass(generalData)
     1217    Volume = generalData['Cell'][7]
     1218    density = mass/(0.6022137*Volume)
     1219    return density,Volume/mass
     1220   
     1221def getRestDist(XYZ,Amat):
     1222    return np.sqrt(np.sum(np.inner(Amat,(XYZ[1]-XYZ[0]))**2))
     1223
     1224def getRestAngle(XYZ,Amat):
     1225   
     1226    def calcVec(Ox,Tx,Amat):
     1227        return np.inner(Amat,(Tx-Ox))
     1228
     1229    VecA = calcVec(XYZ[1],XYZ[0],Amat)
     1230    VecA /= np.sqrt(np.sum(VecA**2))
     1231    VecB = calcVec(XYZ[1],XYZ[2],Amat)
     1232    VecB /= np.sqrt(np.sum(VecB**2))
     1233    edge = VecB-VecA
     1234    edge = np.sum(edge**2)
     1235    angle = (2.-edge)/2.
     1236    angle = max(angle,-1.)
     1237    return acosd(angle)
     1238   
     1239def getRestPlane(XYZ,Amat):
     1240    sumXYZ = np.zeros(3)
     1241    for xyz in XYZ:
     1242        sumXYZ += xyz
     1243    sumXYZ /= len(XYZ)
     1244    XYZ = np.array(XYZ)-sumXYZ
     1245    XYZ = np.inner(Amat,XYZ).T
     1246    Zmat = np.zeros((3,3))
     1247    for i,xyz in enumerate(XYZ):
     1248        Zmat += np.outer(xyz.T,xyz)
     1249    Evec,Emat = nl.eig(Zmat)
     1250    Evec = np.sqrt(Evec)/(len(XYZ)-3)
     1251    Order = np.argsort(Evec)
     1252    return Evec[Order[0]]
     1253   
     1254def getRestChiral(XYZ,Amat):
     1255   
     1256    VecA = np.empty((3,3))   
     1257    VecA[0] = np.inner(XYZ[1]-XYZ[0],Amat)
     1258    VecA[1] = np.inner(XYZ[2]-XYZ[0],Amat)
     1259    VecA[2] = np.inner(XYZ[3]-XYZ[0],Amat)
     1260    return nl.det(VecA)
     1261       
     1262def getDistDerv(Oxyz,Txyz,Amat,Tunit,Top,SGData):
     1263   
     1264    def calcDist(Ox,Tx,U,inv,C,M,T,Amat):
     1265        TxT = inv*(np.inner(M,Tx)+T)+C+U
     1266        return np.sqrt(np.sum(np.inner(Amat,(TxT-Ox))**2))
     1267       
     1268    inv = Top/abs(Top)
     1269    cent = abs(Top)/100
     1270    op = abs(Top)%100-1
     1271    M,T = SGData['SGOps'][op]
     1272    C = SGData['SGCen'][cent]
     1273    dx = .00001
     1274    deriv = np.zeros(6)
     1275    for i in [0,1,2]:
     1276        Oxyz[i] += dx
     1277        d0 = calcDist(Oxyz,Txyz,Tunit,inv,C,M,T,Amat)
     1278        Oxyz[i] -= 2*dx
     1279        deriv[i] = (calcDist(Oxyz,Txyz,Tunit,inv,C,M,T,Amat)-d0)/(2.*dx)
     1280        Oxyz[i] += dx
     1281        Txyz[i] += dx
     1282        d0 = calcDist(Oxyz,Txyz,Tunit,inv,C,M,T,Amat)
     1283        Txyz[i] -= 2*dx
     1284        deriv[i+3] = (calcDist(Oxyz,Txyz,Tunit,inv,C,M,T,Amat)-d0)/(2.*dx)
     1285        Txyz[i] += dx
     1286    return deriv
     1287   
     1288def getAngSig(VA,VB,Amat,SGData,covData={}):
     1289   
     1290    def calcVec(Ox,Tx,U,inv,C,M,T,Amat):
     1291        TxT = inv*(np.inner(M,Tx)+T)+C
     1292        TxT = G2spc.MoveToUnitCell(TxT)+U
     1293        return np.inner(Amat,(TxT-Ox))
     1294       
     1295    def calcAngle(Ox,TxA,TxB,unitA,unitB,invA,CA,MA,TA,invB,CB,MB,TB,Amat):
     1296        VecA = calcVec(Ox,TxA,unitA,invA,CA,MA,TA,Amat)
     1297        VecA /= np.sqrt(np.sum(VecA**2))
     1298        VecB = calcVec(Ox,TxB,unitB,invB,CB,MB,TB,Amat)
     1299        VecB /= np.sqrt(np.sum(VecB**2))
     1300        edge = VecB-VecA
     1301        edge = np.sum(edge**2)
     1302        angle = (2.-edge)/2.
     1303        angle = max(angle,-1.)
     1304        return acosd(angle)
     1305       
     1306    OxAN,OxA,TxAN,TxA,unitA,TopA = VA
     1307    OxBN,OxB,TxBN,TxB,unitB,TopB = VB
     1308    invA = invB = 1
     1309    invA = TopA/abs(TopA)
     1310    invB = TopB/abs(TopB)
     1311    centA = abs(TopA)/100
     1312    centB = abs(TopB)/100
     1313    opA = abs(TopA)%100-1
     1314    opB = abs(TopB)%100-1
     1315    MA,TA = SGData['SGOps'][opA]
     1316    MB,TB = SGData['SGOps'][opB]
     1317    CA = SGData['SGCen'][centA]
     1318    CB = SGData['SGCen'][centB]
     1319    if 'covMatrix' in covData:
     1320        covMatrix = covData['covMatrix']
     1321        varyList = covData['varyList']
     1322        AngVcov = getVCov(OxAN+TxAN+TxBN,varyList,covMatrix)
     1323        dx = .00001
     1324        dadx = np.zeros(9)
     1325        Ang = calcAngle(OxA,TxA,TxB,unitA,unitB,invA,CA,MA,TA,invB,CB,MB,TB,Amat)
     1326        for i in [0,1,2]:
     1327            OxA[i] += dx
     1328            a0 = calcAngle(OxA,TxA,TxB,unitA,unitB,invA,CA,MA,TA,invB,CB,MB,TB,Amat)
     1329            OxA[i] -= 2*dx
     1330            dadx[i] = (calcAngle(OxA,TxA,TxB,unitA,unitB,invA,CA,MA,TA,invB,CB,MB,TB,Amat)-a0)/dx
     1331            OxA[i] += dx
     1332           
     1333            TxA[i] += dx
     1334            a0 = calcAngle(OxA,TxA,TxB,unitA,unitB,invA,CA,MA,TA,invB,CB,MB,TB,Amat)
     1335            TxA[i] -= 2*dx
     1336            dadx[i+3] = (calcAngle(OxA,TxA,TxB,unitA,unitB,invA,CA,MA,TA,invB,CB,MB,TB,Amat)-a0)/dx
     1337            TxA[i] += dx
     1338           
     1339            TxB[i] += dx
     1340            a0 = calcAngle(OxA,TxA,TxB,unitA,unitB,invA,CA,MA,TA,invB,CB,MB,TB,Amat)
     1341            TxB[i] -= 2*dx
     1342            dadx[i+6] = (calcAngle(OxA,TxA,TxB,unitA,unitB,invA,CA,MA,TA,invB,CB,MB,TB,Amat)-a0)/dx
     1343            TxB[i] += dx
     1344           
     1345        sigAng = np.sqrt(np.inner(dadx,np.inner(AngVcov,dadx)))
     1346        if sigAng < 0.01:
     1347            sigAng = 0.0
     1348        return Ang,sigAng
     1349    else:
     1350        return calcAngle(OxA,TxA,TxB,unitA,unitB,invA,CA,MA,TA,invB,CB,MB,TB,Amat),0.0
     1351
     1352def GetDistSig(Oatoms,Atoms,Amat,SGData,covData={}):
     1353
     1354    def calcDist(Atoms,SyOps,Amat):
     1355        XYZ = []
     1356        for i,atom in enumerate(Atoms):
     1357            Inv,M,T,C,U = SyOps[i]
     1358            XYZ.append(np.array(atom[1:4]))
     1359            XYZ[-1] = Inv*(np.inner(M,np.array(XYZ[-1]))+T)+C+U
     1360            XYZ[-1] = np.inner(Amat,XYZ[-1]).T
     1361        V1 = XYZ[1]-XYZ[0]
     1362        return np.sqrt(np.sum(V1**2))
     1363       
     1364    Inv = []
     1365    SyOps = []
     1366    names = []
     1367    for i,atom in enumerate(Oatoms):
     1368        names += atom[-1]
     1369        Op,unit = Atoms[i][-1]
     1370        inv = Op/abs(Op)
     1371        m,t = SGData['SGOps'][abs(Op)%100-1]
     1372        c = SGData['SGCen'][abs(Op)/100]
     1373        SyOps.append([inv,m,t,c,unit])
     1374    Dist = calcDist(Oatoms,SyOps,Amat)
     1375   
     1376    sig = -0.001
     1377    if 'covMatrix' in covData:
     1378        parmNames = []
     1379        dx = .00001
     1380        dadx = np.zeros(6)
     1381        for i in range(6):
     1382            ia = i/3
     1383            ix = i%3
     1384            Oatoms[ia][ix+1] += dx
     1385            a0 = calcDist(Oatoms,SyOps,Amat)
     1386            Oatoms[ia][ix+1] -= 2*dx
     1387            dadx[i] = (calcDist(Oatoms,SyOps,Amat)-a0)/(2.*dx)
     1388        covMatrix = covData['covMatrix']
     1389        varyList = covData['varyList']
     1390        DistVcov = getVCov(names,varyList,covMatrix)
     1391        sig = np.sqrt(np.inner(dadx,np.inner(DistVcov,dadx)))
     1392        if sig < 0.001:
     1393            sig = -0.001
     1394   
     1395    return Dist,sig
     1396
     1397def GetAngleSig(Oatoms,Atoms,Amat,SGData,covData={}):
     1398       
     1399    def calcAngle(Atoms,SyOps,Amat):
     1400        XYZ = []
     1401        for i,atom in enumerate(Atoms):
     1402            Inv,M,T,C,U = SyOps[i]
     1403            XYZ.append(np.array(atom[1:4]))
     1404            XYZ[-1] = Inv*(np.inner(M,np.array(XYZ[-1]))+T)+C+U
     1405            XYZ[-1] = np.inner(Amat,XYZ[-1]).T
     1406        V1 = XYZ[1]-XYZ[0]
     1407        V1 /= np.sqrt(np.sum(V1**2))
     1408        V2 = XYZ[1]-XYZ[2]
     1409        V2 /= np.sqrt(np.sum(V2**2))
     1410        V3 = V2-V1
     1411        cang = min(1.,max((2.-np.sum(V3**2))/2.,-1.))
     1412        return acosd(cang)
     1413
     1414    Inv = []
     1415    SyOps = []
     1416    names = []
     1417    for i,atom in enumerate(Oatoms):
     1418        names += atom[-1]
     1419        Op,unit = Atoms[i][-1]
     1420        inv = Op/abs(Op)
     1421        m,t = SGData['SGOps'][abs(Op)%100-1]
     1422        c = SGData['SGCen'][abs(Op)/100]
     1423        SyOps.append([inv,m,t,c,unit])
     1424    Angle = calcAngle(Oatoms,SyOps,Amat)
     1425   
     1426    sig = -0.01
     1427    if 'covMatrix' in covData:
     1428        parmNames = []
     1429        dx = .00001
     1430        dadx = np.zeros(9)
     1431        for i in range(9):
     1432            ia = i/3
     1433            ix = i%3
     1434            Oatoms[ia][ix+1] += dx
     1435            a0 = calcAngle(Oatoms,SyOps,Amat)
     1436            Oatoms[ia][ix+1] -= 2*dx
     1437            dadx[i] = (calcAngle(Oatoms,SyOps,Amat)-a0)/(2.*dx)
     1438        covMatrix = covData['covMatrix']
     1439        varyList = covData['varyList']
     1440        AngVcov = getVCov(names,varyList,covMatrix)
     1441        sig = np.sqrt(np.inner(dadx,np.inner(AngVcov,dadx)))
     1442        if sig < 0.01:
     1443            sig = -0.01
     1444   
     1445    return Angle,sig
     1446
     1447def GetTorsionSig(Oatoms,Atoms,Amat,SGData,covData={}):
     1448   
     1449    def calcTorsion(Atoms,SyOps,Amat):
     1450       
     1451        XYZ = []
     1452        for i,atom in enumerate(Atoms):
     1453            Inv,M,T,C,U = SyOps[i]
     1454            XYZ.append(np.array(atom[1:4]))
     1455            XYZ[-1] = Inv*(np.inner(M,np.array(XYZ[-1]))+T)+C+U
     1456            XYZ[-1] = np.inner(Amat,XYZ[-1]).T
     1457        V1 = XYZ[1]-XYZ[0]
     1458        V2 = XYZ[2]-XYZ[1]
     1459        V3 = XYZ[3]-XYZ[2]
     1460        V1 /= np.sqrt(np.sum(V1**2))
     1461        V2 /= np.sqrt(np.sum(V2**2))
     1462        V3 /= np.sqrt(np.sum(V3**2))
     1463        M = np.array([V1,V2,V3])
     1464        D = nl.det(M)
     1465        Ang = 1.0
     1466        P12 = np.dot(V1,V2)
     1467        P13 = np.dot(V1,V3)
     1468        P23 = np.dot(V2,V3)
     1469        Tors = acosd((P12*P23-P13)/(np.sqrt(1.-P12**2)*np.sqrt(1.-P23**2)))*D/abs(D)
     1470        return Tors
     1471           
     1472    Inv = []
     1473    SyOps = []
     1474    names = []
     1475    for i,atom in enumerate(Oatoms):
     1476        names += atom[-1]
     1477        Op,unit = Atoms[i][-1]
     1478        inv = Op/abs(Op)
     1479        m,t = SGData['SGOps'][abs(Op)%100-1]
     1480        c = SGData['SGCen'][abs(Op)/100]
     1481        SyOps.append([inv,m,t,c,unit])
     1482    Tors = calcTorsion(Oatoms,SyOps,Amat)
     1483   
     1484    sig = -0.01
     1485    if 'covMatrix' in covData:
     1486        parmNames = []
     1487        dx = .00001
     1488        dadx = np.zeros(12)
     1489        for i in range(12):
     1490            ia = i/3
     1491            ix = i%3
     1492            Oatoms[ia][ix+1] += dx
     1493            a0 = calcTorsion(Oatoms,SyOps,Amat)
     1494            Oatoms[ia][ix+1] -= 2*dx
     1495            dadx[i] = (calcTorsion(Oatoms,SyOps,Amat)-a0)/(2.*dx)
     1496        covMatrix = covData['covMatrix']
     1497        varyList = covData['varyList']
     1498        TorVcov = getVCov(names,varyList,covMatrix)
     1499        sig = np.sqrt(np.inner(dadx,np.inner(TorVcov,dadx)))
     1500        if sig < 0.01:
     1501            sig = -0.01
     1502   
     1503    return Tors,sig
     1504       
     1505def GetDATSig(Oatoms,Atoms,Amat,SGData,covData={}):
     1506   
     1507    def calcDist(Atoms,SyOps,Amat):
     1508        XYZ = []
     1509        for i,atom in enumerate(Atoms):
     1510            Inv,M,T,C,U = SyOps[i]
     1511            XYZ.append(np.array(atom[1:4]))
     1512            XYZ[-1] = Inv*(np.inner(M,np.array(XYZ[-1]))+T)+C+U
     1513            XYZ[-1] = np.inner(Amat,XYZ[-1]).T
     1514        V1 = XYZ[1]-XYZ[0]
     1515        return np.sqrt(np.sum(V1**2))
     1516       
     1517    def calcAngle(Atoms,SyOps,Amat):
     1518        XYZ = []
     1519        for i,atom in enumerate(Atoms):
     1520            Inv,M,T,C,U = SyOps[i]
     1521            XYZ.append(np.array(atom[1:4]))
     1522            XYZ[-1] = Inv*(np.inner(M,np.array(XYZ[-1]))+T)+C+U
     1523            XYZ[-1] = np.inner(Amat,XYZ[-1]).T
     1524        V1 = XYZ[1]-XYZ[0]
     1525        V1 /= np.sqrt(np.sum(V1**2))
     1526        V2 = XYZ[1]-XYZ[2]
     1527        V2 /= np.sqrt(np.sum(V2**2))
     1528        V3 = V2-V1
     1529        cang = min(1.,max((2.-np.sum(V3**2))/2.,-1.))
     1530        return acosd(cang)
     1531
     1532    def calcTorsion(Atoms,SyOps,Amat):
     1533       
     1534        XYZ = []
     1535        for i,atom in enumerate(Atoms):
     1536            Inv,M,T,C,U = SyOps[i]
     1537            XYZ.append(np.array(atom[1:4]))
     1538            XYZ[-1] = Inv*(np.inner(M,np.array(XYZ[-1]))+T)+C+U
     1539            XYZ[-1] = np.inner(Amat,XYZ[-1]).T
     1540        V1 = XYZ[1]-XYZ[0]
     1541        V2 = XYZ[2]-XYZ[1]
     1542        V3 = XYZ[3]-XYZ[2]
     1543        V1 /= np.sqrt(np.sum(V1**2))
     1544        V2 /= np.sqrt(np.sum(V2**2))
     1545        V3 /= np.sqrt(np.sum(V3**2))
     1546        M = np.array([V1,V2,V3])
     1547        D = nl.det(M)
     1548        Ang = 1.0
     1549        P12 = np.dot(V1,V2)
     1550        P13 = np.dot(V1,V3)
     1551        P23 = np.dot(V2,V3)
     1552        Tors = acosd((P12*P23-P13)/(np.sqrt(1.-P12**2)*np.sqrt(1.-P23**2)))*D/abs(D)
     1553        return Tors
     1554           
     1555    Inv = []
     1556    SyOps = []
     1557    names = []
     1558    for i,atom in enumerate(Oatoms):
     1559        names += atom[-1]
     1560        Op,unit = Atoms[i][-1]
     1561        inv = Op/abs(Op)
     1562        m,t = SGData['SGOps'][abs(Op)%100-1]
     1563        c = SGData['SGCen'][abs(Op)/100]
     1564        SyOps.append([inv,m,t,c,unit])
     1565    M = len(Oatoms)
     1566    if M == 2:
     1567        Val = calcDist(Oatoms,SyOps,Amat)
     1568    elif M == 3:
     1569        Val = calcAngle(Oatoms,SyOps,Amat)
     1570    else:
     1571        Val = calcTorsion(Oatoms,SyOps,Amat)
     1572   
     1573    sigVals = [-0.001,-0.01,-0.01]
     1574    sig = sigVals[M-3]
     1575    if 'covMatrix' in covData:
     1576        parmNames = []
     1577        dx = .00001
     1578        N = M*3
     1579        dadx = np.zeros(N)
     1580        for i in range(N):
     1581            ia = i/3
     1582            ix = i%3
     1583            Oatoms[ia][ix+1] += dx
     1584            if M == 2:
     1585                a0 = calcDist(Oatoms,SyOps,Amat)
     1586            elif M == 3:
     1587                a0 = calcAngle(Oatoms,SyOps,Amat)
     1588            else:
     1589                a0 = calcTorsion(Oatoms,SyOps,Amat)
     1590            Oatoms[ia][ix+1] -= 2*dx
     1591            if M == 2:
     1592                dadx[i] = (calcDist(Oatoms,SyOps,Amat)-a0)/(2.*dx)               
     1593            elif M == 3:
     1594                dadx[i] = (calcAngle(Oatoms,SyOps,Amat)-a0)/(2.*dx)               
     1595            else:
     1596                dadx[i] = (calcTorsion(Oatoms,SyOps,Amat)-a0)/(2.*dx)
     1597        covMatrix = covData['covMatrix']
     1598        varyList = covData['varyList']
     1599        Vcov = getVCov(names,varyList,covMatrix)
     1600        sig = np.sqrt(np.inner(dadx,np.inner(Vcov,dadx)))
     1601        if sig < sigVals[M-3]:
     1602            sig = sigVals[M-3]
     1603   
     1604    return Val,sig
     1605       
     1606   
     1607def ValEsd(value,esd=0,nTZ=False):                  #NOT complete - don't use
     1608    # returns value(esd) string; nTZ=True for no trailing zeros
     1609    # use esd < 0 for level of precision shown e.g. esd=-0.01 gives 2 places beyond decimal
     1610    #get the 2 significant digits in the esd
     1611    edig = lambda esd: int(round(10**(math.log10(esd) % 1+1)))
     1612    #get the number of digits to represent them
     1613    epl = lambda esd: 2+int(1.545-math.log10(10*edig(esd)))
     1614   
     1615    mdec = lambda esd: -int(round(math.log10(abs(esd))))+1
     1616    ndec = lambda esd: int(1.545-math.log10(abs(esd)))
     1617    if esd > 0:
     1618        fmt = '"%.'+str(ndec(esd))+'f(%d)"'
     1619        return str(fmt%(value,int(round(esd*10**(mdec(esd)))))).strip('"')
     1620    elif esd < 0:
     1621         return str(round(value,mdec(esd)-1))
     1622    else:
     1623        text = str("%f"%(value))
     1624        if nTZ:
     1625            return text.rstrip('0')
     1626        else:
     1627            return text
     1628           
     1629def adjHKLmax(SGData,Hmax):
     1630    if SGData['SGLaue'] in ['3','3m1','31m','6/m','6/mmm']:
     1631        Hmax[0] = ((Hmax[0]+3)/6)*6
     1632        Hmax[1] = ((Hmax[1]+3)/6)*6
     1633        Hmax[2] = ((Hmax[2]+1)/4)*4
     1634    else:
     1635        Hmax[0] = ((Hmax[0]+2)/4)*4
     1636        Hmax[1] = ((Hmax[1]+2)/4)*4
     1637        Hmax[2] = ((Hmax[2]+1)/4)*4
     1638
     1639def FourierMap(data,reflData):
     1640   
     1641    generalData = data['General']
     1642    if not generalData['Map']['MapType']:
     1643        print '**** ERROR - Fourier map not defined'
     1644        return
     1645    mapData = generalData['Map']
     1646    dmin = mapData['Resolution']
     1647    SGData = generalData['SGData']
     1648    cell = generalData['Cell'][1:8]       
     1649    A = G2lat.cell2A(cell[:6])
     1650    Hmax = np.asarray(G2lat.getHKLmax(dmin,SGData,A),dtype='i')+1
     1651    adjHKLmax(SGData,Hmax)
     1652    Fhkl = np.zeros(shape=2*Hmax,dtype='c16')
     1653#    Fhkl[0,0,0] = generalData['F000X']
     1654    time0 = time.time()
     1655    for ref in reflData:
     1656        if ref[4] >= dmin:
     1657            Fosq,Fcsq,ph = ref[8:11]
     1658            for i,hkl in enumerate(ref[11]):
     1659                hkl = np.asarray(hkl,dtype='i')
     1660                dp = 360.*ref[12][i]
     1661                a = cosd(ph+dp)
     1662                b = sind(ph+dp)
     1663                phasep = complex(a,b)
     1664                phasem = complex(a,-b)
     1665                if 'Fobs' in mapData['MapType']:
     1666                    F = np.sqrt(Fosq)
     1667                    h,k,l = hkl+Hmax
     1668                    Fhkl[h,k,l] = F*phasep
     1669                    h,k,l = -hkl+Hmax
     1670                    Fhkl[h,k,l] = F*phasem
     1671                elif 'Fcalc' in mapData['MapType']:
     1672                    F = np.sqrt(Fcsq)
     1673                    h,k,l = hkl+Hmax
     1674                    Fhkl[h,k,l] = F*phasep
     1675                    h,k,l = -hkl+Hmax
     1676                    Fhkl[h,k,l] = F*phasem
     1677                elif 'delt-F' in mapData['MapType']:
     1678                    dF = np.sqrt(Fosq)-np.sqrt(Fcsq)
     1679                    h,k,l = hkl+Hmax
     1680                    Fhkl[h,k,l] = dF*phasep
     1681                    h,k,l = -hkl+Hmax
     1682                    Fhkl[h,k,l] = dF*phasem
     1683                elif '2*Fo-Fc' in mapData['MapType']:
     1684                    F = 2.*np.sqrt(Fosq)-np.sqrt(Fcsq)
     1685                    h,k,l = hkl+Hmax
     1686                    Fhkl[h,k,l] = F*phasep
     1687                    h,k,l = -hkl+Hmax
     1688                    Fhkl[h,k,l] = F*phasem
     1689                elif 'Patterson' in mapData['MapType']:
     1690                    h,k,l = hkl+Hmax
     1691                    Fhkl[h,k,l] = complex(Fosq,0.)
     1692                    h,k,l = -hkl+Hmax
     1693                    Fhkl[h,k,l] = complex(Fosq,0.)
     1694    rho = fft.fftn(fft.fftshift(Fhkl))/cell[6]
     1695    print 'Fourier map time: %.4f'%(time.time()-time0),'no. elements: %d'%(Fhkl.size)
     1696    mapData['rho'] = np.real(rho)
     1697    mapData['rhoMax'] = max(np.max(mapData['rho']),-np.min(mapData['rho']))
     1698    return mapData
     1699   
     1700# map printing for testing purposes
     1701def printRho(SGLaue,rho,rhoMax):                         
     1702    dim = len(rho.shape)
     1703    if dim == 2:
     1704        ix,jy = rho.shape
     1705        for j in range(jy):
     1706            line = ''
     1707            if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
     1708                line += (jy-j)*'  '
     1709            for i in range(ix):
     1710                r = int(100*rho[i,j]/rhoMax)
     1711                line += '%4d'%(r)
     1712            print line+'\n'
     1713    else:
     1714        ix,jy,kz = rho.shape
     1715        for k in range(kz):
     1716            print 'k = ',k
     1717            for j in range(jy):
     1718                line = ''
     1719                if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
     1720                    line += (jy-j)*'  '
     1721                for i in range(ix):
     1722                    r = int(100*rho[i,j,k]/rhoMax)
     1723                    line += '%4d'%(r)
     1724                print line+'\n'
     1725## keep this
     1726               
     1727def findOffset(SGData,A,Fhkl):   
     1728    if SGData['SpGrp'] == 'P 1':
     1729        return [0,0,0]   
     1730    hklShape = Fhkl.shape
     1731    steps = np.array(hklShape)
     1732    Hmax = 2*np.asarray(G2lat.getHKLmax(4.5,SGData,A),dtype='i')
     1733    Fmax = np.max(np.absolute(Fhkl))
     1734    hklHalf = np.array(hklShape)/2
     1735    sortHKL = np.argsort(Fhkl.flatten())
     1736    Fdict = {}
     1737    for hkl in sortHKL:
     1738        HKL = np.unravel_index(hkl,hklShape)
     1739        F = Fhkl[HKL[0]][HKL[1]][HKL[2]]
     1740        if F == 0.:
     1741            break
     1742        Fdict['%.6f'%(np.absolute(F))] = hkl
     1743    Flist = np.flipud(np.sort(Fdict.keys()))
     1744    F = str(1.e6)
     1745    i = 0
     1746    DH = []
     1747    Dphi = []
     1748    while i < 20 and len(DH) < 30:
     1749        F = Flist[i]
     1750        hkl = np.unravel_index(Fdict[F],hklShape)
     1751        iabsnt,mulp,Uniq,Phi = G2spc.GenHKLf(list(hkl-hklHalf),SGData)
     1752        Uniq = np.array(Uniq,dtype='i')
     1753        Phi = np.array(Phi)
     1754        Uniq = np.concatenate((Uniq,-Uniq))+hklHalf         # put in Friedel pairs & make as index to Farray
     1755        Phi = np.concatenate((Phi,-Phi))                      # and their phase shifts
     1756        Fh0 = Fhkl[hkl[0],hkl[1],hkl[2]]
     1757        ang0 = np.angle(Fh0,deg=True)/360.
     1758        for j,H in enumerate(Uniq[1:]):
     1759            ang = (np.angle(Fhkl[H[0],H[1],H[2]],deg=True)/360.-Phi[j+1])
     1760            dH = H-hkl
     1761            dang = ang-ang0
     1762            if np.any(np.abs(dH)-Hmax > 0):    #keep low order DHs
     1763                continue
     1764            DH.append(dH)
     1765            Dphi.append((dang+0.5) % 1.0)
     1766        i += 1
     1767    DH = np.array(DH)
     1768    print ' map offset no.of terms: %d'%(len(DH))
     1769    Dphi = np.array(Dphi)
     1770    X,Y,Z = np.mgrid[0:1:1./steps[0],0:1:1./steps[1],0:1:1./steps[2]]
     1771    XYZ = np.array(zip(X.flatten(),Y.flatten(),Z.flatten()))
     1772    Mmap = np.reshape(np.sum(((np.dot(XYZ,DH.T)+.5)%1.-Dphi)**2,axis=1),newshape=steps)
     1773    chisq = np.min(Mmap)
     1774    DX = -np.array(np.unravel_index(np.argmin(Mmap),Mmap.shape))
     1775    print ' map offset chi**2: %.3f, map offset: %d %d %d'%(chisq,DX[0],DX[1],DX[2])
     1776    return DX
     1777   
     1778def ChargeFlip(data,reflData,pgbar):
     1779    generalData = data['General']
     1780    mapData = generalData['Map']
     1781    flipData = generalData['Flip']
     1782    FFtable = {}
     1783    if 'None' not in flipData['Norm element']:
     1784        normElem = flipData['Norm element'].upper()
     1785        FFs = G2el.GetFormFactorCoeff(normElem.split('+')[0].split('-')[0])
     1786        for ff in FFs:
     1787            if ff['Symbol'] == normElem:
     1788                FFtable.update(ff)
     1789    dmin = flipData['Resolution']
     1790    SGData = generalData['SGData']
     1791    cell = generalData['Cell'][1:8]       
     1792    A = G2lat.cell2A(cell[:6])
     1793    Vol = cell[6]
     1794    Hmax = np.asarray(G2lat.getHKLmax(dmin,SGData,A),dtype='i')+1
     1795    adjHKLmax(SGData,Hmax)
     1796    Ehkl = np.zeros(shape=2*Hmax,dtype='c16')       #2X64bits per complex no.
     1797    time0 = time.time()
     1798    for ref in reflData:
     1799        dsp = ref[4]
     1800        if dsp >= dmin:
     1801            ff = 0.1*Vol    #est. no. atoms for ~10A**3/atom
     1802            if FFtable:
     1803                SQ = 0.25/dsp**2
     1804                ff *= G2el.ScatFac(FFtable,SQ)[0]
     1805            if ref[8] > 0.:
     1806                E = np.sqrt(ref[8])/ff
     1807            else:
     1808                E = 0.
     1809            ph = ref[10]
     1810            ph = rn.uniform(0.,360.)
     1811            for i,hkl in enumerate(ref[11]):
     1812                hkl = np.asarray(hkl,dtype='i')
     1813                dp = 360.*ref[12][i]
     1814                a = cosd(ph+dp)
     1815                b = sind(ph+dp)
     1816                phasep = complex(a,b)
     1817                phasem = complex(a,-b)
     1818                h,k,l = hkl+Hmax
     1819                Ehkl[h,k,l] = E*phasep
     1820                h,k,l = -hkl+Hmax       #Friedel pair refl.
     1821                Ehkl[h,k,l] = E*phasem
     1822#    Ehkl[Hmax] = 0.00001           #this to preserve F[0,0,0]
     1823    CEhkl = copy.copy(Ehkl)
     1824    MEhkl = ma.array(Ehkl,mask=(Ehkl==0.0))
     1825    Emask = ma.getmask(MEhkl)
     1826    sumE = np.sum(ma.array(np.absolute(CEhkl),mask=Emask))
     1827    Ncyc = 0
     1828    old = np.seterr(all='raise')
     1829    while True:       
     1830        CErho = np.real(fft.fftn(fft.fftshift(CEhkl)))*(1.+0j)
     1831        CEsig = np.std(CErho)
     1832        CFrho = np.where(np.real(CErho) >= flipData['k-factor']*CEsig,CErho,-CErho)
     1833        CFhkl = fft.ifftshift(fft.ifftn(CFrho))
     1834        CFhkl = np.where(CFhkl,CFhkl,1.0)           #avoid divide by zero
     1835        phase = CFhkl/np.absolute(CFhkl)
     1836        CEhkl = np.absolute(Ehkl)*phase
     1837        Ncyc += 1
     1838        sumCF = np.sum(ma.array(np.absolute(CFhkl),mask=Emask))
     1839        DEhkl = np.absolute(np.absolute(Ehkl)/sumE-np.absolute(CFhkl)/sumCF)
     1840        Rcf = min(100.,np.sum(ma.array(DEhkl,mask=Emask)*100.))
     1841        if Rcf < 5.:
     1842            break
     1843        GoOn = pgbar.Update(Rcf,newmsg='%s%8.3f%s\n%s %d'%('Residual Rcf =',Rcf,'%','No.cycles = ',Ncyc))[0]
     1844        if not GoOn or Ncyc > 10000:
     1845            break
     1846    np.seterr(**old)
     1847    print ' Charge flip time: %.4f'%(time.time()-time0),'no. elements: %d'%(Ehkl.size)
     1848    CErho = np.real(fft.fftn(fft.fftshift(CEhkl)))
     1849    print ' No.cycles = ',Ncyc,'Residual Rcf =%8.3f%s'%(Rcf,'%')+' Map size:',CErho.shape
     1850    roll = findOffset(SGData,A,CEhkl)
     1851       
     1852    mapData['Rcf'] = Rcf
     1853    mapData['rho'] = np.roll(np.roll(np.roll(CErho,roll[0],axis=0),roll[1],axis=1),roll[2],axis=2)
     1854    mapData['rhoMax'] = max(np.max(mapData['rho']),-np.min(mapData['rho']))
     1855    mapData['rollMap'] = [0,0,0]
     1856    return mapData
     1857   
    8091858def SearchMap(data,keepDup=False,Pgbar=None):
    8101859   
     
    10912140    return Q
    10922141   
     2142>>>>>>> .r762
  • trunk/GSASIIphsGUI.py

    r762 r763  
     1<<<<<<< .mine
    12# -*- coding: utf-8 -*-
    23#GSASII - phase data display routines
     
    42984299        mapData = generalData['Map']
    42994300        if len(mapData['rho']):
    4300             pgbar = wx.ProgressDialog('Map search','No. Peaks found =',1001.0,
    4301                 style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
    4302             screenSize = wx.ClientDisplayRect()
    4303             Size = pgbar.GetSize()
    4304             Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
    4305             pgbar.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
    4306             pgbar.SetSize(Size)
     4301            wx.BeginBusyCursor()
    43074302            try:
    4308                 peaks,mags,dzeros = G2mth.SearchMap(data,keepDup=True,Pgbar=pgbar)
     4303                peaks,mags,dzeros = G2mth.SearchMap(data)
    43094304            finally:
    4310                 pgbar.Destroy()
    4311             sortIdx = np.argsort(mags.flatten())
     4305                wx.EndBusyCursor()
    43124306            if len(peaks):
    4313                 data['Map Peaks'] = np.concatenate((mags,peaks,dzeros),axis=1)           
    4314                 print ' Map search finished, time = %.2fs'%(time.time()-time0)
     4307                mapPeaks = np.concatenate((mags,peaks,dzeros),axis=1)
     4308                data['Map Peaks'] = G2mth.sortArray(mapPeaks,0,reverse=True)           
     4309            print ' Map search finished, time = %.2fs'%(time.time()-time0)
     4310            print ' No.peaks found:',len(peaks)   
    43154311            Page = G2frame.dataDisplay.FindPage('Map peaks')
    43164312            G2frame.dataDisplay.ChangeSelection(Page)
     
    44854481    G2frame.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
    44864482    G2frame.dataDisplay.SetSelection(oldPage)
     4483=======
     4484# -*- coding: utf-8 -*-
     4485#GSASII - phase data display routines
     4486########### SVN repository information ###################
     4487# $Date$
     4488# $Author$
     4489# $Revision$
     4490# $URL$
     4491# $Id$
     4492########### SVN repository information ###################
     4493import wx
     4494import wx.grid as wg
     4495import matplotlib as mpl
     4496import math
     4497import copy
     4498import time
     4499import sys
     4500import random as ran
     4501import cPickle
     4502import GSASIIpath
     4503GSASIIpath.SetVersionNumber("$Revision$")
     4504import GSASIIlattice as G2lat
     4505import GSASIIspc as G2spc
     4506import GSASIIElem as G2elem
     4507import GSASIIElemGUI as G2elemGUI
     4508import GSASIIplot as G2plt
     4509import GSASIIgrid as G2gd
     4510import GSASIIIO as G2IO
     4511import GSASIIstruct as G2str
     4512import GSASIImath as G2mth
     4513import GSASIIpwd as G2pwd
     4514import numpy as np
     4515import numpy.linalg as nl
     4516import numpy.ma as ma
     4517
     4518VERY_LIGHT_GREY = wx.Colour(235,235,235)
     4519WHITE = wx.Colour(255,255,255)
     4520BLACK = wx.Colour(0,0,0)
     4521mapDefault = {'MapType':'','RefList':'','Resolution':0.5,
     4522                'rho':[],'rhoMax':0.,'mapSize':10.0,'cutOff':50.,'Flip':False}
     4523# trig functions in degrees
     4524sind = lambda x: np.sin(x*np.pi/180.)
     4525tand = lambda x: np.tan(x*np.pi/180.)
     4526cosd = lambda x: np.cos(x*np.pi/180.)
     4527asind = lambda x: 180.*np.arcsin(x)/np.pi
     4528acosd = lambda x: 180.*np.arccos(x)/np.pi
     4529
     4530class SymOpDialog(wx.Dialog):
     4531    def __init__(self,parent,SGData,New=True,ForceUnit=False):
     4532        wx.Dialog.__init__(self,parent,-1,'Select symmetry operator',
     4533            pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
     4534        panel = wx.Panel(self)
     4535        self.SGData = SGData
     4536        self.New = New
     4537        self.Force = ForceUnit
     4538        self.OpSelected = [0,0,0,[0,0,0],False,False]
     4539        mainSizer = wx.BoxSizer(wx.VERTICAL)
     4540        if ForceUnit:
     4541            choice = ['No','Yes']
     4542            self.force = wx.RadioBox(panel,-1,'Force to unit cell?',choices=choice)
     4543            self.force.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
     4544            mainSizer.Add(self.force,0,wx.ALIGN_CENTER_VERTICAL)
     4545        mainSizer.Add((5,5),0)
     4546        if SGData['SGInv']:
     4547            choice = ['No','Yes']
     4548            self.inv = wx.RadioBox(panel,-1,'Choose inversion?',choices=choice)
     4549            self.inv.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
     4550            mainSizer.Add(self.inv,0,wx.ALIGN_CENTER_VERTICAL)
     4551        mainSizer.Add((5,5),0)
     4552        if SGData['SGLatt'] != 'P':
     4553            LattOp = G2spc.Latt2text(SGData['SGLatt']).split(';')
     4554            self.latt = wx.RadioBox(panel,-1,'Choose cell centering?',choices=LattOp)
     4555            self.latt.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
     4556            mainSizer.Add(self.latt,0,wx.ALIGN_CENTER_VERTICAL)
     4557        mainSizer.Add((5,5),0)
     4558        if SGData['SGLaue'] in ['-1','2/m','mmm','4/m','4/mmm']:
     4559            Ncol = 2
     4560        else:
     4561            Ncol = 3
     4562        OpList = []
     4563        for M,T in SGData['SGOps']:
     4564            OpList.append(G2spc.MT2text(M,T))
     4565        self.oprs = wx.RadioBox(panel,-1,'Choose space group operator?',choices=OpList,
     4566            majorDimension=Ncol)
     4567        self.oprs.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
     4568        mainSizer.Add(self.oprs,0,wx.ALIGN_CENTER_VERTICAL)
     4569        mainSizer.Add((5,5),0)
     4570        mainSizer.Add(wx.StaticText(panel,-1,"   Choose unit cell?"),0,wx.ALIGN_CENTER_VERTICAL)
     4571        mainSizer.Add((5,5),0)
     4572        cellSizer = wx.BoxSizer(wx.HORIZONTAL)
     4573        cellSizer.Add((5,0),0)
     4574        cellName = ['X','Y','Z']
     4575        self.cell = []
     4576        for i in range(3):
     4577            self.cell.append(wx.SpinCtrl(panel,-1,cellName[i],size=wx.Size(50,20)))
     4578            self.cell[-1].SetRange(-3,3)
     4579            self.cell[-1].SetValue(0)
     4580            self.cell[-1].Bind(wx.EVT_SPINCTRL, self.OnOpSelect)
     4581            cellSizer.Add(self.cell[-1],0,wx.ALIGN_CENTER_VERTICAL)
     4582        mainSizer.Add(cellSizer,0,)
     4583        if self.New:
     4584            choice = ['No','Yes']
     4585            self.new = wx.RadioBox(panel,-1,'Generate new positions?',choices=choice)
     4586            self.new.Bind(wx.EVT_RADIOBOX, self.OnOpSelect)
     4587            mainSizer.Add(self.new,0,wx.ALIGN_CENTER_VERTICAL)
     4588        mainSizer.Add((5,5),0)
     4589
     4590        OkBtn = wx.Button(panel,-1,"Ok")
     4591        OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
     4592        cancelBtn = wx.Button(panel,-1,"Cancel")
     4593        cancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
     4594        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
     4595        btnSizer.Add((20,20),1)
     4596        btnSizer.Add(OkBtn)
     4597        btnSizer.Add((20,20),1)
     4598        btnSizer.Add(cancelBtn)
     4599        btnSizer.Add((20,20),1)
     4600
     4601        mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
     4602        panel.SetSizer(mainSizer)
     4603        panel.Fit()
     4604        self.Fit()
     4605
     4606    def OnOpSelect(self,event):
     4607        if self.SGData['SGInv']:
     4608            self.OpSelected[0] = self.inv.GetSelection()
     4609        if self.SGData['SGLatt'] != 'P':
     4610            self.OpSelected[1] = self.latt.GetSelection()
     4611        self.OpSelected[2] = self.oprs.GetSelection()
     4612        for i in range(3):
     4613            self.OpSelected[3][i] = float(self.cell[i].GetValue())
     4614        if self.New:
     4615            self.OpSelected[4] = self.new.GetSelection()
     4616        if self.Force:
     4617            self.OpSelected[5] = self.force.GetSelection()
     4618
     4619    def GetSelection(self):
     4620        return self.OpSelected
     4621
     4622    def OnOk(self,event):
     4623        parent = self.GetParent()
     4624        parent.Raise()
     4625        self.EndModal(wx.ID_OK)
     4626
     4627    def OnCancel(self,event):
     4628        parent = self.GetParent()
     4629        parent.Raise()
     4630        self.EndModal(wx.ID_CANCEL)
     4631
     4632class DisAglDialog(wx.Dialog):
     4633   
     4634    def __default__(self,data,default):
     4635        if data:
     4636            self.data = data
     4637        else:
     4638            self.data = {}
     4639            self.data['Name'] = default['Name']
     4640            self.data['Factors'] = [0.85,0.85]
     4641            self.data['AtomTypes'] = default['AtomTypes']
     4642            self.data['BondRadii'] = default['BondRadii']
     4643            self.data['AngleRadii'] = default['AngleRadii']
     4644       
     4645    def __init__(self,parent,data,default):
     4646        wx.Dialog.__init__(self,parent,-1,'Distance Angle Controls',
     4647            pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
     4648        self.default = default
     4649        self.panel = wx.Panel(self)         #just a dummy - gets destroyed in Draw!
     4650        self.__default__(data,self.default)
     4651        self.Draw(self.data)
     4652               
     4653    def Draw(self,data):
     4654        self.panel.Destroy()
     4655        self.panel = wx.Panel(self)
     4656        mainSizer = wx.BoxSizer(wx.VERTICAL)
     4657        mainSizer.Add(wx.StaticText(self.panel,-1,'Controls for phase '+data['Name']),
     4658            0,wx.ALIGN_CENTER_VERTICAL|wx.LEFT,10)
     4659        mainSizer.Add((10,10),1)
     4660       
     4661        radiiSizer = wx.FlexGridSizer(2,3,5,5)
     4662        radiiSizer.Add(wx.StaticText(self.panel,-1,' Type'),0,wx.ALIGN_CENTER_VERTICAL)
     4663        radiiSizer.Add(wx.StaticText(self.panel,-1,'Bond radii'),0,wx.ALIGN_CENTER_VERTICAL)
     4664        radiiSizer.Add(wx.StaticText(self.panel,-1,'Angle radii'),0,wx.ALIGN_CENTER_VERTICAL)
     4665        self.objList = {}
     4666        for id,item in enumerate(self.data['AtomTypes']):
     4667            radiiSizer.Add(wx.StaticText(self.panel,-1,' '+item),0,wx.ALIGN_CENTER_VERTICAL)
     4668            bRadii = wx.TextCtrl(self.panel,-1,value='%.3f'%(data['BondRadii'][id]),style=wx.TE_PROCESS_ENTER)
     4669            self.objList[bRadii.GetId()] = ['BondRadii',id]
     4670            bRadii.Bind(wx.EVT_TEXT_ENTER,self.OnRadiiVal)
     4671            bRadii.Bind(wx.EVT_KILL_FOCUS,self.OnRadiiVal)
     4672            radiiSizer.Add(bRadii,0,wx.ALIGN_CENTER_VERTICAL)
     4673            aRadii = wx.TextCtrl(self.panel,-1,value='%.3f'%(data['AngleRadii'][id]),style=wx.TE_PROCESS_ENTER)
     4674            self.objList[aRadii.GetId()] = ['AngleRadii',id]
     4675            aRadii.Bind(wx.EVT_TEXT_ENTER,self.OnRadiiVal)
     4676            aRadii.Bind(wx.EVT_KILL_FOCUS,self.OnRadiiVal)
     4677            radiiSizer.Add(aRadii,0,wx.ALIGN_CENTER_VERTICAL)
     4678        mainSizer.Add(radiiSizer,0,wx.EXPAND)
     4679        factorSizer = wx.FlexGridSizer(2,2,5,5)
     4680        Names = ['Bond','Angle']
     4681        for i,name in enumerate(Names):
     4682            factorSizer.Add(wx.StaticText(self.panel,-1,name+' search factor'),0,wx.ALIGN_CENTER_VERTICAL)
     4683            bondFact = wx.TextCtrl(self.panel,-1,value='%.3f'%(data['Factors'][i]),style=wx.TE_PROCESS_ENTER)
     4684            self.objList[bondFact.GetId()] = ['Factors',i]
     4685            bondFact.Bind(wx.EVT_TEXT_ENTER,self.OnRadiiVal)
     4686            bondFact.Bind(wx.EVT_KILL_FOCUS,self.OnRadiiVal)
     4687            factorSizer.Add(bondFact)
     4688        mainSizer.Add(factorSizer,0,wx.EXPAND)
     4689       
     4690        OkBtn = wx.Button(self.panel,-1,"Ok")
     4691        OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
     4692        ResetBtn = wx.Button(self.panel,-1,'Reset')
     4693        ResetBtn.Bind(wx.EVT_BUTTON, self.OnReset)
     4694        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
     4695        btnSizer.Add((20,20),1)
     4696        btnSizer.Add(OkBtn)
     4697        btnSizer.Add(ResetBtn)
     4698        btnSizer.Add((20,20),1)
     4699        mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
     4700        self.panel.SetSizer(mainSizer)
     4701        self.panel.Fit()
     4702        self.Fit()
     4703   
     4704    def OnRadiiVal(self,event):
     4705        Obj = event.GetEventObject()
     4706        item = self.objList[Obj.GetId()]
     4707        try:
     4708            self.data[item[0]][item[1]] = float(Obj.GetValue())
     4709        except ValueError:
     4710            pass
     4711        Obj.SetValue("%.3f"%(self.data[item[0]][item[1]]))          #reset in case of error
     4712       
     4713    def GetData(self):
     4714        return self.data
     4715       
     4716    def OnOk(self,event):
     4717        parent = self.GetParent()
     4718        parent.Raise()
     4719        self.EndModal(wx.ID_OK)             
     4720       
     4721    def OnReset(self,event):
     4722        data = {}
     4723        self.__default__(data,self.default)
     4724        self.Draw(self.data)
     4725       
     4726class SingleFloatDialog(wx.Dialog):
     4727   
     4728    def __init__(self,parent,title,prompt,value,limits=[0.,1.]):
     4729        wx.Dialog.__init__(self,parent,-1,title,
     4730            pos=wx.DefaultPosition,style=wx.DEFAULT_DIALOG_STYLE)
     4731        self.panel = wx.Panel(self)         #just a dummy - gets destroyed in Draw!
     4732        self.limits = limits
     4733        self.value = value
     4734        self.prompt = prompt
     4735        self.Draw()
     4736       
     4737    def Draw(self):
     4738       
     4739        def OnValItem(event):
     4740            try:
     4741                val = float(valItem.GetValue())
     4742                if val < self.limits[0] or val > self.limits[1]:
     4743                    raise ValueError
     4744            except ValueError:
     4745                val = self.value
     4746            self.value = val
     4747            valItem.SetValue('%.5g'%(self.value))
     4748           
     4749        self.panel.Destroy()
     4750        self.panel = wx.Panel(self)
     4751        mainSizer = wx.BoxSizer(wx.VERTICAL)
     4752        mainSizer.Add(wx.StaticText(self.panel,-1,self.prompt),0,wx.ALIGN_CENTER)
     4753        valItem = wx.TextCtrl(self.panel,-1,value='%.5g'%(self.value),style=wx.TE_PROCESS_ENTER)
     4754        mainSizer.Add(valItem,0,wx.ALIGN_CENTER)
     4755        valItem.Bind(wx.EVT_TEXT_ENTER,OnValItem)
     4756        valItem.Bind(wx.EVT_KILL_FOCUS,OnValItem)
     4757        OkBtn = wx.Button(self.panel,-1,"Ok")
     4758        OkBtn.Bind(wx.EVT_BUTTON, self.OnOk)
     4759        CancelBtn = wx.Button(self.panel,-1,'Cancel')
     4760        CancelBtn.Bind(wx.EVT_BUTTON, self.OnCancel)
     4761        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
     4762        btnSizer.Add((20,20),1)
     4763        btnSizer.Add(OkBtn)
     4764        btnSizer.Add(CancelBtn)
     4765        btnSizer.Add((20,20),1)
     4766        mainSizer.Add(btnSizer,0,wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
     4767        self.panel.SetSizer(mainSizer)
     4768        self.panel.Fit()
     4769        self.Fit()
     4770
     4771    def GetValue(self):
     4772        return self.value
     4773       
     4774    def OnOk(self,event):
     4775        parent = self.GetParent()
     4776        parent.Raise()
     4777        self.EndModal(wx.ID_OK)             
     4778       
     4779    def OnCancel(self,event):
     4780        parent = self.GetParent()
     4781        parent.Raise()
     4782        self.EndModal(wx.ID_CANCEL)
     4783       
     4784class GridFractionEditor(wg.PyGridCellEditor):
     4785    def __init__(self,grid):
     4786        wg.PyGridCellEditor.__init__(self)
     4787
     4788    def Create(self, parent, id, evtHandler):
     4789        self._tc = wx.TextCtrl(parent, id, "")
     4790        self._tc.SetInsertionPoint(0)
     4791        self.SetControl(self._tc)
     4792
     4793        if evtHandler:
     4794            self._tc.PushEventHandler(evtHandler)
     4795
     4796        self._tc.Bind(wx.EVT_CHAR, self.OnChar)
     4797
     4798    def SetSize(self, rect):
     4799        self._tc.SetDimensions(rect.x, rect.y, rect.width+2, rect.height+2,
     4800                               wx.SIZE_ALLOW_MINUS_ONE)
     4801
     4802    def BeginEdit(self, row, col, grid):
     4803        self.startValue = grid.GetTable().GetValue(row, col)
     4804        self._tc.SetValue(str(self.startValue))
     4805        self._tc.SetInsertionPointEnd()
     4806        self._tc.SetFocus()
     4807        self._tc.SetSelection(0, self._tc.GetLastPosition())
     4808
     4809    def EndEdit(self, row, col, grid):
     4810        changed = False
     4811
     4812        val = self._tc.GetValue()
     4813       
     4814        if val != self.startValue:
     4815            changed = True
     4816            if '/' in val and '.' not in val:
     4817                val += '.'
     4818            try:
     4819                val = float(eval(val))
     4820            except (SyntaxError,NameError):
     4821                val = self.startValue
     4822            grid.GetTable().SetValue(row, col, val) # update the table
     4823
     4824        self.startValue = ''
     4825        self._tc.SetValue('')
     4826        return changed
     4827
     4828    def Reset(self):
     4829        self._tc.SetValue(self.startValue)
     4830        self._tc.SetInsertionPointEnd()
     4831
     4832    def Clone(self):
     4833        return GridFractionEditor(grid)
     4834
     4835    def StartingKey(self, evt):
     4836        self.OnChar(evt)
     4837        if evt.GetSkipped():
     4838            self._tc.EmulateKeyPress(evt)
     4839
     4840    def OnChar(self, evt):
     4841        key = evt.GetKeyCode()
     4842        if key > 255:
     4843            evt.Skip()
     4844            return
     4845        char = chr(key)
     4846        if char in '.+-/0123456789':
     4847            self._tc.WriteText(char)
     4848        else:
     4849            evt.Skip()
     4850
     4851def FindAtomIndexByIDs(atomData,IDs,Draw=True):
     4852    indx = []
     4853    for i,atom in enumerate(atomData):
     4854        if Draw and atom[-3] in IDs:
     4855            indx.append(i)
     4856        elif atom[-1] in IDs:
     4857            indx.append(i)
     4858    return indx
     4859       
     4860def UpdatePhaseData(G2frame,Item,data,oldPage):
     4861
     4862    Atoms = []
     4863    if G2frame.dataDisplay:
     4864        G2frame.dataDisplay.Destroy()
     4865    PhaseName = G2frame.PatternTree.GetItemText(Item)
     4866    G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.BlankMenu)
     4867    G2frame.dataFrame.SetLabel('Phase Data for '+PhaseName)
     4868    G2frame.dataFrame.CreateStatusBar()
     4869    G2frame.dataDisplay = G2gd.GSNoteBook(parent=G2frame.dataFrame,size=G2frame.dataFrame.GetClientSize())
     4870
     4871    def SetupGeneral():
     4872        generalData = data['General']
     4873        atomData = data['Atoms']
     4874        generalData['AtomTypes'] = []
     4875        generalData['Isotopes'] = {}
     4876# various patches
     4877        if 'Isotope' not in generalData:
     4878            generalData['Isotope'] = {}
     4879        if 'Data plot type' not in generalData:
     4880            generalData['Data plot type'] = 'Mustrain'
     4881        if 'POhkl' not in generalData:
     4882            generalData['POhkl'] = [0,0,1]
     4883        if 'Map' not in generalData:
     4884            generalData['Map'] = mapDefault
     4885        if 'Flip' not in generalData:
     4886            generalData['Flip'] = {'RefList':'','Resolution':0.5,'Norm element':'None',
     4887                'k-factor':0.1}
     4888        if 'doPawley' not in generalData:
     4889            generalData['doPawley'] = False
     4890        if 'Pawley dmin' not in generalData:
     4891            generalData['Pawley dmin'] = 1.0
     4892        if 'Pawley neg wt' not in generalData:
     4893            generalData['Pawley neg wt'] = 0.0
     4894           
     4895#        if 'SH Texture' not in generalData:
     4896#            generalData['SH Texture'] = data['SH Texture']
     4897        generalData['NoAtoms'] = {}
     4898        generalData['BondRadii'] = []
     4899        generalData['AngleRadii'] = []
     4900        generalData['vdWRadii'] = []
     4901        generalData['AtomMass'] = []
     4902        generalData['Color'] = []
     4903        generalData['Mydir'] = G2frame.dirname
     4904        cx,ct,cs,cia = [3,1,7,9]
     4905        if generalData['Type'] =='macromolecular':
     4906            cx,ct,cs,cia = [6,4,10,12]
     4907        generalData['AtomPtrs'] = [cx,ct,cs,cia]
     4908        for atom in atomData:
     4909            atom[ct] = atom[ct].lower().capitalize()              #force to standard form
     4910            if generalData['AtomTypes'].count(atom[ct]):
     4911                generalData['NoAtoms'][atom[ct]] += atom[cs-1]*float(atom[cs+1])
     4912            elif atom[ct] != 'UNK':
     4913                Info = G2elem.GetAtomInfo(atom[ct])
     4914                generalData['AtomTypes'].append(atom[ct])
     4915                generalData['Z'] = Info['Z']
     4916                generalData['Isotopes'][atom[ct]] = Info['Isotopes']
     4917                generalData['BondRadii'].append(Info['Drad'])
     4918                generalData['AngleRadii'].append(Info['Arad'])
     4919                generalData['vdWRadii'].append(Info['Vdrad'])
     4920                if atom[ct] in generalData['Isotope']:
     4921                    generalData['AtomMass'].append(Info['Isotopes'][generalData['Isotope'][atom[ct]]][0])
     4922                else:
     4923                    generalData['Isotope'][atom[ct]] = 'Nat. Abund.'
     4924                    generalData['AtomMass'].append(Info['Mass'])
     4925                generalData['NoAtoms'][atom[ct]] = atom[cs-1]*float(atom[cs+1])
     4926                generalData['Color'].append(Info['Color'])
     4927        F000X = 0.
     4928        F000N = 0.
     4929        for i,elem in enumerate(generalData['AtomTypes']):
     4930            F000X += generalData['NoAtoms'][elem]*generalData['Z']
     4931            isotope = generalData['Isotope'][elem]
     4932            F000N += generalData['NoAtoms'][elem]*generalData['Isotopes'][elem][isotope][1]
     4933        generalData['F000X'] = F000X
     4934        generalData['F000N'] = F000N
     4935       
     4936
     4937################################################################################
     4938##### General phase routines
     4939################################################################################
     4940
     4941    def UpdateGeneral():
     4942       
     4943        ''' default dictionary structure for phase data: (taken from GSASII.py)
     4944        'General':{
     4945            'Name':PhaseName
     4946            'Type':'nuclear'
     4947            'SGData':SGData
     4948            'Cell':[False,10.,10.,10.,90.,90.,90,1000.]
     4949            'AtomPtrs':[]
     4950            'Histogram list':['',]
     4951            'Pawley dmin':1.0,
     4952            'Pawley neg wt':0.0}
     4953        'Atoms':[]
     4954        'Drawing':{}
     4955        '''
     4956       
     4957        phaseTypes = ['nuclear','modulated','magnetic','macromolecular']
     4958        SetupGeneral()
     4959        generalData = data['General']
     4960        Map = generalData['Map']
     4961        Flip = generalData['Flip'] 
     4962        PWDR = any(['PWDR' in item for item in data['Histograms'].keys()])
     4963       
     4964        def NameSizer():
     4965                   
     4966            def OnPhaseName(event):
     4967                oldName = generalData['Name']
     4968                generalData['Name'] = NameTxt.GetValue()
     4969                G2frame.G2plotNB.Rename(oldName,generalData['Name'])
     4970                G2frame.dataFrame.SetLabel('Phase Data for '+generalData['Name'])
     4971                G2frame.PatternTree.SetItemText(Item,generalData['Name'])
     4972                #Hmm, need to change phase name key in Reflection Lists for each histogram
     4973                           
     4974            def OnPhaseType(event):
     4975                if not generalData['AtomTypes']:             #can change only if no atoms!
     4976                    generalData['Type'] = TypeTxt.GetValue()
     4977                    dataDisplay.DestroyChildren()           #needed to clear away bad cellSizer, etc.
     4978                    wx.CallAfter(UpdateGeneral)
     4979                else:
     4980                    TypeTxt.SetValue(generalData['Type'])               
     4981               
     4982            def OnSpaceGroup(event):
     4983                SpcGp = SGTxt.GetValue()
     4984                SGErr,SGData = G2spc.SpcGroup(SpcGp)
     4985                # try a lookup on the user-supplied name
     4986                if SGErr:
     4987                    SpGrpNorm = G2spc.StandardizeSpcName(SpcGp)
     4988                    if SpGrpNorm:
     4989                        E,SGData = G2spc.SpcGroup(SpGrpNorm)
     4990                        if not E: SGErr = False
     4991                if SGErr:
     4992                    text = [G2spc.SGErrors(SGErr)+'\nSpace Group set to previous']
     4993                    SGTxt.SetValue(generalData['SGData']['SpGrp'])
     4994                    msg = 'Space Group Error'
     4995                    Style = wx.ICON_EXCLAMATION
     4996                else:
     4997                    text = G2spc.SGPrint(SGData)
     4998                    generalData['SGData'] = SGData
     4999                    msg = 'Space Group Information'
     5000                    Style = wx.ICON_INFORMATION
     5001                Text = ''
     5002                for line in text:
     5003                    Text += line+'\n'
     5004                wx.MessageBox(Text,caption=msg,style=Style)
     5005                dataDisplay.DestroyChildren()           #needed to clear away bad cellSizer, etc.
     5006                wx.CallAfter(UpdateGeneral)
     5007               
     5008            nameSizer = wx.BoxSizer(wx.HORIZONTAL)
     5009            nameSizer.Add(wx.StaticText(dataDisplay,-1,' Phase name: '),0,wx.ALIGN_CENTER_VERTICAL)
     5010            NameTxt = wx.TextCtrl(dataDisplay,-1,value=generalData['Name'],style=wx.TE_PROCESS_ENTER)
     5011            NameTxt.Bind(wx.EVT_TEXT_ENTER,OnPhaseName)
     5012            NameTxt.Bind(wx.EVT_KILL_FOCUS,OnPhaseName)
     5013            nameSizer.Add(NameTxt,0,wx.ALIGN_CENTER_VERTICAL)
     5014            nameSizer.Add(wx.StaticText(dataDisplay,-1,'  Phase type: '),0,wx.ALIGN_CENTER_VERTICAL)
     5015            if len(data['Atoms']):
     5016                choices = phaseTypes[:-1]
     5017            else:
     5018                choices = phaseTypes           
     5019            TypeTxt = wx.ComboBox(dataDisplay,-1,value=generalData['Type'],choices=choices,
     5020                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     5021            TypeTxt.Bind(wx.EVT_COMBOBOX, OnPhaseType)
     5022            nameSizer.Add(TypeTxt,0,wx.ALIGN_CENTER_VERTICAL)
     5023            nameSizer.Add(wx.StaticText(dataDisplay,-1,'  Space group: '),0,wx.ALIGN_CENTER_VERTICAL)
     5024            SGTxt = wx.TextCtrl(dataDisplay,-1,value=generalData['SGData']['SpGrp'],style=wx.TE_PROCESS_ENTER)
     5025            SGTxt.Bind(wx.EVT_TEXT_ENTER,OnSpaceGroup)
     5026            nameSizer.Add(SGTxt,0,wx.ALIGN_CENTER_VERTICAL)
     5027            return nameSizer
     5028           
     5029        def CellSizer():
     5030           
     5031            cellGUIlist = [[['m3','m3m'],4,zip([" Unit cell: a = "," Vol = "],["%.5f","%.3f"],[True,False],[0,0])],
     5032            [['3R','3mR'],6,zip([" a = "," alpha = "," Vol = "],["%.5f","%.3f","%.3f"],[True,True,False],[0,2,0])],
     5033            [['3','3m1','31m','6/m','6/mmm','4/m','4/mmm'],6,zip([" a = "," c = "," Vol = "],["%.5f","%.5f","%.3f"],[True,True,False],[0,2,0])],
     5034            [['mmm'],8,zip([" a = "," b = "," c = "," Vol = "],["%.5f","%.5f","%.5f","%.3f"],
     5035                [True,True,True,False],[0,1,2,0])],
     5036            [['2/m'+'a'],10,zip([" a = "," b = "," c = "," alpha = "," Vol = "],
     5037                ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
     5038            [['2/m'+'b'],10,zip([" a = "," b = "," c = "," beta = "," Vol = "],
     5039                ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
     5040            [['2/m'+'c'],10,zip([" a = "," b = "," c = "," gamma = "," Vol = "],
     5041                ["%.5f","%.5f","%.5f","%.3f","%.3f"],[True,True,True,True,False],[0,1,2,4,0])],
     5042            [['-1'],8,zip([" a = "," b = "," c = "," Vol = "," alpha = "," beta = "," gamma = "],
     5043                ["%.5f","%.5f","%.5f","%.3f","%.3f","%.3f","%.3f"],
     5044                [True,True,True,False,True,True,True],[0,1,2,0,3,4,5])]]
     5045               
     5046            def OnCellRef(event):
     5047                generalData['Cell'][0] = cellRef.GetValue()
     5048               
     5049            def OnCellChange(event):
     5050                SGData = generalData['SGData']
     5051                laue = SGData['SGLaue']
     5052                if laue == '2/m':
     5053                    laue += SGData['SGUniq']
     5054                cell = generalData['Cell']
     5055                Obj = event.GetEventObject()
     5056                ObjId = cellList.index(Obj.GetId())
     5057                try:
     5058                    value = max(1.0,float(Obj.GetValue()))
     5059                except ValueError:
     5060                    if ObjId < 3:               #bad cell edge - reset
     5061                        value = controls[6+ObjId]
     5062                    else:                       #bad angle
     5063                        value = 90.
     5064                if laue in ['m3','m3m']:
     5065                    cell[1] = cell[2] = cell[3] = value
     5066                    cell[4] = cell[5] = cell[6] = 90.0
     5067                    Obj.SetValue("%.5f"%(cell[1]))
     5068                elif laue in ['3R','3mR']:
     5069                    if ObjId == 0:
     5070                        cell[1] = cell[2] = cell[3] = value
     5071                        Obj.SetValue("%.5f"%(cell[1]))
     5072                    else:
     5073                        cell[4] = cell[5] = cell[6] = value
     5074                        Obj.SetValue("%.5f"%(cell[4]))
     5075                elif laue in ['3','3m1','31m','6/m','6/mmm','4/m','4/mmm']:                   
     5076                    cell[4] = cell[5] = 90.
     5077                    cell[6] = 120.
     5078                    if laue in ['4/m','4/mmm']:
     5079                        cell[6] = 90.
     5080                    if ObjId == 0:
     5081                        cell[1] = cell[2] = value
     5082                        Obj.SetValue("%.5f"%(cell[1]))
     5083                    else:
     5084                        cell[3] = value
     5085                        Obj.SetValue("%.5f"%(cell[3]))
     5086                elif laue in ['mmm']:
     5087                    cell[ObjId+1] = value
     5088                    cell[4] = cell[5] = cell[6] = 90.
     5089                    Obj.SetValue("%.5f"%(cell[ObjId+1]))
     5090                elif laue in ['2/m'+'a']:
     5091                    cell[5] = cell[6] = 90.
     5092                    if ObjId != 3:
     5093                        cell[ObjId+1] = value
     5094                        Obj.SetValue("%.5f"%(cell[ObjId+1]))
     5095                    else:
     5096                        cell[4] = value
     5097                        Obj.SetValue("%.3f"%(cell[4]))
     5098                elif laue in ['2/m'+'b']:
     5099                    cell[4] = cell[6] = 90.
     5100                    if ObjId != 3:
     5101                        cell[ObjId+1] = value
     5102                        Obj.SetValue("%.5f"%(cell[ObjId+1]))
     5103                    else:
     5104                        cell[5] = value
     5105                        Obj.SetValue("%.3f"%(cell[5]))
     5106                elif laue in ['2/m'+'c']:
     5107                    cell[5] = cell[6] = 90.
     5108                    if ObjId != 3:
     5109                        cell[ObjId+1] = value
     5110                        Obj.SetValue("%.5f"%(cell[ObjId+1]))
     5111                    else:
     5112                        cell[6] = value
     5113                        Obj.SetValue("%.3f"%(cell[6]))
     5114                else:
     5115                    cell[ObjId+1] = value
     5116                    if ObjId < 3:
     5117                        Obj.SetValue("%.5f"%(cell[1+ObjId]))
     5118                    else:
     5119                        Obj.SetValue("%.3f"%(cell[1+ObjId]))                       
     5120                cell[7] = G2lat.calc_V(G2lat.cell2A(cell[1:7]))
     5121                volVal.SetValue("%.3f"%(cell[7]))
     5122                density,mattCoeff = G2mth.getDensity(generalData)
     5123                if denSizer:
     5124                    denSizer[1].SetValue('%.3f'%(density))
     5125                    if denSizer[2]:
     5126                        denSizer[2].SetValue('%.3f'%(mattCoeff))
     5127                generalData['Cell'] = cell
     5128           
     5129            cell = generalData['Cell']
     5130            laue = generalData['SGData']['SGLaue']
     5131            if laue == '2/m':
     5132                laue += generalData['SGData']['SGUniq']
     5133            for cellGUI in cellGUIlist:
     5134                if laue in cellGUI[0]:
     5135                    useGUI = cellGUI
     5136            cellSizer = wx.FlexGridSizer(2,useGUI[1]+1,5,5)
     5137            if PWDR:
     5138                cellRef = wx.CheckBox(dataDisplay,-1,label='Refine unit cell:')
     5139                cellSizer.Add(cellRef,0,wx.ALIGN_CENTER_VERTICAL)
     5140                cellRef.Bind(wx.EVT_CHECKBOX, OnCellRef)
     5141                cellRef.SetValue(cell[0])
     5142            cellList = []
     5143            for txt,fmt,ifEdit,Id in useGUI[2]:
     5144                cellSizer.Add(wx.StaticText(dataDisplay,label=txt),0,wx.ALIGN_CENTER_VERTICAL)
     5145                if ifEdit:          #a,b,c,etc.
     5146                    cellVal = wx.TextCtrl(dataDisplay,value=(fmt%(cell[Id+1])),
     5147                        style=wx.TE_PROCESS_ENTER)
     5148                    cellVal.Bind(wx.EVT_TEXT_ENTER,OnCellChange)       
     5149                    cellVal.Bind(wx.EVT_KILL_FOCUS,OnCellChange)
     5150                    cellSizer.Add(cellVal,0,wx.ALIGN_CENTER_VERTICAL)
     5151                    cellList.append(cellVal.GetId())
     5152                else:               #volume
     5153                    volVal = wx.TextCtrl(dataDisplay,value=(fmt%(cell[7])),style=wx.TE_READONLY)
     5154                    volVal.SetBackgroundColour(VERY_LIGHT_GREY)
     5155                    cellSizer.Add(volVal,0,wx.ALIGN_CENTER_VERTICAL)
     5156            return cellSizer
     5157           
     5158        def ElemSizer():
     5159           
     5160            def OnIsotope(event):
     5161                Obj = event.GetEventObject()
     5162                item = Indx[Obj.GetId()]
     5163                isotope = Obj.GetValue()
     5164                generalData['Isotope'][item] = isotope
     5165                indx = generalData['AtomTypes'].index(item)
     5166                data['General']['AtomMass'][indx] = generalData['Isotopes'][item][isotope][0]
     5167                density,mattCoeff = G2mth.getDensity(generalData)
     5168                denSizer[1].SetValue('%.3f'%(density))
     5169                if denSizer[2]:
     5170                    denSizer[2].SetValue('%.3f'%(mattCoeff))
     5171               
     5172            elemSizer = wx.FlexGridSizer(8,len(generalData['AtomTypes'])+1,1,1)
     5173            elemSizer.Add(wx.StaticText(dataDisplay,label=' Elements'),0,wx.ALIGN_CENTER_VERTICAL)
     5174            for elem in generalData['AtomTypes']:
     5175                typTxt = wx.TextCtrl(dataDisplay,value=elem,style=wx.TE_READONLY)
     5176                typTxt.SetBackgroundColour(VERY_LIGHT_GREY)
     5177                elemSizer.Add(typTxt,0,wx.ALIGN_CENTER_VERTICAL)
     5178            elemSizer.Add(wx.StaticText(dataDisplay,label=' Isotope'),0,wx.ALIGN_CENTER_VERTICAL)
     5179            for elem in generalData['AtomTypes']:
     5180                choices = generalData['Isotopes'][elem].keys()
     5181                isoSel = wx.ComboBox(dataDisplay,-1,value=generalData['Isotope'][elem],choices=choices,
     5182                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
     5183                isoSel.Bind(wx.EVT_COMBOBOX,OnIsotope)
     5184                Indx[isoSel.GetId()] = elem
     5185                elemSizer.Add(isoSel,1,wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
     5186            elemSizer.Add(wx.StaticText(dataDisplay,label=' No. per cell'),0,wx.ALIGN_CENTER_VERTICAL)
     5187            for elem in generalData['AtomTypes']:
     5188                numbTxt = wx.TextCtrl(dataDisplay,value='%.1f'%(generalData['NoAtoms'][elem]),
     5189                    style=wx.TE_READONLY)
     5190                numbTxt.SetBackgroundColour(VERY_LIGHT_GREY)
     5191                elemSizer.Add(numbTxt,0,wx.ALIGN_CENTER_VERTICAL)
     5192            elemSizer.Add(wx.StaticText(dataDisplay,label=' Atom weight'),0,wx.ALIGN_CENTER_VERTICAL)
     5193            for wt in generalData['AtomMass']:
     5194                wtTxt = wx.TextCtrl(dataDisplay,value='%.3f'%(wt),style=wx.TE_READONLY)
     5195                wtTxt.SetBackgroundColour(VERY_LIGHT_GREY)
     5196                elemSizer.Add(wtTxt,0,wx.ALIGN_CENTER_VERTICAL)
     5197            elemSizer.Add(wx.StaticText(dataDisplay,label=' Bond radii'),0,wx.ALIGN_CENTER_VERTICAL)
     5198            for rad in generalData['BondRadii']:
     5199                bondRadii = wx.TextCtrl(dataDisplay,value='%.2f'%(rad),style=wx.TE_READONLY)
     5200                bondRadii.SetBackgroundColour(VERY_LIGHT_GREY)
     5201                elemSizer.Add(bondRadii,0,wx.ALIGN_CENTER_VERTICAL)
     5202            elemSizer.Add(wx.StaticText(dataDisplay,label=' Angle radii'),0,wx.ALIGN_CENTER_VERTICAL)
     5203            for rad in generalData['AngleRadii']:
     5204                elemTxt = wx.TextCtrl(dataDisplay,value='%.2f'%(rad),style=wx.TE_READONLY)
     5205                elemTxt.SetBackgroundColour(VERY_LIGHT_GREY)
     5206                elemSizer.Add(elemTxt,0,wx.ALIGN_CENTER_VERTICAL)
     5207            elemSizer.Add(wx.StaticText(dataDisplay,label=' van der Waals radii'),0,wx.ALIGN_CENTER_VERTICAL)
     5208            for rad in generalData['vdWRadii']:
     5209                elemTxt = wx.TextCtrl(dataDisplay,value='%.2f'%(rad),style=wx.TE_READONLY)
     5210                elemTxt.SetBackgroundColour(VERY_LIGHT_GREY)
     5211                elemSizer.Add(elemTxt,0,wx.ALIGN_CENTER_VERTICAL)
     5212            elemSizer.Add(wx.StaticText(dataDisplay,label=' Default color'),0,wx.ALIGN_CENTER_VERTICAL)
     5213            for R,G,B in generalData['Color']:
     5214                colorTxt = wx.TextCtrl(dataDisplay,value='',style=wx.TE_READONLY)
     5215                colorTxt.SetBackgroundColour(wx.Colour(R,G,B))
     5216                elemSizer.Add(colorTxt,0,wx.ALIGN_CENTER_VERTICAL)
     5217            return elemSizer
     5218       
     5219        def DenSizer():
     5220           
     5221            mass = G2mth.getMass(generalData)
     5222            density,mattCoeff = G2mth.getDensity(generalData)
     5223            denSizer = wx.BoxSizer(wx.HORIZONTAL)
     5224            denSizer.Add(wx.StaticText(dataDisplay,-1,' Density: '),0,wx.ALIGN_CENTER_VERTICAL)
     5225            denTxt = wx.TextCtrl(dataDisplay,-1,'%.3f'%(density),style=wx.TE_READONLY)
     5226            denTxt.SetBackgroundColour(VERY_LIGHT_GREY)
     5227            denSizer.Add(denTxt,0,wx.ALIGN_CENTER_VERTICAL)
     5228            mattTxt = None       
     5229            if generalData['Type'] == 'macromolecular' and mass > 0.0:
     5230                denSizer.Add(wx.StaticText(dataDisplay,-1,' Matthews coeff.: '),
     5231                    0,wx.ALIGN_CENTER_VERTICAL)
     5232                mattTxt = wx.TextCtrl(dataDisplay,-1,'%.3f'%(mattCoeff),style=wx.TE_READONLY)
     5233                mattTxt.SetBackgroundColour(VERY_LIGHT_GREY)
     5234                denSizer.Add(mattTxt,0,wx.ALIGN_CENTER_VERTICAL)
     5235            return denSizer,denTxt,mattTxt
     5236           
     5237        def PawleySizer():
     5238           
     5239            def OnPawleyRef(event):
     5240                generalData['doPawley'] = pawlRef.GetValue()
     5241           
     5242            def OnPawleyVal(event):
     5243                try:
     5244                    dmin = float(pawlVal.GetValue())
     5245                    if 0.25 <= dmin <= 20.:
     5246                        generalData['Pawley dmin'] = dmin
     5247                except ValueError:
     5248                    pass
     5249                pawlVal.SetValue("%.3f"%(generalData['Pawley dmin']))          #reset in case of error               
     5250           
     5251            def OnPawleyNegWt(event):
     5252                try:
     5253                    wt = float(pawlNegWt.GetValue())
     5254                    if 0. <= wt <= 1.:
     5255                        generalData['Pawley neg wt'] = wt
     5256                except ValueError:
     5257                    pass
     5258                pawlNegWt.SetValue("%.3g"%(generalData['Pawley neg wt']))          #reset in case of error               
     5259
     5260            pawleySizer = wx.BoxSizer(wx.HORIZONTAL)
     5261            pawleySizer.Add(wx.StaticText(dataDisplay,label=' Pawley controls: '),0,wx.ALIGN_CENTER_VERTICAL)
     5262            pawlRef = wx.CheckBox(dataDisplay,-1,label=' Do Pawley refinement?')
     5263            pawlRef.SetValue(generalData['doPawley'])
     5264            pawlRef.Bind(wx.EVT_CHECKBOX,OnPawleyRef)
     5265            pawleySizer.Add(pawlRef,0,wx.ALIGN_CENTER_VERTICAL)
     5266            pawleySizer.Add(wx.StaticText(dataDisplay,label=' Pawley dmin: '),0,wx.ALIGN_CENTER_VERTICAL)
     5267            pawlVal = wx.TextCtrl(dataDisplay,value='%.3f'%(generalData['Pawley dmin']),style=wx.TE_PROCESS_ENTER)
     5268            pawlVal.Bind(wx.EVT_TEXT_ENTER,OnPawleyVal)       
     5269            pawlVal.Bind(wx.EVT_KILL_FOCUS,OnPawleyVal)
     5270            pawleySizer.Add(pawlVal,0,wx.ALIGN_CENTER_VERTICAL)
     5271            pawleySizer.Add(wx.StaticText(dataDisplay,label=' Pawley neg. wt.: '),0,wx.ALIGN_CENTER_VERTICAL)
     5272            pawlNegWt = wx.TextCtrl(dataDisplay,value='%.3g'%(generalData['Pawley neg wt']),style=wx.TE_PROCESS_ENTER)
     5273            pawlNegWt.Bind(wx.EVT_TEXT_ENTER,OnPawleyNegWt)       
     5274            pawlNegWt.Bind(wx.EVT_KILL_FOCUS,OnPawleyNegWt)
     5275            pawleySizer.Add(pawlNegWt,0,wx.ALIGN_CENTER_VERTICAL)
     5276            return pawleySizer
     5277           
     5278        def MapSizer():
     5279           
     5280            def OnMapType(event):
     5281                Map['MapType'] = mapType.GetValue()
     5282               
     5283            def OnRefList(event):
     5284                Map['RefList'] = refList.GetValue()
     5285               
     5286            def OnResVal(event):
     5287                try:
     5288                    res = float(mapRes.GetValue())
     5289                    if 0.25 <= res <= 20.:
     5290                        Map['Resolution'] = res
     5291                except ValueError:
     5292                    pass
     5293                mapRes.SetValue("%.2f"%(Map['Resolution']))          #reset in case of error
     5294           
     5295            def OnCutOff(event):
     5296                try:
     5297                    res = float(cutOff.GetValue())
     5298                    if 10.0 <= res <= 100.:
     5299                        Map['cutOff'] = res
     5300                except ValueError:
     5301                    pass
     5302                cutOff.SetValue("%.1f"%(Map['cutOff']))          #reset in case of error
     5303           
     5304            #patch
     5305            if 'cutOff' not in Map:
     5306                Map['cutOff'] = 100.0
     5307            mapTypes = ['Fobs','Fcalc','delt-F','2*Fo-Fc','Patterson']
     5308            refList = data['Histograms'].keys()
     5309            if not generalData['AtomTypes']:
     5310                 mapTypes = ['Patterson',]
     5311                 Map['MapType'] = 'Patterson'
     5312            mapSizer = wx.BoxSizer(wx.VERTICAL)
     5313            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
     5314            lineSizer.Add(wx.StaticText(dataDisplay,label=' Fourier map controls: Map type: '),0,wx.ALIGN_CENTER_VERTICAL)
     5315            mapType = wx.ComboBox(dataDisplay,-1,value=Map['MapType'],choices=mapTypes,
     5316                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     5317            mapType.Bind(wx.EVT_COMBOBOX,OnMapType)
     5318            lineSizer.Add(mapType,0,wx.ALIGN_CENTER_VERTICAL)
     5319            lineSizer.Add(wx.StaticText(dataDisplay,label=' Reflection set from: '),0,wx.ALIGN_CENTER_VERTICAL)
     5320            refList = wx.ComboBox(dataDisplay,-1,value=Map['RefList'],choices=refList,
     5321                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     5322            refList.Bind(wx.EVT_COMBOBOX,OnRefList)
     5323            lineSizer.Add(refList,0,wx.ALIGN_CENTER_VERTICAL)
     5324            mapSizer.Add(lineSizer,0,wx.ALIGN_CENTER_VERTICAL)
     5325            line2Sizer = wx.BoxSizer(wx.HORIZONTAL)
     5326            line2Sizer.Add(wx.StaticText(dataDisplay,label=' Resolution: '),0,wx.ALIGN_CENTER_VERTICAL)
     5327            mapRes =  wx.TextCtrl(dataDisplay,value='%.2f'%(Map['Resolution']),style=wx.TE_PROCESS_ENTER)
     5328            mapRes.Bind(wx.EVT_TEXT_ENTER,OnResVal)       
     5329            mapRes.Bind(wx.EVT_KILL_FOCUS,OnResVal)
     5330            line2Sizer.Add(mapRes,0,wx.ALIGN_CENTER_VERTICAL)
     5331            line2Sizer.Add(wx.StaticText(dataDisplay,label=' Peak cutoff %: '),0,wx.ALIGN_CENTER_VERTICAL)
     5332            cutOff =  wx.TextCtrl(dataDisplay,value='%.1f'%(Map['cutOff']),style=wx.TE_PROCESS_ENTER)
     5333            cutOff.Bind(wx.EVT_TEXT_ENTER,OnCutOff)       
     5334            cutOff.Bind(wx.EVT_KILL_FOCUS,OnCutOff)
     5335            line2Sizer.Add(cutOff,0,wx.ALIGN_CENTER_VERTICAL)
     5336            mapSizer.Add(line2Sizer,0,wx.ALIGN_CENTER_VERTICAL)
     5337            return mapSizer
     5338               
     5339        def FlipSizer():
     5340           
     5341            def OnRefList(event):
     5342                Flip['RefList'] = refList.GetValue()
     5343               
     5344            def OnNormElem(event):
     5345                PE = G2elemGUI.PickElement(G2frame,ifNone=True)
     5346                if PE.ShowModal() == wx.ID_OK:
     5347                    Flip['Norm element'] = PE.Elem.strip()
     5348                    normElem.SetLabel(Flip['Norm element'])
     5349                PE.Destroy()               
     5350               
     5351            def OnResVal(event):
     5352                try:
     5353                    res = float(flipRes.GetValue())
     5354                    if 0.25 <= res <= 20.:
     5355                        Flip['Resolution'] = res
     5356                except ValueError:
     5357                    pass
     5358                flipRes.SetValue("%.2f"%(Flip['Resolution']))          #reset in case of error
     5359           
     5360            def OnkFactor(event):
     5361                try:
     5362                    res = float(kFactor.GetValue())
     5363                    if 0.1 <= res <= 1.2:
     5364                        Flip['k-factor'] = res
     5365                except ValueError:
     5366                    pass
     5367                kFactor.SetValue("%.3f"%(Flip['k-factor']))          #reset in case of error
     5368           
     5369            refList = data['Histograms'].keys()
     5370            flipSizer = wx.BoxSizer(wx.VERTICAL)
     5371            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
     5372            lineSizer.Add(wx.StaticText(dataDisplay,label=' Charge flip controls: Reflection set from: '),0,wx.ALIGN_CENTER_VERTICAL)
     5373            refList = wx.ComboBox(dataDisplay,-1,value=Flip['RefList'],choices=refList,
     5374                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     5375            refList.Bind(wx.EVT_COMBOBOX,OnRefList)
     5376            lineSizer.Add(refList,0,wx.ALIGN_CENTER_VERTICAL)
     5377            flipSizer.Add(lineSizer,0,wx.ALIGN_CENTER_VERTICAL)
     5378            line2Sizer = wx.BoxSizer(wx.HORIZONTAL)
     5379            line2Sizer.Add(wx.StaticText(dataDisplay,label=' Normalizing element: '),0,wx.ALIGN_CENTER_VERTICAL)
     5380            normElem = wx.Button(dataDisplay,label=Flip['Norm element'],style=wx.TE_READONLY)
     5381            normElem.Bind(wx.EVT_BUTTON,OnNormElem)
     5382            line2Sizer.Add(normElem,0,wx.ALIGN_CENTER_VERTICAL)
     5383            line2Sizer.Add(wx.StaticText(dataDisplay,label=' Resolution: '),0,wx.ALIGN_CENTER_VERTICAL)
     5384            flipRes =  wx.TextCtrl(dataDisplay,value='%.2f'%(Flip['Resolution']),style=wx.TE_PROCESS_ENTER)
     5385            flipRes.Bind(wx.EVT_TEXT_ENTER,OnResVal)       
     5386            flipRes.Bind(wx.EVT_KILL_FOCUS,OnResVal)
     5387            line2Sizer.Add(flipRes,0,wx.ALIGN_CENTER_VERTICAL)
     5388            line2Sizer.Add(wx.StaticText(dataDisplay,label=' k-Factor (0.1-1.2): '),0,wx.ALIGN_CENTER_VERTICAL)
     5389            kFactor =  wx.TextCtrl(dataDisplay,value='%.3f'%(Flip['k-factor']),style=wx.TE_PROCESS_ENTER)
     5390            kFactor.Bind(wx.EVT_TEXT_ENTER,OnkFactor)       
     5391            kFactor.Bind(wx.EVT_KILL_FOCUS,OnkFactor)
     5392            line2Sizer.Add(kFactor,0,wx.ALIGN_CENTER_VERTICAL)
     5393            flipSizer.Add(line2Sizer,0,wx.ALIGN_CENTER_VERTICAL)
     5394            return flipSizer
     5395               
     5396        General.DestroyChildren()
     5397        dataDisplay = wx.Panel(General)
     5398        mainSizer = wx.BoxSizer(wx.VERTICAL)
     5399        mainSizer.Add((5,5),0)
     5400        mainSizer.Add(NameSizer(),0)
     5401        mainSizer.Add((5,5),0)       
     5402        mainSizer.Add(CellSizer(),0)
     5403        mainSizer.Add((5,5),0)
     5404       
     5405        Indx = {}
     5406        denSizer = None
     5407        if len(generalData['AtomTypes']):
     5408            denSizer = DenSizer()
     5409            mainSizer.Add(denSizer[0])
     5410            mainSizer.Add((5,5),0)           
     5411            mainSizer.Add(ElemSizer())
     5412           
     5413        mainSizer.Add((5,5),0)
     5414        mainSizer.Add(PawleySizer())
     5415
     5416        mainSizer.Add((5,5),0)
     5417        mainSizer.Add(MapSizer())
     5418
     5419        mainSizer.Add((5,5),0)
     5420        mainSizer.Add(FlipSizer())
     5421
     5422        dataDisplay.SetSizer(mainSizer)
     5423        Size = mainSizer.Fit(G2frame.dataFrame)
     5424        Size[1] += 35                           #compensate for status bar
     5425        dataDisplay.SetSize(Size)
     5426        G2frame.dataFrame.SetStatusText('')
     5427        G2frame.dataFrame.setSizePosLeft(Size)
     5428
     5429################################################################################
     5430#####  Atom routines
     5431################################################################################
     5432
     5433    def FillAtomsGrid():
     5434
     5435        G2frame.dataFrame.setSizePosLeft([700,300])
     5436        generalData = data['General']
     5437        atomData = data['Atoms']
     5438        DData = data['Drawing']
     5439        Items = [G2gd.wxID_ATOMSEDITINSERT, G2gd.wxID_ATOMSEDITDELETE, G2gd.wxID_ATOMSREFINE,
     5440            G2gd.wxID_ATOMSMODIFY, G2gd.wxID_ATOMSTRANSFORM, G2gd.wxID_ATOMVIEWINSERT]
     5441        if atomData:
     5442            for item in Items:   
     5443                G2frame.dataFrame.AtomsMenu.Enable(item,True)
     5444        else:
     5445            for item in Items:
     5446                G2frame.dataFrame.AtomsMenu.Enable(item,False)
     5447        Items = [G2gd.wxID_ATOMVIEWINSERT, G2gd.wxID_ATOMSVIEWADD]
     5448        if data['Drawing']['showABC']:
     5449            for item in Items:
     5450                G2frame.dataFrame.AtomsMenu.Enable(item,True)
     5451        else:
     5452            for item in Items:
     5453                G2frame.dataFrame.AtomsMenu.Enable(item,False)
     5454
     5455        AAchoice = ": ,ALA,ARG,ASN,ASP,CYS,GLN,GLU,GLY,HIS,ILE,LEU,LYS,MET,PHE,PRO,SER,THR,TRP,TYR,VAL,MSE,HOH,UNK"
     5456        Types = [wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+": ,X,XU,U,F,FX,FXU,FU",]+ \
     5457            3*[wg.GRID_VALUE_FLOAT+':10,5',]+[wg.GRID_VALUE_FLOAT+':10,4', #x,y,z,frac
     5458            wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+":I,A",]
     5459        Types += 7*[wg.GRID_VALUE_FLOAT+':10,5',]
     5460        colLabels = ['Name','Type','refine','x','y','z','frac','site sym','mult','I/A','Uiso','U11','U22','U33','U12','U13','U23']
     5461        if generalData['Type'] == 'magnetic':
     5462            colLabels += ['Mx','My','Mz']
     5463            Types[2] = wg.GRID_VALUE_CHOICE+": ,X,XU,U,M,MX,MXU,MU,F,FX,FXU,FU,FM,FMX,FMU,"
     5464            Types += 3*[wg.GRID_VALUE_FLOAT+':10,4',]
     5465        elif generalData['Type'] == 'macromolecular':
     5466            colLabels = ['res no','residue','chain'] + colLabels
     5467            Types = [wg.GRID_VALUE_STRING,
     5468                wg.GRID_VALUE_CHOICE+AAchoice,
     5469                wg.GRID_VALUE_STRING] + Types
     5470        elif generalData['Type'] == 'modulated':
     5471            Types += []
     5472            colLabels += []
     5473
     5474        def RefreshAtomGrid(event):
     5475
     5476            r,c =  event.GetRow(),event.GetCol()
     5477            if r < 0 and c < 0:
     5478                for row in range(Atoms.GetNumberRows()):
     5479                    Atoms.SelectRow(row,True)                   
     5480            if r < 0:                          #double click on col label! Change all atoms!
     5481                sel = -1
     5482                noSkip = True
     5483                if Atoms.GetColLabelValue(c) == 'refine':
     5484                    Type = generalData['Type']
     5485                    if Type in ['nuclear','macromolecular']:
     5486                        choice = ['F - site fraction','X - coordinates','U - thermal parameters']
     5487                    elif Type in ['magnetic',]:
     5488                        choice = ['F - site fraction','X - coordinates','U - thermal parameters','M - magnetic moment']
     5489                    dlg = wx.MultiChoiceDialog(G2frame,'Select','Refinement controls',choice)
     5490                    if dlg.ShowModal() == wx.ID_OK:
     5491                        sel = dlg.GetSelections()
     5492                        parms = ''
     5493                        for x in sel:
     5494                            parms += choice[x][0]
     5495                    dlg.Destroy()
     5496                elif Atoms.GetColLabelValue(c) == 'I/A':
     5497                    choice = ['Isotropic','Anisotropic']
     5498                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Thermal Motion',choice)
     5499                    if dlg.ShowModal() == wx.ID_OK:
     5500                        sel = dlg.GetSelection()
     5501                        parms = choice[sel][0]
     5502                    dlg.Destroy()
     5503                elif Atoms.GetColLabelValue(c) == 'Type':
     5504                    choice = generalData['AtomTypes']
     5505                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom types',choice)
     5506                    if dlg.ShowModal() == wx.ID_OK:
     5507                        sel = dlg.GetSelection()
     5508                        parms = choice[sel]
     5509                        noSkip = False
     5510                        Atoms.ClearSelection()
     5511                        for row in range(Atoms.GetNumberRows()):
     5512                            if parms == atomData[row][c]:
     5513                                Atoms.SelectRow(row,True)
     5514                    dlg.Destroy()
     5515                    SetupGeneral()
     5516                elif Atoms.GetColLabelValue(c) == 'residue':
     5517                    choice = []
     5518                    for r in range(Atoms.GetNumberRows()):
     5519                        if str(atomData[r][c]) not in choice:
     5520                            choice.append(str(atomData[r][c]))
     5521                    choice.sort()
     5522                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Residue',choice)
     5523                    if dlg.ShowModal() == wx.ID_OK:
     5524                        sel = dlg.GetSelection()
     5525                        parms = choice[sel]
     5526                        noSkip = False
     5527                        Atoms.ClearSelection()
     5528                        for row in range(Atoms.GetNumberRows()):
     5529                            if parms == atomData[row][c]:
     5530                                Atoms.SelectRow(row,True)
     5531                    dlg.Destroy()
     5532                elif Atoms.GetColLabelValue(c) == 'res no':
     5533                    choice = []
     5534                    for r in range(Atoms.GetNumberRows()):
     5535                        if str(atomData[r][c]) not in choice:
     5536                            choice.append(str(atomData[r][c]))
     5537                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Residue no.',choice)
     5538                    if dlg.ShowModal() == wx.ID_OK:
     5539                        sel = dlg.GetSelection()
     5540                        parms = choice[sel]
     5541                        noSkip = False
     5542                        Atoms.ClearSelection()
     5543                        for row in range(Atoms.GetNumberRows()):
     5544                            if int(parms) == atomData[row][c]:
     5545                                Atoms.SelectRow(row,True)
     5546                    dlg.Destroy()
     5547                elif Atoms.GetColLabelValue(c) == 'chain':
     5548                    choice = []
     5549                    for r in range(Atoms.GetNumberRows()):
     5550                        if atomData[r][c] not in choice:
     5551                            choice.append(atomData[r][c])
     5552                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Chain',choice)
     5553                    if dlg.ShowModal() == wx.ID_OK:
     5554                        sel = dlg.GetSelection()
     5555                        parms = choice[sel]
     5556                        noSkip = False
     5557                        Atoms.ClearSelection()
     5558                        for row in range(Atoms.GetNumberRows()):
     5559                            if parms == atomData[row][c]:
     5560                                Atoms.SelectRow(row,True)
     5561                    dlg.Destroy()
     5562                elif Atoms.GetColLabelValue(c) == 'Uiso':       #this needs to ask for value
     5563                    pass                                        #& then change all 'I' atoms
     5564                if sel >= 0 and noSkip:
     5565                    ui = colLabels.index('U11')
     5566                    us = colLabels.index('Uiso')
     5567                    ss = colLabels.index('site sym')
     5568                    for r in range(Atoms.GetNumberRows()):
     5569                        ID = atomData[r][-1]
     5570                        if parms != atomData[r][c] and Atoms.GetColLabelValue(c) == 'I/A':
     5571                            if parms == 'A':                #'I' --> 'A'
     5572                                Uiso = float(Atoms.GetCellValue(r,us))
     5573                                sytsym = atomData[r][ss]
     5574                                CSI = G2spc.GetCSuinel(sytsym)
     5575                                atomData[r][ui:ui+6] = Uiso*np.array(CSI[3])
     5576                                atomData[r][us] = 0.0
     5577                                Atoms.SetCellStyle(r,us,VERY_LIGHT_GREY,True)
     5578                                for i in range(6):
     5579                                    ci = ui+i
     5580                                    Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
     5581                                    if CSI[2][i]:
     5582                                        Atoms.SetCellStyle(r,ci,WHITE,False)
     5583                            else:                           #'A' --> 'I'
     5584                                Uij = atomData[r][ui:ui+6]
     5585                                Uiso = (Uij[0]+Uij[1]+Uij[2])/3.0
     5586                                atomData[r][us] = Uiso
     5587                                Atoms.SetCellStyle(r,us,WHITE,False)
     5588                                for i in range(6):
     5589                                    ci = ui+i
     5590                                    atomData[r][ci] = 0.0
     5591                                    Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
     5592                        atomData[r][c] = parms
     5593                        if 'Atoms' in data['Drawing']:
     5594                            DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
     5595                    FillAtomsGrid()
     5596                   
     5597        def ChangeAtomCell(event):
     5598           
     5599            def chkUij(Uij,CSI): #needs to do something!!!
     5600                return Uij
     5601
     5602            r,c =  event.GetRow(),event.GetCol()
     5603            if r >= 0 and c >= 0:
     5604                ID = atomData[r][-1]
     5605                if Atoms.GetColLabelValue(c) in ['x','y','z']:
     5606                    ci = colLabels.index('x')
     5607                    XYZ = atomData[r][ci:ci+3]
     5608                    if None in XYZ:
     5609                        XYZ = [0,0,0]
     5610                    SScol = colLabels.index('site sym')
     5611                    Mulcol = colLabels.index('mult')
     5612                    E,SGData = G2spc.SpcGroup(generalData['SGData']['SpGrp'])
     5613                    Sytsym,Mult = G2spc.SytSym(XYZ,SGData)
     5614                    atomData[r][SScol] = Sytsym
     5615                    atomData[r][Mulcol] = Mult
     5616                    if atomData[r][colLabels.index('I/A')] == 'A':
     5617                        ui = colLabels.index('U11')
     5618                        CSI = G2spc.GetCSuinel(Sytsym)
     5619                        atomData[r][ui:ui+6] = chkUij(atomData[r][ui:ui+6],Sytsym)
     5620                        for i in range(6):
     5621                            ci = i+ui
     5622                            Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
     5623                            if CSI[2][i]:
     5624                                Atoms.SetCellStyle(r,ci,WHITE,False)
     5625                    SetupGeneral()
     5626                elif Atoms.GetColLabelValue(c) == 'I/A':            #note use of text color to make it vanish!
     5627                    if atomData[r][c] == 'I':
     5628                        Uij = atomData[r][c+2:c+8]
     5629                        atomData[r][c+1] = (Uij[0]+Uij[1]+Uij[2])/3.0
     5630                        Atoms.SetCellStyle(r,c+1,WHITE,False)
     5631                        Atoms.SetCellTextColour(r,c+1,BLACK)
     5632                        for i in range(6):
     5633                            ci = i+colLabels.index('U11')
     5634                            Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
     5635                            Atoms.SetCellTextColour(r,ci,VERY_LIGHT_GREY)
     5636                            atomData[r][ci] = 0.0
     5637                    else:
     5638                        value = atomData[r][c+1]
     5639                        CSI = G2spc.GetCSuinel(atomData[r][colLabels.index('site sym')])
     5640                        atomData[r][c+1] =  0.0
     5641                        Atoms.SetCellStyle(r,c+1,VERY_LIGHT_GREY,True)
     5642                        Atoms.SetCellTextColour(r,c+1,VERY_LIGHT_GREY)
     5643                        for i in range(6):
     5644                            ci = i+colLabels.index('U11')
     5645                            atomData[r][ci] = value*CSI[3][i]
     5646                            Atoms.SetCellStyle(r,ci,VERY_LIGHT_GREY,True)
     5647                            Atoms.SetCellTextColour(r,ci,BLACK)
     5648                            if CSI[2][i]:
     5649                                Atoms.SetCellStyle(r,ci,WHITE,False)
     5650                elif Atoms.GetColLabelValue(c) in ['U11','U22','U33','U12','U13','U23']:
     5651                    value = atomData[r][c]
     5652                    CSI = G2spc.GetCSuinel(atomData[r][colLabels.index('site sym')])
     5653                    iUij = CSI[0][c-colLabels.index('U11')]
     5654                    for i in range(6):
     5655                        if iUij == CSI[0][i]:
     5656                            atomData[r][i+colLabels.index('U11')] = value*CSI[1][i]
     5657                if 'Atoms' in data['Drawing']:
     5658                    DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
     5659                    FindBondsDraw()
     5660
     5661        def AtomTypeSelect(event):
     5662            r,c =  event.GetRow(),event.GetCol()
     5663            if Atoms.GetColLabelValue(c) == 'Type':
     5664                PE = G2elemGUI.PickElement(G2frame)
     5665                if PE.ShowModal() == wx.ID_OK:
     5666                    if PE.Elem != 'None':                       
     5667                        atomData[r][c] = PE.Elem.strip()
     5668                        name = atomData[r][c]
     5669                        if len(name) in [2,4]:
     5670                            atomData[r][c-1] = name[:2]+'(%d)'%(r+1)
     5671                        else:
     5672                            atomData[r][c-1] = name[:1]+'(%d)'%(r+1)
     5673                PE.Destroy()
     5674                SetupGeneral()
     5675                FillAtomsGrid()
     5676                value = Atoms.GetCellValue(r,c)
     5677                atomData[r][c] = value
     5678                ID = atomData[r][-1]
     5679                if 'Atoms' in data['Drawing']:
     5680                    DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
     5681                SetupGeneral()
     5682            else:
     5683                event.Skip()
     5684
     5685        def RowSelect(event):
     5686            r,c =  event.GetRow(),event.GetCol()
     5687            if r < 0 and c < 0:
     5688                if Atoms.IsSelection():
     5689                    Atoms.ClearSelection()
     5690            elif c < 0:                   #only row clicks
     5691                if event.ControlDown():                   
     5692                    if r in Atoms.GetSelectedRows():
     5693                        Atoms.DeselectRow(r)
     5694                    else:
     5695                        Atoms.SelectRow(r,True)
     5696                elif event.ShiftDown():
     5697                    for row in range(r+1):
     5698                        Atoms.SelectRow(row,True)
     5699                else:
     5700                    Atoms.ClearSelection()
     5701                    Atoms.SelectRow(r,True)
     5702               
     5703        def ChangeSelection(event):
     5704            r,c =  event.GetRow(),event.GetCol()
     5705            if r < 0 and c < 0:
     5706                Atoms.ClearSelection()
     5707            if c < 0:
     5708                if r in Atoms.GetSelectedRows():
     5709                    Atoms.DeselectRow(r)
     5710                else:
     5711                    Atoms.SelectRow(r,True)
     5712            if r < 0:
     5713                if c in Atoms.GetSelectedCols():
     5714                    Atoms.DeselectCol(c)
     5715                else:
     5716                    Atoms.SelectCol(c,True)
     5717       
     5718        SGData = data['General']['SGData']
     5719        G2frame.dataFrame.SetStatusText('')
     5720        if SGData['SGPolax']:
     5721            G2frame.dataFrame.SetStatusText('Warning: The location of the origin is arbitrary in '+SGData['SGPolax'])
     5722        table = []
     5723        rowLabels = []
     5724        for i,atom in enumerate(atomData):
     5725            table.append(atom)
     5726            rowLabels.append(str(i))
     5727        atomTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
     5728        Atoms.SetTable(atomTable, True)
     5729        Atoms.Bind(wg.EVT_GRID_CELL_CHANGE, ChangeAtomCell)
     5730        Atoms.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, AtomTypeSelect)
     5731        Atoms.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, RefreshAtomGrid)
     5732        Atoms.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
     5733        Atoms.Bind(wg.EVT_GRID_LABEL_RIGHT_CLICK, ChangeSelection)
     5734        Atoms.SetMargins(0,0)
     5735        Atoms.AutoSizeColumns(False)
     5736        colType = colLabels.index('Type')
     5737        colSS = colLabels.index('site sym')
     5738        colX = colLabels.index('x')
     5739        colIA = colLabels.index('I/A')
     5740        colU11 = colLabels.index('U11')
     5741        colUiso = colLabels.index('Uiso')
     5742        attr = wx.grid.GridCellAttr()
     5743        attr.SetEditor(GridFractionEditor(Atoms))
     5744        for c in range(colX,colX+3):
     5745            Atoms.SetColAttr(c, attr)
     5746        for i in range(colU11-1,colU11+6):
     5747            Atoms.SetColSize(i,50)           
     5748        for row in range(Atoms.GetNumberRows()):
     5749            Atoms.SetReadOnly(row,colType,True)
     5750            Atoms.SetReadOnly(row,colSS,True)                         #site sym
     5751            Atoms.SetReadOnly(row,colSS+1,True)                       #Mult
     5752            if Atoms.GetCellValue(row,colIA) == 'A':
     5753                CSI = G2spc.GetCSuinel(atomData[row][colLabels.index('site sym')])
     5754                Atoms.SetCellStyle(row,colUiso,VERY_LIGHT_GREY,True)
     5755                Atoms.SetCellTextColour(row,colUiso,VERY_LIGHT_GREY)
     5756                for i in range(6):
     5757                    ci = colU11+i
     5758                    Atoms.SetCellTextColour(row,ci,BLACK)
     5759                    Atoms.SetCellStyle(row,ci,VERY_LIGHT_GREY,True)
     5760                    if CSI[2][i]:
     5761                        Atoms.SetCellStyle(row,ci,WHITE,False)
     5762            else:
     5763                Atoms.SetCellStyle(row,colUiso,WHITE,False)
     5764                Atoms.SetCellTextColour(row,colUiso,BLACK)
     5765                for i in range(6):
     5766                    ci = colU11+i
     5767                    Atoms.SetCellStyle(row,ci,VERY_LIGHT_GREY,True)
     5768                    Atoms.SetCellTextColour(row,ci,VERY_LIGHT_GREY)
     5769
     5770    def OnAtomAdd(event):
     5771        AtomAdd(0,0,0)
     5772        FillAtomsGrid()
     5773        event.StopPropagation()
     5774       
     5775    def OnAtomViewAdd(event):
     5776        try:
     5777            drawData = data['Drawing']
     5778            x,y,z = drawData['viewPoint'][0]
     5779            AtomAdd(x,y,z)
     5780        except:
     5781            AtomAdd(0,0,0)
     5782        FillAtomsGrid()
     5783        event.StopPropagation()
     5784               
     5785    def AtomAdd(x,y,z,El='H'):
     5786        atomData = data['Atoms']
     5787        generalData = data['General']
     5788        Ncol = Atoms.GetNumberCols()
     5789        atId = ran.randint(0,sys.maxint)
     5790        E,SGData = G2spc.SpcGroup(generalData['SGData']['SpGrp'])
     5791        Sytsym,Mult = G2spc.SytSym([x,y,z],SGData)
     5792        if generalData['Type'] == 'macromolecular':
     5793            atomData.append([0,'UNK','','UNK',El,'',x,y,z,1,Sytsym,Mult,'I',0.10,0,0,0,0,0,0,atId])
     5794        elif generalData['Type'] == 'nuclear':
     5795            atomData.append(['UNK',El,'',x,y,z,1,Sytsym,Mult,'I',0.01,0,0,0,0,0,0,atId])
     5796        elif generalData['Type'] == 'magnetic':
     5797            atomData.append(['UNK',El,'',x,y,z,1,Sytsym,Mult,0,'I',0.01,0,0,0,0,0,0,0,0,0,atId])
     5798        SetupGeneral()
     5799        if 'Atoms' in data['Drawing']:           
     5800            DrawAtomAdd(data['Drawing'],atomData[-1])
     5801            G2plt.PlotStructure(G2frame,data)
     5802
     5803    def OnAtomInsert(event):
     5804        AtomInsert(0,0,0)
     5805        FillAtomsGrid()
     5806        event.StopPropagation()
     5807       
     5808    def OnAtomViewInsert(event):
     5809        if 'Drawing' in data:
     5810            drawData = data['Drawing']
     5811            x,y,z = drawData['viewPoint'][0]
     5812            AtomAdd(x,y,z)
     5813            FillAtomsGrid()
     5814        event.StopPropagation()
     5815           
     5816    def AtomInsert(x,y,z):
     5817        indx = Atoms.GetSelectedRows()
     5818        if indx:
     5819            indx = indx[0]
     5820            atomData = data['Atoms']
     5821            generalData = data['General']
     5822            Ncol = Atoms.GetNumberCols()
     5823            E,SGData = G2spc.SpcGroup(generalData['SGData']['SpGrp'])
     5824            Sytsym,Mult = G2spc.SytSym([0,0,0],SGData)
     5825            atId = ran.randint(0,sys.maxint)
     5826            if generalData['Type'] == 'macromolecular':
     5827                atomData.insert(indx,[0,'UNK','','UNK','UNK','',x,y,z,1,Sytsym,Mult,'I',0.10,0,0,0,0,0,0,atId])
     5828            elif generalData['Type'] == 'nuclear':
     5829                atomData.insert(indx,['UNK','UNK','',x,y,z,1,Sytsym,Mult,'I',0.01,0,0,0,0,0,0,atId])
     5830            elif generalData['Type'] == 'magnetic':
     5831                atomData.insert(indx,['UNK','UNK','',x,y,z,1,Sytsym,Mult,0,'I',0.01,0,0,0,0,0,0,0,0,0,atId])
     5832            SetupGeneral()
     5833
     5834    def AtomDelete(event):
     5835        indx = Atoms.GetSelectedRows()
     5836        IDs = []
     5837        if indx:
     5838            atomData = data['Atoms']
     5839            indx.reverse()
     5840            for ind in indx:
     5841                atom = atomData[ind]
     5842                IDs.append(atom[-1])
     5843                del atomData[ind]
     5844            if 'Atoms' in data['Drawing']:
     5845                DrawAtomsDeleteByIDs(IDs)
     5846                wx.CallAfter(FillAtomsGrid)
     5847                G2plt.PlotStructure(G2frame,data)
     5848            SetupGeneral()
     5849        event.StopPropagation()
     5850
     5851    def AtomRefine(event):
     5852        colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
     5853        c = colLabels.index('refine')
     5854        indx = Atoms.GetSelectedRows()
     5855        if indx:
     5856            atomData = data['Atoms']
     5857            generalData = data['General']
     5858            Type = generalData['Type']
     5859            if Type in ['nuclear','macromolecular']:
     5860                choice = ['F - site fraction','X - coordinates','U - thermal parameters']
     5861            elif Type == 'magnetic':
     5862                choice = ['F - site fraction','X - coordinates','U - thermal parameters','M - magnetic moment']
     5863            dlg = wx.MultiChoiceDialog(G2frame,'Select','Refinement controls',choice)
     5864            if dlg.ShowModal() == wx.ID_OK:
     5865                sel = dlg.GetSelections()
     5866                parms = ''
     5867                for x in sel:
     5868                    parms += choice[x][0]
     5869                for r in indx:
     5870                    atomData[r][c] = parms
     5871                Atoms.ForceRefresh()
     5872            dlg.Destroy()
     5873
     5874    def AtomModify(event):                  #intent to implement global modifications (+,-,*,/, etc.)?
     5875        indx = Atoms.GetSelectedRows()
     5876        if indx:
     5877            atomData = data['Atoms']
     5878            generalData = data['General']
     5879            colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
     5880            choices = ['Type','Name','x','y','z','frac','I/A','Uiso']
     5881            dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom parameter',choices)
     5882            if dlg.ShowModal() == wx.ID_OK:
     5883                sel = dlg.GetSelection()
     5884                parm = choices[sel]
     5885                cid = colLabels.index(parm)
     5886            dlg.Destroy()
     5887            if parm in ['Type']:
     5888                dlg = G2elemGUI.PickElement(G2frame)
     5889                if dlg.ShowModal() == wx.ID_OK:
     5890                    if dlg.Elem not in ['None']:
     5891                        El = dlg.Elem.strip()
     5892                        for r in indx:                       
     5893                            atomData[r][cid] = El
     5894                            if len(El) in [2,4]:
     5895                                atomData[r][cid-1] = El[:2]+'(%d)'%(r+1)
     5896                            else:
     5897                                atomData[r][cid-1] = El[:1]+'(%d)'%(r+1)
     5898                        SetupGeneral()
     5899                        if 'Atoms' in data['Drawing']:
     5900                            for r in indx:
     5901                                ID = atomData[r][-1]
     5902                                DrawAtomsReplaceByID(data['Drawing'],atomData[r],ID)
     5903                    FillAtomsGrid()
     5904                dlg.Destroy()
     5905            elif parm in ['Name',]:
     5906                dlg = wx.MessageDialog(G2frame,'Do you really want to rename the selected atoms?','Rename',
     5907                    wx.YES_NO | wx.ICON_QUESTION)
     5908                try:
     5909                    result = dlg.ShowModal()
     5910                    if result == wx.ID_YES:
     5911                        for r in indx:
     5912                            El = atomData[r][cid+1]
     5913                            if len(El) in [2,4]:
     5914                                atomData[r][cid] = El[:2]+'(%d)'%(r+1)
     5915                            else:
     5916                                atomData[r][cid] = El[:1]+'(%d)'%(r+1)
     5917                    FillAtomsGrid()
     5918                finally:
     5919                    dlg.Destroy()
     5920                   
     5921            elif parm in ['I/A']:
     5922                choices = ['Isotropic','Anisotropic']
     5923                dlg = wx.SingleChoiceDialog(G2frame,'Select','Thermal parameter model',choices)
     5924                if dlg.ShowModal() == wx.ID_OK:
     5925                    sel = dlg.GetSelection()
     5926                    parm = choices[sel][0]
     5927                    for r in indx:                       
     5928                        atomData[r][cid] = parm
     5929                    FillAtomsGrid()
     5930                dlg.Destroy()
     5931            elif parm in ['frac','Uiso']:
     5932                limits = [0.,1.]
     5933                val = 1.0
     5934                if  parm in ['Uiso']:
     5935                    limits = [0.,0.25]
     5936                    val = 0.01
     5937                dlg = SingleFloatDialog(G2frame,'New value','Enter new value for '+parm,val,limits)
     5938                if dlg.ShowModal() == wx.ID_OK:
     5939                    parm = dlg.GetValue()
     5940                    for r in indx:                       
     5941                        atomData[r][cid] = parm
     5942                    SetupGeneral()
     5943                    FillAtomsGrid()
     5944                dlg.Destroy()
     5945            elif parm in ['x','y','z']:
     5946                limits = [-1.,1.]
     5947                val = 0.
     5948                dlg = SingleFloatDialog(G2frame,'Atom shift','Enter shift for '+parm,val,limits)
     5949                if dlg.ShowModal() == wx.ID_OK:
     5950                    parm = dlg.GetValue()
     5951                    for r in indx:                       
     5952                        atomData[r][cid] += parm
     5953                    SetupGeneral()
     5954                    FillAtomsGrid()
     5955                dlg.Destroy()
     5956
     5957    def AtomTransform(event):
     5958        indx = Atoms.GetSelectedRows()
     5959        if indx:
     5960            generalData = data['General']
     5961            colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
     5962            cx = colLabels.index('x')
     5963            cuia = colLabels.index('I/A')
     5964            cuij = colLabels.index('U11')
     5965            css = colLabels.index('site sym')
     5966            atomData = data['Atoms']
     5967            generalData = data['General']
     5968            SGData = generalData['SGData']
     5969            dlg = SymOpDialog(G2frame,SGData,True,True)
     5970            try:
     5971                if dlg.ShowModal() == wx.ID_OK:
     5972                    Inv,Cent,Opr,Cell,New,Force = dlg.GetSelection()
     5973                    Cell = np.array(Cell)
     5974                    cent = SGData['SGCen'][Cent]
     5975                    M,T = SGData['SGOps'][Opr]
     5976                    for ind in indx:
     5977                        XYZ = np.array(atomData[ind][cx:cx+3])
     5978                        XYZ = np.inner(M,XYZ)+T
     5979                        if Inv:
     5980                            XYZ = -XYZ
     5981                        XYZ = XYZ+cent+Cell
     5982                        if Force:
     5983                            XYZ = G2spc.MoveToUnitCell(XYZ)
     5984                        if New:
     5985                            atom = copy.copy(atomData[ind])
     5986                        else:
     5987                            atom = atomData[ind]
     5988                        atom[cx:cx+3] = XYZ
     5989                        atom[css:css+2] = G2spc.SytSym(XYZ,SGData)
     5990                        if atom[cuia] == 'A':
     5991                            Uij = atom[cuij:cuij+6]
     5992                            U = G2spc.Uij2U(Uij)
     5993                            U = np.inner(np.inner(M,U),M)
     5994                            Uij = G2spc.U2Uij(U)
     5995                            atom[cuij:cuij+6] = Uij
     5996                        if New:
     5997                            atomData.append(atom)
     5998            finally:
     5999                dlg.Destroy()
     6000            Atoms.ClearSelection()
     6001            if New:
     6002                FillAtomsGrid()
     6003            else:
     6004                Atoms.ForceRefresh()
     6005
     6006    def OnDistAngle(event):
     6007        indx = Atoms.GetSelectedRows()
     6008        Oxyz = []
     6009        xyz = []
     6010        DisAglData = {}
     6011        DisAglCtls = {}
     6012        if indx:
     6013            generalData = data['General']
     6014            DisAglData['OrigIndx'] = indx
     6015            if 'DisAglCtls' in generalData:
     6016                DisAglCtls = generalData['DisAglCtls']
     6017            dlg = DisAglDialog(G2frame,DisAglCtls,generalData)
     6018            if dlg.ShowModal() == wx.ID_OK:
     6019                DisAglCtls = dlg.GetData()
     6020            dlg.Destroy()
     6021            generalData['DisAglCtls'] = DisAglCtls
     6022            atomData = data['Atoms']
     6023            colLabels = [Atoms.GetColLabelValue(c) for c in range(Atoms.GetNumberCols())]
     6024            cx = colLabels.index('x')
     6025            cn = colLabels.index('Name')
     6026            for i,atom in enumerate(atomData):
     6027                xyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+3])
     6028                if i in indx:
     6029                    Oxyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+3])
     6030            DisAglData['OrigAtoms'] = Oxyz
     6031            DisAglData['TargAtoms'] = xyz
     6032            generalData = data['General']
     6033            DisAglData['SGData'] = generalData['SGData']
     6034            DisAglData['Cell'] = generalData['Cell'][1:] #+ volume
     6035            if 'pId' in data:
     6036                DisAglData['pId'] = data['pId']
     6037                DisAglData['covData'] = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Covariance'))
     6038            G2str.DistAngle(DisAglCtls,DisAglData)
     6039                       
     6040################################################################################
     6041#Structure drawing GUI stuff               
     6042################################################################################
     6043
     6044    def SetupDrawingData():
     6045        generalData = data['General']
     6046        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
     6047        atomData = data['Atoms']
     6048        AA3letter = ['ALA','ARG','ASN','ASP','CYS','GLN','GLU','GLY','HIS','ILE',
     6049            'LEU','LYS','MET','PHE','PRO','SER','THR','TRP','TYR','VAL','MSE','HOH','WAT','UNK']
     6050        AA1letter = ['A','R','N','D','C','Q','E','G','H','I',
     6051            'L','K','M','F','P','S','T','W','Y','V','M',' ',' ',' ']
     6052        defaultDrawing = {'Atoms':[],'viewPoint':[[0.5,0.5,0.5],[]],'showHydrogen':True,
     6053            'backColor':[0,0,0],'depthFog':False,'Zclip':50.0,'cameraPos':50.,'Zstep':0.5,
     6054            'radiusFactor':0.85,'contourLevel':1.,'bondRadius':0.1,'ballScale':0.33,
     6055            'vdwScale':0.67,'ellipseProb':50,'sizeH':0.50,'unitCellBox':False,
     6056            'showABC':True,'selectedAtoms':[],'Atoms':[],'oldxy':[],
     6057            'bondList':{},'viewDir':[1,0,0]}
     6058        V0 = np.array([0,0,1])
     6059        V = np.inner(Amat,V0)
     6060        V /= np.sqrt(np.sum(V**2))
     6061        A = np.arccos(np.sum(V*V0))
     6062        defaultDrawing['Quaternion'] = G2mth.AV2Q(A,[0,1,0])
     6063        try:
     6064            drawingData = data['Drawing']
     6065        except KeyError:
     6066            data['Drawing'] = {}
     6067            drawingData = data['Drawing']
     6068        if not drawingData:                 #fill with defaults if empty
     6069            drawingData.update(defaultDrawing)
     6070        if 'Zstep' not in drawingData:
     6071            drawingData['Zstep'] = 0.5
     6072        if 'contourLevel' not in drawingData:
     6073            drawingData['contourLevel'] = 1.
     6074        if 'viewDir' not in drawingData:
     6075            drawingData['viewDir'] = [0,0,1]
     6076        if 'Quaternion' not in drawingData:
     6077            drawingData['Quaternion'] = G2mth.AV2Q(2*np.pi,np.inner(Amat,[0,0,1]))
     6078        cx,ct,cs,ci = [0,0,0,0]
     6079        if generalData['Type'] == 'nuclear':
     6080            cx,ct,cs,ci = [2,1,6,17]         #x, type, style & index
     6081        elif generalData['Type'] == 'macromolecular':
     6082            cx,ct,cs,ci = [5,4,9,20]         #x, type, style & index
     6083        elif generalData['Type'] == 'magnetic':
     6084            cx,ct,cs,ci = [2,1,6,20]         #x, type, style & index
     6085#        elif generalData['Type'] == 'modulated':
     6086#           ?????   for future
     6087        drawingData['atomPtrs'] = [cx,ct,cs,ci]
     6088        if not drawingData.get('Atoms'):
     6089            for atom in atomData:
     6090                DrawAtomAdd(drawingData,atom)
     6091            data['Drawing'] = drawingData
     6092           
     6093    def MakeDrawAtom(atom,oldatom=None):
     6094        AA3letter = ['ALA','ARG','ASN','ASP','CYS','GLN','GLU','GLY','HIS','ILE',
     6095            'LEU','LYS','MET','PHE','PRO','SER','THR','TRP','TYR','VAL','MSE','HOH','WAT','UNK']
     6096        AA1letter = ['A','R','N','D','C','Q','E','G','H','I',
     6097            'L','K','M','F','P','S','T','W','Y','V','M',' ',' ',' ']
     6098        generalData = data['General']
     6099        SGData = generalData['SGData']
     6100        if generalData['Type'] == 'nuclear':
     6101            if oldatom:
     6102                opr = oldatom[5]
     6103                if atom[9] == 'A':                   
     6104                    X,U = G2spc.ApplyStringOps(opr,SGData,atom[3:6],atom[11:17])
     6105                    atomInfo = [atom[:2]+list(X)+oldatom[5:9]+atom[9:11]+list(U)+oldatom[17:]][0]
     6106                else:
     6107                    X = G2spc.ApplyStringOps(opr,SGData,atom[3:6])
     6108                    atomInfo = [atom[:2]+list(X)+oldatom[5:9]+atom[9:]+[oldatom[-1]]][0]
     6109            else:
     6110                atomInfo = [atom[:2]+atom[3:6]+['1',]+['vdW balls',]+
     6111                    ['',]+[[255,255,255],]+atom[9:]+[[],[]]][0]
     6112            ct,cs = [1,8]         #type & color
     6113        elif generalData['Type'] == 'macromolecular':
     6114            try:
     6115                oneLetter = AA3letter.index(atom[1])
     6116            except ValueError:
     6117                oneLetter = -1
     6118            atomInfo = [[atom[1].strip()+atom[0],]+
     6119                [AA1letter[oneLetter]+atom[0],]+atom[2:5]+
     6120                atom[6:9]+['1',]+['sticks',]+['',]+[[255,255,255],]+atom[12:]+[[],[]]][0]
     6121            ct,cs = [4,11]         #type & color
     6122        elif generalData['Type'] == 'magnetic':
     6123            if oldatom:
     6124                atomInfo = [atom[:2]+oldatom[3:]][0]
     6125            else:
     6126                atomInfo = [atom[:2]+atom[3:6]+['vdW balls',]+['',]+atom[9:]+[[],[]]][0]
     6127            ct,cs = [1,8]         #type & color
     6128#        elif generalData['Type'] == 'modulated':
     6129#           ?????   for future
     6130        atNum = generalData['AtomTypes'].index(atom[ct])
     6131        atomInfo[cs] = list(generalData['Color'][atNum])
     6132        return atomInfo
     6133           
     6134    def DrawAtomAdd(drawingData,atom):
     6135        drawingData['Atoms'].append(MakeDrawAtom(atom))
     6136       
     6137    def DrawAtomsReplaceByID(drawingData,atom,ID):
     6138        IDs = [ID,]
     6139        atomData = drawingData['Atoms']
     6140        indx = FindAtomIndexByIDs(atomData,IDs)
     6141        for ind in indx:
     6142            atomData[ind] = MakeDrawAtom(atom,atomData[ind])
     6143           
     6144    def OnRestraint(event):       
     6145        indx = drawAtoms.GetSelectedRows()
     6146        restData = G2frame.PatternTree.GetItemPyData(   
     6147            G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Restraints'))
     6148        drawingData = data['Drawing']
     6149        generalData = data['General']
     6150        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
     6151        cx,ct,cs,ci = drawingData['atomPtrs']
     6152        atomData = drawingData['Atoms']
     6153        atNames = []
     6154        atXYZ = []
     6155        atSymOp = []
     6156        atIndx = []
     6157        for item in indx:
     6158            atNames.append(atomData[item][ct-1])
     6159            atXYZ.append(np.array(atomData[item][cx:cx+3]))
     6160            atSymOp.append(atomData[item][cs-1])
     6161            atIndx.append(atomData[item][ci])
     6162        if event.GetId() == G2gd.wxID_DRAWRESTRBOND and len(indx) == 2:
     6163            try:
     6164                bondData = restData[PhaseName]['Bond']
     6165            except KeyError:
     6166                bondData = {'wtFactor':1.0,'Bonds':[]}
     6167                restData[PhaseName] = {}
     6168                restData[PhaseName]['Bond'] = bondData
     6169            dist = G2mth.getRestDist(atXYZ,Amat)
     6170            bondData['Bonds'].append([atNames,atSymOp,atIndx,dist,1.54,0.01])
     6171        elif event.GetId() == G2gd.wxID_DRAWRESTRANGLE and len(indx) == 3:
     6172            try:
     6173                angleData = restData[PhaseName]['Angle']
     6174            except KeyError:
     6175                angleData = {'wtFactor':1.0,'Angles':[]}
     6176                restData[PhaseName] = {}
     6177                restData[PhaseName]['Angle'] = angleData
     6178            angle = G2mth.getRestAngle(atXYZ,Amat)
     6179            angleData['Angles'].append([atNames,atSymOp,atIndx,angle,109.5,1.0])           
     6180        elif event.GetId() == G2gd.wxID_DRAWRESTRPLANE and len(indx) > 3:
     6181            try:
     6182                planeData = restData[PhaseName]['Plane']
     6183            except KeyError:
     6184                planeData = {'wtFactor':1.0,'Planes':[]}
     6185                restData[PhaseName] = {}
     6186                restData[PhaseName]['Plane'] = planeData
     6187            plane = G2mth.getRestPlane(atXYZ,Amat)
     6188            planeData['Planes'].append([atNames,atSymOp,atIndx,plane,0.0,0.01])           
     6189        elif event.GetId() == G2gd.wxID_DRAWRESTRCHIRAL and len(indx) == 4:
     6190            try:
     6191                chiralData = restData[PhaseName]['Chiral']
     6192            except KeyError:
     6193                chiralData = {'wtFactor':1.0,'Volumes':[]}
     6194                restData[PhaseName] = {}
     6195                restData[PhaseName]['Chiral'] = chiralData
     6196            volume = G2mth.getRestChiral(atXYZ,Amat)
     6197            chiralData['Volumes'].append([atNames,atSymOp,atIndx,volume,2.5,0.1])           
     6198        else:
     6199            print '**** ERROR wrong number of atoms selected for this restraint'
     6200            return
     6201        G2frame.PatternTree.SetItemPyData(   
     6202            G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Restraints'),restData)
     6203
     6204################################################################################
     6205##### Atom draw routines
     6206################################################################################
     6207           
     6208    def UpdateDrawAtoms():
     6209        G2frame.dataFrame.SetStatusText('')
     6210        generalData = data['General']
     6211        SetupDrawingData()
     6212        drawingData = data['Drawing']
     6213        cx,ct,cs,ci = drawingData['atomPtrs']
     6214        atomData = drawingData['Atoms']
     6215        Types = [wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,]+3*[wg.GRID_VALUE_FLOAT+':10,5',]+ \
     6216            [wg.GRID_VALUE_STRING,wg.GRID_VALUE_CHOICE+": ,lines,vdW balls,sticks,balls & sticks,ellipsoids,polyhedra",
     6217            wg.GRID_VALUE_CHOICE+": ,type,name,number",wg.GRID_VALUE_STRING,wg.GRID_VALUE_STRING,]
     6218        styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','polyhedra']
     6219        labelChoice = [' ','type','name','number']
     6220        colLabels = ['Name','Type','x','y','z','Sym Op','Style','Label','Color','I/A']
     6221        if generalData['Type'] == 'macromolecular':
     6222            colLabels = ['Residue','1-letter','Chain'] + colLabels
     6223            Types = 3*[wg.GRID_VALUE_STRING,]+Types
     6224            Types[8] = wg.GRID_VALUE_CHOICE+": ,lines,vdW balls,sticks,balls & sticks,ellipsoids,backbone,ribbons,schematic"
     6225            styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','backbone','ribbons','schematic']
     6226            labelChoice = [' ','type','name','number','residue','1-letter','chain']
     6227            Types[9] = wg.GRID_VALUE_CHOICE+": ,type,name,number,residue,1-letter,chain"
     6228#        elif generalData['Type'] == 'modulated':
     6229#            Types += []
     6230#            colLabels += []
     6231
     6232        def RefreshAtomGrid(event):
     6233
     6234            def SetChoice(name,c,n=0):
     6235                choice = []
     6236                for r in range(len(atomData)):
     6237                    if n:
     6238                        srchStr = str(atomData[r][c][:n])
     6239                    else:
     6240                        srchStr = str(atomData[r][c])
     6241                    if srchStr not in choice:
     6242                        if n:
     6243                            choice.append(str(atomData[r][c][:n]))
     6244                        else:
     6245                            choice.append(str(atomData[r][c]))
     6246                choice.sort()
     6247
     6248                dlg = wx.MultiChoiceDialog(G2frame,'Select',name,choice)
     6249                if dlg.ShowModal() == wx.ID_OK:
     6250                    sel = dlg.GetSelections()
     6251                    parms = []
     6252                    for x in sel:
     6253                        parms.append(choice[x])
     6254                    noSkip = False
     6255                    drawAtoms.ClearSelection()
     6256                    drawingData['selectedAtoms'] = []
     6257                    for row in range(len(atomData)):
     6258                        test = atomData[row][c]
     6259                        if n:
     6260                            test = test[:n]
     6261                        if  test in parms:
     6262                            drawAtoms.SelectRow(row,True)
     6263                            drawingData['selectedAtoms'].append(row)
     6264                    G2plt.PlotStructure(G2frame,data)                   
     6265                dlg.Destroy()
     6266               
     6267            r,c =  event.GetRow(),event.GetCol()
     6268            if r < 0 and c < 0:
     6269                for row in range(drawAtoms.GetNumberRows()):
     6270                    drawingData['selectedAtoms'].append(row)
     6271                    drawAtoms.SelectRow(row,True)                   
     6272            elif r < 0:                          #dclick on col label
     6273                sel = -1
     6274                Parms = False
     6275                noSkip = True
     6276                if drawAtoms.GetColLabelValue(c) == 'Style':
     6277                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom drawing style',styleChoice)
     6278                    if dlg.ShowModal() == wx.ID_OK:
     6279                        sel = dlg.GetSelection()
     6280                        parms = styleChoice[sel]
     6281                        for r in range(len(atomData)):
     6282                            atomData[r][c] = parms
     6283                            drawAtoms.SetCellValue(r,c,parms)
     6284                        FindBondsDraw()
     6285                        G2plt.PlotStructure(G2frame,data)
     6286                    dlg.Destroy()
     6287                elif drawAtoms.GetColLabelValue(c) == 'Label':
     6288                    dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom labelling style',labelChoice)
     6289                    if dlg.ShowModal() == wx.ID_OK:
     6290                        sel = dlg.GetSelection()
     6291                        parms = labelChoice[sel]
     6292                        for r in range(len(atomData)):
     6293                            atomData[r][c] = parms
     6294                            drawAtoms.SetCellValue(r,c,parms)
     6295                    dlg.Destroy()                   
     6296                elif drawAtoms.GetColLabelValue(c) == 'Color':
     6297                    dlg = wx.ColourDialog(G2frame)
     6298                    if dlg.ShowModal() == wx.ID_OK:
     6299                        color = dlg.GetColourData().GetColour()
     6300                        attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
     6301                        attr.SetReadOnly(True)
     6302                        attr.SetBackgroundColour(color)
     6303                        for r in range(len(atomData)):
     6304                            atomData[r][c] = color
     6305                            drawingData['Atoms'][r][c] = color
     6306                            drawAtoms.SetAttr(r,c,attr)
     6307                        UpdateDrawAtoms()
     6308                    dlg.Destroy()
     6309                elif drawAtoms.GetColLabelValue(c) == 'Residue':
     6310                    SetChoice('Residue',c,3)
     6311                elif drawAtoms.GetColLabelValue(c) == '1-letter':
     6312                    SetChoice('1-letter',c,1)
     6313                elif drawAtoms.GetColLabelValue(c) == 'Chain':
     6314                    SetChoice('Chain',c)
     6315                elif drawAtoms.GetColLabelValue(c) == 'Name':
     6316                    SetChoice('Name',c)
     6317                elif drawAtoms.GetColLabelValue(c) == 'Sym Op':
     6318                    SetChoice('Name',c)
     6319                elif drawAtoms.GetColLabelValue(c) == 'Type':
     6320                    SetChoice('Type',c)
     6321                elif drawAtoms.GetColLabelValue(c) in ['x','y','z','I/A']:
     6322                    drawAtoms.ClearSelection()
     6323            else:
     6324                if drawAtoms.GetColLabelValue(c) in ['Style','Label']:
     6325                    atomData[r][c] = drawAtoms.GetCellValue(r,c)
     6326                    FindBondsDraw()
     6327                elif drawAtoms.GetColLabelValue(c) == 'Color':
     6328                    dlg = wx.ColourDialog(G2frame)
     6329                    if dlg.ShowModal() == wx.ID_OK:
     6330                        color = dlg.GetColourData().GetColour()
     6331                        attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
     6332                        attr.SetReadOnly(True)
     6333                        attr.SetBackgroundColour(color)
     6334                        atomData[r][c] = color
     6335                        drawingData['Atoms'][r][c] = color
     6336                        drawAtoms.SetAttr(i,cs+2,attr)
     6337                    dlg.Destroy()
     6338                    UpdateDrawAtoms()
     6339            G2plt.PlotStructure(G2frame,data)
     6340                   
     6341        def RowSelect(event):
     6342            r,c =  event.GetRow(),event.GetCol()
     6343            if r < 0 and c < 0:
     6344                if drawAtoms.IsSelection():
     6345                    drawAtoms.ClearSelection()
     6346            elif c < 0:                   #only row clicks
     6347                if event.ControlDown():                   
     6348                    if r in drawAtoms.GetSelectedRows():
     6349                        drawAtoms.DeselectRow(r)
     6350                    else:
     6351                        drawAtoms.SelectRow(r,True)
     6352                elif event.ShiftDown():
     6353                    for row in range(r+1):
     6354                        drawAtoms.SelectRow(row,True)
     6355                else:
     6356                    drawAtoms.ClearSelection()
     6357                    drawAtoms.SelectRow(r,True)               
     6358            drawingData['selectedAtoms'] = []
     6359            drawingData['selectedAtoms'] = drawAtoms.GetSelectedRows()
     6360            G2plt.PlotStructure(G2frame,data)                   
     6361               
     6362        table = []
     6363        rowLabels = []
     6364        for i,atom in enumerate(drawingData['Atoms']):
     6365            table.append(atom[:colLabels.index('I/A')+1])
     6366            rowLabels.append(str(i))
     6367
     6368        atomTable = G2gd.Table(table,rowLabels=rowLabels,colLabels=colLabels,types=Types)
     6369        drawAtoms.SetTable(atomTable, True)
     6370        drawAtoms.SetMargins(0,0)
     6371        drawAtoms.AutoSizeColumns(True)
     6372        drawAtoms.SetColSize(colLabels.index('Style'),80)
     6373        drawAtoms.SetColSize(colLabels.index('Color'),50)
     6374        drawAtoms.Bind(wg.EVT_GRID_CELL_CHANGE, RefreshAtomGrid)
     6375        drawAtoms.Bind(wg.EVT_GRID_LABEL_LEFT_DCLICK, RefreshAtomGrid)
     6376        drawAtoms.Bind(wg.EVT_GRID_CELL_LEFT_DCLICK, RefreshAtomGrid)
     6377        drawAtoms.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
     6378        for i,atom in enumerate(drawingData['Atoms']):
     6379            attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
     6380            attr.SetReadOnly(True)
     6381            attr.SetBackgroundColour(atom[cs+2])
     6382            drawAtoms.SetAttr(i,cs+2,attr)
     6383            drawAtoms.SetCellValue(i,cs+2,'')
     6384        indx = drawingData['selectedAtoms']
     6385        if indx:
     6386            for r in range(len(atomData)):
     6387                if r in indx:
     6388                    drawAtoms.SelectRow(r)
     6389        for c in range(len(colLabels)):
     6390           attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
     6391           attr.SetReadOnly(True)
     6392           attr.SetBackgroundColour(VERY_LIGHT_GREY)
     6393           if colLabels[c] not in ['Style','Label','Color']:
     6394                drawAtoms.SetColAttr(c,attr)
     6395        G2frame.dataFrame.setSizePosLeft([600,300])
     6396       
     6397        FindBondsDraw()
     6398        drawAtoms.ClearSelection()
     6399        G2plt.PlotStructure(G2frame,data)
     6400
     6401    def DrawAtomStyle(event):
     6402        indx = drawAtoms.GetSelectedRows()
     6403        if indx:
     6404            generalData = data['General']
     6405            atomData = data['Drawing']['Atoms']
     6406            cx,ct,cs,ci = data['Drawing']['atomPtrs']
     6407            styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids','polyhedra']
     6408            if generalData['Type'] == 'macromolecular':
     6409                styleChoice = [' ','lines','vdW balls','sticks','balls & sticks','ellipsoids',
     6410                'backbone','ribbons','schematic']
     6411            dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom drawing style',styleChoice)
     6412            if dlg.ShowModal() == wx.ID_OK:
     6413                sel = dlg.GetSelection()
     6414                parms = styleChoice[sel]
     6415                for r in indx:
     6416                    atomData[r][cs] = parms
     6417                    drawAtoms.SetCellValue(r,cs,parms)
     6418            dlg.Destroy()
     6419            FindBondsDraw()
     6420            drawAtoms.ClearSelection()
     6421            G2plt.PlotStructure(G2frame,data)
     6422
     6423    def DrawAtomLabel(event):
     6424        indx = drawAtoms.GetSelectedRows()
     6425        if indx:
     6426            generalData = data['General']
     6427            atomData = data['Drawing']['Atoms']
     6428            cx,ct,cs,ci = data['Drawing']['atomPtrs']
     6429            styleChoice = [' ','type','name','number']
     6430            if generalData['Type'] == 'macromolecular':
     6431                styleChoice = [' ','type','name','number','residue','1-letter','chain']
     6432            dlg = wx.SingleChoiceDialog(G2frame,'Select','Atom label style',styleChoice)
     6433            if dlg.ShowModal() == wx.ID_OK:
     6434                sel = dlg.GetSelection()
     6435                parms = styleChoice[sel]
     6436                for r in indx:
     6437                    atomData[r][cs+1] = parms
     6438                    drawAtoms.SetCellValue(r,cs+1,parms)
     6439            dlg.Destroy()
     6440            drawAtoms.ClearSelection()
     6441            G2plt.PlotStructure(G2frame,data)
     6442           
     6443    def DrawAtomColor(event):
     6444
     6445        indx = drawAtoms.GetSelectedRows()
     6446        if indx:
     6447            if len(indx) > 1:
     6448                G2frame.dataFrame.SetStatusText('Select Custom Color, change color, Add to Custom Colors, then OK')
     6449            else:
     6450                G2frame.dataFrame.SetStatusText('Change color, Add to Custom Colors, then OK')
     6451            generalData = data['General']
     6452            atomData = data['Drawing']['Atoms']
     6453            cx,ct,cs,ci = data['Drawing']['atomPtrs']
     6454            atmColors = []
     6455            atmTypes = []
     6456            for r in indx:
     6457                if atomData[r][cs+2] not in atmColors:
     6458                    atmColors.append(atomData[r][cs+2])
     6459                    atmTypes.append(atomData[r][ct])
     6460                    if len(atmColors) > 16:
     6461                        break
     6462            colors = wx.ColourData()
     6463            colors.SetChooseFull(True)
     6464            dlg = wx.ColourDialog(G2frame)
     6465            if dlg.ShowModal() == wx.ID_OK:
     6466                for i in range(len(atmColors)):                   
     6467                    atmColors[i] = dlg.GetColourData().GetColour()
     6468                colorDict = dict(zip(atmTypes,atmColors))
     6469                for r in indx:
     6470                    color = colorDict[atomData[r][ct]]
     6471                    atomData[r][cs+2] = color
     6472                    attr = wg.GridCellAttr()                #needs to be here - gets lost if outside loop!
     6473                    attr.SetBackgroundColour(color)
     6474                    drawAtoms.SetAttr(r,cs+2,attr)
     6475                    data['Drawing']['Atoms'][r][cs+2] = color
     6476            drawAtoms.ClearSelection()
     6477            dlg.Destroy()
     6478            G2frame.dataFrame.SetStatusText('')
     6479            G2plt.PlotStructure(G2frame,data)
     6480           
     6481    def ResetAtomColors(event):
     6482        generalData = data['General']
     6483        atomData = data['Drawing']['Atoms']
     6484        cx,ct,cs,ci = data['Drawing']['atomPtrs']
     6485        for atom in atomData:           
     6486            atNum = generalData['AtomTypes'].index(atom[ct])
     6487            atom[cs+2] = list(generalData['Color'][atNum])
     6488        UpdateDrawAtoms()
     6489        drawAtoms.ClearSelection()
     6490        G2plt.PlotStructure(G2frame,data)       
     6491       
     6492    def SetViewPoint(event):
     6493        indx = drawAtoms.GetSelectedRows()
     6494        if indx:
     6495            atomData = data['Drawing']['Atoms']
     6496            cx = data['Drawing']['atomPtrs'][0]
     6497            data['Drawing']['viewPoint'] = [atomData[indx[0]][cx:cx+3],[indx[0],0]]
     6498            drawAtoms.ClearSelection()                                  #do I really want to do this?
     6499            G2plt.PlotStructure(G2frame,data)
     6500           
     6501    def noDuplicate(xyz,atomData):                  #be careful where this is used - it's slow
     6502        cx = data['Drawing']['atomPtrs'][0]
     6503        if True in [np.allclose(np.array(xyz),np.array(atom[cx:cx+3]),atol=0.0002) for atom in atomData]:
     6504            return False
     6505        else:
     6506            return True
     6507               
     6508    def AddSymEquiv(event):
     6509        indx = drawAtoms.GetSelectedRows()
     6510        indx.sort()
     6511        if indx:
     6512            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
     6513            cx = colLabels.index('x')
     6514            cuia = colLabels.index('I/A')
     6515            cuij = cuia+2
     6516            atomData = data['Drawing']['Atoms']
     6517            generalData = data['General']
     6518            SGData = generalData['SGData']
     6519            dlg = SymOpDialog(G2frame,SGData,False,True)
     6520            try:
     6521                if dlg.ShowModal() == wx.ID_OK:
     6522                    Inv,Cent,Opr,Cell,New,Force = dlg.GetSelection()
     6523                    Cell = np.array(Cell)
     6524                    cent = SGData['SGCen'][Cent]
     6525                    M,T = SGData['SGOps'][Opr]
     6526                    for ind in indx:
     6527                        XYZ = np.array(atomData[ind][cx:cx+3])
     6528                        XYZ = np.inner(M,XYZ)+T
     6529                        if Inv:
     6530                            XYZ = -XYZ
     6531                        XYZ = XYZ+cent+Cell
     6532                        if Force:
     6533                            XYZ = G2spc.MoveToUnitCell(XYZ)
     6534                        if noDuplicate(XYZ,atomData):
     6535                            atom = copy.copy(atomData[ind])
     6536                            atom[cx:cx+3] = XYZ
     6537                            atomOp = atom[cx+3]
     6538                            newOp = str(((Opr+1)+100*Cent)*(1-2*Inv))+'+'+ \
     6539                                str(int(Cell[0]))+','+str(int(Cell[1]))+','+str(int(Cell[2]))                           
     6540                            atom[cx+3] = G2spc.StringOpsProd(atomOp,newOp,SGData)
     6541                            if atom[cuia] == 'A':
     6542                                Uij = atom[cuij:cuij+6]
     6543                                U = G2spc.Uij2U(Uij)
     6544                                U = np.inner(np.inner(M,U),M)
     6545                                Uij = G2spc.U2Uij(U)
     6546                                atom[cuij:cuij+6] = Uij
     6547                            atomData.append(atom)
     6548            finally:
     6549                dlg.Destroy()
     6550            UpdateDrawAtoms()
     6551            drawAtoms.ClearSelection()
     6552            G2plt.PlotStructure(G2frame,data)
     6553           
     6554    def TransformSymEquiv(event):
     6555        indx = drawAtoms.GetSelectedRows()
     6556        indx.sort()
     6557        if indx:
     6558            atomData = data['Drawing']['Atoms']
     6559            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
     6560            cx = colLabels.index('x')
     6561            cuia = colLabels.index('I/A')
     6562            cuij = cuia+2
     6563            atomData = data['Drawing']['Atoms']
     6564            generalData = data['General']
     6565            SGData = generalData['SGData']
     6566            dlg = SymOpDialog(G2frame,SGData,False,True)
     6567            try:
     6568                if dlg.ShowModal() == wx.ID_OK:
     6569                    Inv,Cent,Opr,Cell,New,Force = dlg.GetSelection()
     6570                    Cell = np.array(Cell)
     6571                    cent = SGData['SGCen'][Cent]
     6572                    M,T = SGData['SGOps'][Opr]
     6573                    for ind in indx:
     6574                        XYZ = np.array(atomData[ind][cx:cx+3])
     6575                        XYZ = np.inner(M,XYZ)+T
     6576                        if Inv:
     6577                            XYZ = -XYZ
     6578                        XYZ = XYZ+cent+Cell
     6579                        if Force:
     6580                            XYZ = G2spc.MoveToUnitCell(XYZ)
     6581                        atom = atomData[ind]
     6582                        atom[cx:cx+3] = XYZ
     6583                        atomOp = atom[cx+3]
     6584                        newOp = str(((Opr+1)+100*Cent)*(1-2*Inv))+'+'+ \
     6585                            str(int(Cell[0]))+','+str(int(Cell[1]))+','+str(int(Cell[2]))
     6586                        atom[cx+3] = G2spc.StringOpsProd(atomOp,newOp,SGData)
     6587                        if atom[cuia] == 'A':
     6588                            Uij = atom[cuij:cuij+6]
     6589                            U = G2spc.Uij2U(Uij)
     6590                            U = np.inner(np.inner(M,U),M)
     6591                            Uij = G2spc.U2Uij(U)
     6592                            atom[cuij:cuij+6] = Uij
     6593                    data['Drawing']['Atoms'] = atomData
     6594            finally:
     6595                dlg.Destroy()
     6596            UpdateDrawAtoms()
     6597            drawAtoms.ClearSelection()
     6598            G2plt.PlotStructure(G2frame,data)
     6599           
     6600    def FillCoordSphere(event):
     6601        generalData = data['General']
     6602        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
     6603        radii = generalData['BondRadii']
     6604        atomTypes = generalData['AtomTypes']
     6605        try:
     6606            indH = atomTypes.index('H')
     6607            radii[indH] = 0.5
     6608        except:
     6609            pass           
     6610        indx = drawAtoms.GetSelectedRows()
     6611        if indx:
     6612            indx.sort()
     6613            atomData = data['Drawing']['Atoms']
     6614            numAtoms = len(atomData)
     6615            cx,ct,cs,ci = data['Drawing']['atomPtrs']
     6616            generalData = data['General']
     6617            SGData = generalData['SGData']
     6618            cellArray = G2lat.CellBlock(1)
     6619            wx.BeginBusyCursor()
     6620            try:
     6621                for ind in indx:
     6622                    atomA = atomData[ind]
     6623                    xyzA = np.array(atomA[cx:cx+3])
     6624                    indA = atomTypes.index(atomA[ct])
     6625                    for atomB in atomData[:numAtoms]:
     6626                        indB = atomTypes.index(atomB[ct])
     6627                        sumR = radii[indA]+radii[indB]
     6628                        xyzB = np.array(atomB[cx:cx+3])
     6629                        for xyz in cellArray+xyzB:
     6630                            dist = np.sqrt(np.sum(np.inner(Amat,xyz-xyzA)**2))
     6631                            if 0 < dist <= data['Drawing']['radiusFactor']*sumR:
     6632                                if noDuplicate(xyz,atomData):
     6633                                    oprB = atomB[cx+3]
     6634                                    C = xyz-xyzB
     6635                                    newOp = '1+'+str(int(round(C[0])))+','+str(int(round(C[1])))+','+str(int(round(C[2])))
     6636                                    newAtom = atomB[:]
     6637                                    newAtom[cx:cx+3] = xyz
     6638                                    newAtom[cx+3] = G2spc.StringOpsProd(oprB,newOp,SGData)
     6639                                    atomData.append(newAtom)
     6640            finally:
     6641                wx.EndBusyCursor()
     6642            data['Drawing']['Atoms'] = atomData
     6643            UpdateDrawAtoms()
     6644            drawAtoms.ClearSelection()
     6645            G2plt.PlotStructure(G2frame,data)
     6646           
     6647    def FillUnitCell(event):
     6648        indx = drawAtoms.GetSelectedRows()
     6649        indx.sort()
     6650        if indx:
     6651            atomData = data['Drawing']['Atoms']
     6652            colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
     6653            cx = colLabels.index('x')
     6654            cuia = colLabels.index('I/A')
     6655            cuij = cuia+2
     6656            generalData = data['General']
     6657            SGData = generalData['SGData']
     6658            wx.BeginBusyCursor()
     6659            try:
     6660                for ind in indx:
     6661                    atom = atomData[ind]
     6662                    XYZ = np.array(atom[cx:cx+3])
     6663                    if atom[cuia] == 'A':
     6664                        Uij = atom[cuij:cuij+6]
     6665                        result = G2spc.GenAtom(XYZ,SGData,False,Uij,False)
     6666                        for item in result:
     6667                            atom = copy.copy(atomData[ind])
     6668                            atom[cx:cx+3] = item[0]
     6669                            atom[cx+3] = str(item[2])+'+' \
     6670                                +str(item[3][0])+','+str(item[3][1])+','+str(item[3][2])
     6671                            atom[cuij:cuij+6] = item[1]
     6672                            Opp = G2spc.Opposite(item[0])
     6673                            for xyz in Opp:
     6674                                if noDuplicate(xyz,atomData):
     6675                                    cell = np.asarray(np.rint(xyz-atom[cx:cx+3]),dtype=np.int32)
     6676                                    cell = '1'+'+'+ \
     6677                                        str(cell[0])+','+str(cell[1])+','+str(cell[2])
     6678                                    atom[cx:cx+3] = xyz
     6679                                    atom[cx+3] = G2spc.StringOpsProd(cell,atom[cx+3],SGData)
     6680                                    atomData.append(atom[:])
     6681                    else:
     6682                        result = G2spc.GenAtom(XYZ,SGData,False,Move=False)
     6683                        for item in result:
     6684                            atom = copy.copy(atomData[ind])
     6685                            atom[cx:cx+3] = item[0]
     6686                            atom[cx+3] = str(item[1])+'+' \
     6687                                +str(item[2][0])+','+str(item[2][1])+','+str(item[2][2])
     6688                            Opp = G2spc.Opposite(item[0])
     6689                            for xyz in Opp:
     6690                                if noDuplicate(xyz,atomData):
     6691                                    cell = np.asarray(np.rint(xyz-atom[cx:cx+3]),dtype=np.int32)
     6692                                    cell = '1'+'+'+ \
     6693                                        str(cell[0])+','+str(cell[1])+','+str(cell[2])
     6694                                    atom[cx:cx+3] = xyz
     6695                                    atom[cx+3] = G2spc.StringOpsProd(cell,atom[cx+3],SGData)
     6696                                    atomData.append(atom[:])               
     6697                    data['Drawing']['Atoms'] = atomData
     6698            finally:
     6699                wx.EndBusyCursor()
     6700            UpdateDrawAtoms()
     6701            drawAtoms.ClearSelection()
     6702            G2plt.PlotStructure(G2frame,data)
     6703           
     6704    def FindBondsToo():                         #works but slow for large structures - keep as reference
     6705        cx,ct,cs,ci = data['Drawing']['atomPtrs']
     6706        atomData = data['Drawing']['Atoms']
     6707        generalData = data['General']
     6708        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
     6709        radii = generalData['BondRadii']
     6710        atomTypes = generalData['AtomTypes']
     6711        try:
     6712            indH = atomTypes.index('H')
     6713            radii[indH] = 0.5
     6714        except:
     6715            pass           
     6716        for atom in atomData:
     6717            atom[-1] = []
     6718        Atoms = []
     6719        for i,atom in enumerate(atomData):
     6720            Atoms.append([i,np.array(atom[cx:cx+3]),atom[cs],radii[atomTypes.index(atom[ct])]])
     6721        for atomA in Atoms:
     6722            if atomA[2] in ['lines','sticks','ellipsoids','balls & sticks','polyhedra']:
     6723                for atomB in Atoms:                   
     6724                    Dx = atomB[1]-atomA[1]
     6725                    DX = np.inner(Amat,Dx)
     6726                    dist = np.sqrt(np.sum(DX**2))
     6727                    sumR = atomA[3]+atomB[3]
     6728                    if 0.5 < dist <= 0.85*sumR:
     6729                        i = atomA[0]
     6730                        if atomA[2] == 'polyhedra':
     6731                            atomData[i][-1].append(DX)
     6732                        elif atomB[1] != 'polyhedra':
     6733                            j = atomB[0]
     6734                            atomData[i][-1].append(Dx*atomA[3]/sumR)
     6735                            atomData[j][-1].append(-Dx*atomB[3]/sumR)
     6736                   
     6737    def FindBondsDraw():                    #uses numpy & masks - very fast even for proteins!
     6738        import numpy.ma as ma
     6739        cx,ct,cs,ci = data['Drawing']['atomPtrs']
     6740        hydro = data['Drawing']['showHydrogen']
     6741        atomData = data['Drawing']['Atoms']
     6742        generalData = data['General']
     6743        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
     6744        radii = generalData['BondRadii']
     6745        atomTypes = generalData['AtomTypes']
     6746        try:
     6747            indH = atomTypes.index('H')
     6748            radii[indH] = 0.5
     6749        except:
     6750            pass           
     6751        for atom in atomData:
     6752            atom[-2] = []               #clear out old bonds/polyhedra
     6753            atom[-1] = []
     6754        Indx = range(len(atomData))
     6755        Atoms = []
     6756        Styles = []
     6757        Radii = []
     6758        for atom in atomData:
     6759            Atoms.append(np.array(atom[cx:cx+3]))
     6760            Styles.append(atom[cs])
     6761            try:
     6762                if not hydro and atom[ct] == 'H':
     6763                    Radii.append(0.0)
     6764                else:
     6765                    Radii.append(radii[atomTypes.index(atom[ct])])
     6766            except ValueError:          #changed atom type!
     6767                Radii.append(0.20)
     6768        Atoms = np.array(Atoms)
     6769        Radii = np.array(Radii)
     6770        IASR = zip(Indx,Atoms,Styles,Radii)
     6771        for atomA in IASR:
     6772            if atomA[2] in ['lines','sticks','ellipsoids','balls & sticks','polyhedra']:
     6773                Dx = Atoms-atomA[1]
     6774                dist = ma.masked_less(np.sqrt(np.sum(np.inner(Amat,Dx)**2,axis=0)),0.5) #gets rid of G2frame & disorder "bonds" < 0.5A
     6775                sumR = atomA[3]+Radii
     6776                IndB = ma.nonzero(ma.masked_greater(dist-data['Drawing']['radiusFactor']*sumR,0.))                 #get indices of bonded atoms
     6777                i = atomA[0]
     6778                for j in IndB[0]:
     6779                    if Styles[i] == 'polyhedra':
     6780                        atomData[i][-2].append(np.inner(Amat,Dx[j]))
     6781                    elif Styles[j] != 'polyhedra' and j > i:
     6782                        atomData[i][-2].append(Dx[j]*Radii[i]/sumR[j])
     6783                        atomData[j][-2].append(-Dx[j]*Radii[j]/sumR[j])
     6784                if Styles[i] == 'polyhedra':
     6785                    Bonds = atomData[i][-2]
     6786                    Faces = []
     6787                    if len(Bonds) > 2:
     6788                        FaceGen = G2lat.uniqueCombinations(Bonds,3)     #N.B. this is a generator
     6789                        for face in FaceGen:
     6790                            vol = nl.det(face)
     6791                            if abs(vol) > 1. or len(Bonds) == 3:
     6792                                if vol < 0.:
     6793                                    face = [face[0],face[2],face[1]]
     6794                                face = np.array(face)
     6795                                if not np.array([np.array(nl.det(face-bond))+0.0001 < 0 for bond in Bonds]).any():
     6796                                    norm = np.cross(face[1]-face[0],face[2]-face[0])
     6797                                    norm /= np.sqrt(np.sum(norm**2))
     6798                                    Faces.append([face,norm])
     6799                        atomData[i][-1] = Faces
     6800                       
     6801    def DrawAtomsDelete(event):   
     6802        indx = drawAtoms.GetSelectedRows()
     6803        indx.sort()
     6804        if indx:
     6805            atomData = data['Drawing']['Atoms']
     6806            indx.reverse()
     6807            for ind in indx:
     6808                del atomData[ind]
     6809            UpdateDrawAtoms()
     6810            drawAtoms.ClearSelection()
     6811            G2plt.PlotStructure(G2frame,data)
     6812        event.StopPropagation()
     6813       
     6814    def OnReloadDrawAtoms(event):
     6815        data['Drawing']['Atoms'] = []
     6816        UpdateDrawAtoms()
     6817        drawAtoms.ClearSelection()
     6818        G2plt.PlotStructure(G2frame,data)
     6819        event.StopPropagation()
     6820       
     6821    def FindAtomIndexByIDs(atomData,IDs,Draw=True):
     6822        indx = []
     6823        for i,atom in enumerate(atomData):
     6824            if Draw and atom[-3] in IDs:
     6825                indx.append(i)
     6826            elif atom[-1] in IDs:
     6827                indx.append(i)
     6828        return indx
     6829       
     6830    def DrawAtomsDeleteByIDs(IDs):
     6831        atomData = data['Drawing']['Atoms']
     6832        indx = FindAtomIndexByIDs(atomData,IDs)
     6833        indx.reverse()
     6834        for ind in indx:
     6835            del atomData[ind]
     6836           
     6837    def ChangeDrawAtomsByIDs(colName,IDs,value):
     6838        atomData = data['Drawing']['Atoms']
     6839        cx,ct,cs,ci = data['Drawing']['atomPtrs']
     6840        if colName == 'Name':
     6841            col = ct-1
     6842        elif colName == 'Type':
     6843            col = ct
     6844        elif colName == 'I/A':
     6845            col = cs
     6846        indx = FindAtomIndexByIDs(atomData,IDs)
     6847        for ind in indx:
     6848            atomData[ind][col] = value
     6849               
     6850    def OnDrawPlane(event):
     6851        indx = drawAtoms.GetSelectedRows()
     6852        if len(indx) < 4:
     6853            print '**** ERROR - need 4+ atoms for plane calculation'
     6854            return
     6855        PlaneData = {}
     6856        drawingData = data['Drawing']
     6857        atomData = drawingData['Atoms']
     6858        colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
     6859        cx = colLabels.index('x')
     6860        cn = colLabels.index('Name')
     6861        xyz = []
     6862        for i,atom in enumerate(atomData):
     6863            if i in indx:
     6864                xyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+3])
     6865        generalData = data['General']
     6866        PlaneData['Name'] = generalData['Name']
     6867        PlaneData['Atoms'] = xyz
     6868        PlaneData['Cell'] = generalData['Cell'][1:] #+ volume
     6869        G2str.BestPlane(PlaneData)
     6870       
     6871    def OnDrawDistVP(event):
     6872        # distance to view point
     6873        indx = drawAtoms.GetSelectedRows()
     6874        if not indx:
     6875            print '***** ERROR - no atoms selected'
     6876            return
     6877        generalData = data['General']
     6878        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
     6879        drawingData = data['Drawing']
     6880        viewPt = np.array(drawingData['viewPoint'][0])
     6881        print ' Distance from view point at %.3f %.3f %.3f to:'%(viewPt[0],viewPt[1],viewPt[2])
     6882        atomDData = drawingData['Atoms']
     6883        colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
     6884        cx = colLabels.index('x')
     6885        cn = colLabels.index('Name')
     6886        for i in indx:
     6887            atom = atomDData[i]
     6888            Dx = np.array(atom[cx:cx+3])-viewPt
     6889            dist = np.sqrt(np.sum(np.inner(Amat,Dx)**2,axis=0))
     6890            print 'Atom: %8s (%12s) distance = %.3f'%(atom[cn],atom[cx+3],dist)
     6891   
     6892    def OnDrawDAT(event):
     6893        #distance, angle, torsion
     6894        indx = drawAtoms.GetSelectedRows()
     6895        if len(indx) not in [2,3,4]:
     6896            print '**** ERROR - wrong number of atoms for distance, angle or torsion calculation'
     6897            return
     6898        DATData = {}
     6899        ocx,oct,ocs,cia = data['General']['AtomPtrs']
     6900        drawingData = data['Drawing']
     6901        atomData = data['Atoms']
     6902        atomDData = drawingData['Atoms']
     6903        colLabels = [drawAtoms.GetColLabelValue(c) for c in range(drawAtoms.GetNumberCols())]
     6904        cx = colLabels.index('x')
     6905        cn = colLabels.index('Name')
     6906        cid = colLabels.index('I/A')+8
     6907        xyz = []
     6908        Oxyz = []
     6909        DATData['Natoms'] = len(indx)
     6910        for i in indx:
     6911            atom = atomDData[i]
     6912            xyz.append([i,]+atom[cn:cn+2]+atom[cx:cx+4]) #also gets Sym Op
     6913            id = FindAtomIndexByIDs(atomData,[atom[cid],],False)[0]
     6914            Oxyz.append([id,]+atomData[id][cx+1:cx+4])
     6915        DATData['Datoms'] = xyz
     6916        DATData['Oatoms'] = Oxyz
     6917        generalData = data['General']
     6918        DATData['Name'] = generalData['Name']
     6919        DATData['SGData'] = generalData['SGData']
     6920        DATData['Cell'] = generalData['Cell'][1:] #+ volume
     6921        if 'pId' in data:
     6922            DATData['pId'] = data['pId']
     6923            DATData['covData'] = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,G2frame.root, 'Covariance'))
     6924        G2str.DisAglTor(DATData)
     6925               
     6926################################################################################
     6927#### Draw Options page
     6928################################################################################
     6929
     6930    def UpdateDrawOptions():
     6931        import copy
     6932        import wx.lib.colourselect as wcs
     6933        generalData = data['General']
     6934        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
     6935        SetupDrawingData()
     6936        drawingData = data['Drawing']
     6937        if generalData['Type'] == 'nuclear':
     6938            pickChoice = ['Atoms','Bonds','Torsions','Planes']
     6939        elif generalData['Type'] == 'macromolecular':
     6940            pickChoice = ['Atoms','Residues','Chains','Bonds','Torsions','Planes','phi/psi']
     6941
     6942        def SlopSizer():
     6943           
     6944            def OnCameraPos(event):
     6945                drawingData['cameraPos'] = cameraPos.GetValue()
     6946                cameraPosTxt.SetLabel(' Camera Distance: '+'%.2f'%(drawingData['cameraPos']))
     6947                ZclipTxt.SetLabel(' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
     6948                G2plt.PlotStructure(G2frame,data)
     6949
     6950            def OnZclip(event):
     6951                drawingData['Zclip'] = Zclip.GetValue()
     6952                ZclipTxt.SetLabel(' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
     6953                G2plt.PlotStructure(G2frame,data)
     6954               
     6955            def OnZstep(event):
     6956                try:
     6957                    step = float(Zstep.GetValue())
     6958                    if not (0.01 <= step <= 1.0):
     6959                        raise ValueError
     6960                except ValueError:
     6961                    step = drawingData['Zstep']
     6962                drawingData['Zstep'] = step
     6963                Zstep.SetValue('%.2fA'%(drawingData['Zstep']))
     6964               
     6965            def OnMoveZ(event):
     6966                move = MoveZ.GetValue()*drawingData['Zstep']
     6967                MoveZ.SetValue(0)
     6968                VP = np.inner(Amat,np.array(drawingData['viewPoint'][0]))
     6969                VD = np.inner(Amat,np.array(drawingData['viewDir']))
     6970                VD /= np.sqrt(np.sum(VD**2))
     6971                VP += move*VD
     6972                VP = np.inner(Bmat,VP)
     6973                drawingData['viewPoint'][0] = VP
     6974                panel = dataDisplay.GetChildren()
     6975                names = [child.GetName() for child in panel]
     6976                panel[names.index('viewPoint')].SetValue('%.3f %.3f %.3f'%(VP[0],VP[1],VP[2]))               
     6977                G2plt.PlotStructure(G2frame,data)
     6978               
     6979            def OnVdWScale(event):
     6980                drawingData['vdwScale'] = vdwScale.GetValue()/100.
     6981                vdwScaleTxt.SetLabel(' van der Waals scale: '+'%.2f'%(drawingData['vdwScale']))
     6982                G2plt.PlotStructure(G2frame,data)
     6983   
     6984            def OnEllipseProb(event):
     6985                drawingData['ellipseProb'] = ellipseProb.GetValue()
     6986                ellipseProbTxt.SetLabel(' Ellipsoid probability: '+'%d%%'%(drawingData['ellipseProb']))
     6987                G2plt.PlotStructure(G2frame,data)
     6988   
     6989            def OnBallScale(event):
     6990                drawingData['ballScale'] = ballScale.GetValue()/100.
     6991                ballScaleTxt.SetLabel(' Ball scale: '+'%.2f'%(drawingData['ballScale']))
     6992                G2plt.PlotStructure(G2frame,data)
     6993
     6994            def OnBondRadius(event):
     6995                drawingData['bondRadius'] = bondRadius.GetValue()/100.
     6996                bondRadiusTxt.SetLabel(' Bond radius, A: '+'%.2f'%(drawingData['bondRadius']))
     6997                G2plt.PlotStructure(G2frame,data)
     6998               
     6999            def OnContourLevel(event):
     7000                drawingData['contourLevel'] = contourLevel.GetValue()/100.
     7001                contourLevelTxt.SetLabel(' Contour level: '+'%.2f'%(drawingData['contourLevel']*generalData['Map']['rhoMax']))
     7002                G2plt.PlotStructure(G2frame,data)
     7003
     7004            def OnMapSize(event):
     7005                drawingData['mapSize'] = mapSize.GetValue()/10.
     7006                mapSizeTxt.SetLabel(' Map radius, A: '+'%.1f'%(drawingData['mapSize']))
     7007                G2plt.PlotStructure(G2frame,data)
     7008
     7009           
     7010            slopSizer = wx.BoxSizer(wx.HORIZONTAL)
     7011            slideSizer = wx.FlexGridSizer(7,2)
     7012            slideSizer.AddGrowableCol(1,1)
     7013   
     7014            cameraPosTxt = wx.StaticText(dataDisplay,-1,
     7015                ' Camera Distance: '+'%.2f'%(drawingData['cameraPos']),name='cameraPos')
     7016            slideSizer.Add(cameraPosTxt,0,wx.ALIGN_CENTER_VERTICAL)
     7017            cameraPos = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['cameraPos'],name='cameraSlider')
     7018            cameraPos.SetRange(10,500)
     7019            cameraPos.Bind(wx.EVT_SLIDER, OnCameraPos)
     7020            slideSizer.Add(cameraPos,1,wx.EXPAND|wx.RIGHT)
     7021           
     7022            ZclipTxt = wx.StaticText(dataDisplay,-1,' Z clipping: '+'%.2fA'%(drawingData['Zclip']*drawingData['cameraPos']/100.))
     7023            slideSizer.Add(ZclipTxt,0,wx.ALIGN_CENTER_VERTICAL)
     7024            Zclip = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['Zclip'])
     7025            Zclip.SetRange(1,99)
     7026            Zclip.Bind(wx.EVT_SLIDER, OnZclip)
     7027            slideSizer.Add(Zclip,1,wx.EXPAND|wx.RIGHT)
     7028           
     7029            ZstepSizer = wx.BoxSizer(wx.HORIZONTAL)
     7030            ZstepSizer.Add(wx.StaticText(dataDisplay,-1,' Z step:'),0,wx.ALIGN_CENTER_VERTICAL)
     7031            Zstep = wx.TextCtrl(dataDisplay,value='%.2f'%(drawingData['Zstep']),
     7032                style=wx.TE_PROCESS_ENTER)
     7033            Zstep.Bind(wx.EVT_TEXT_ENTER,OnZstep)
     7034            Zstep.Bind(wx.EVT_KILL_FOCUS,OnZstep)
     7035            ZstepSizer.Add(Zstep,0,wx.ALIGN_CENTER_VERTICAL)
     7036            slideSizer.Add(ZstepSizer)
     7037            MoveSizer = wx.BoxSizer(wx.HORIZONTAL)
     7038            MoveSizer.Add(wx.StaticText(dataDisplay,-1,'   Press to step:'),0,wx.ALIGN_CENTER_VERTICAL)
     7039            MoveZ = wx.SpinButton(dataDisplay,style=wx.SP_HORIZONTAL,size=wx.Size(100,20))
     7040            MoveZ.SetValue(0)
     7041            MoveZ.SetRange(-1,1)
     7042            MoveZ.Bind(wx.EVT_SPIN, OnMoveZ)
     7043            MoveSizer.Add(MoveZ)
     7044            slideSizer.Add(MoveSizer,1,wx.EXPAND|wx.RIGHT)
     7045           
     7046            vdwScaleTxt = wx.StaticText(dataDisplay,-1,' van der Waals scale: '+'%.2f'%(drawingData['vdwScale']))
     7047            slideSizer.Add(vdwScaleTxt,0,wx.ALIGN_CENTER_VERTICAL)
     7048            vdwScale = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['vdwScale']))
     7049            vdwScale.Bind(wx.EVT_SLIDER, OnVdWScale)
     7050            slideSizer.Add(vdwScale,1,wx.EXPAND|wx.RIGHT)
     7051   
     7052            ellipseProbTxt = wx.StaticText(dataDisplay,-1,' Ellipsoid probability: '+'%d%%'%(drawingData['ellipseProb']))
     7053            slideSizer.Add(ellipseProbTxt,0,wx.ALIGN_CENTER_VERTICAL)
     7054            ellipseProb = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=drawingData['ellipseProb'])
     7055            ellipseProb.SetRange(1,99)
     7056            ellipseProb.Bind(wx.EVT_SLIDER, OnEllipseProb)
     7057            slideSizer.Add(ellipseProb,1,wx.EXPAND|wx.RIGHT)
     7058   
     7059            ballScaleTxt = wx.StaticText(dataDisplay,-1,' Ball scale: '+'%.2f'%(drawingData['ballScale']))
     7060            slideSizer.Add(ballScaleTxt,0,wx.ALIGN_CENTER_VERTICAL)
     7061            ballScale = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['ballScale']))
     7062            ballScale.Bind(wx.EVT_SLIDER, OnBallScale)
     7063            slideSizer.Add(ballScale,1,wx.EXPAND|wx.RIGHT)
     7064   
     7065            bondRadiusTxt = wx.StaticText(dataDisplay,-1,' Bond radius, A: '+'%.2f'%(drawingData['bondRadius']))
     7066            slideSizer.Add(bondRadiusTxt,0,wx.ALIGN_CENTER_VERTICAL)
     7067            bondRadius = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['bondRadius']))
     7068            bondRadius.SetRange(1,25)
     7069            bondRadius.Bind(wx.EVT_SLIDER, OnBondRadius)
     7070            slideSizer.Add(bondRadius,1,wx.EXPAND|wx.RIGHT)
     7071           
     7072            if generalData['Map']['rhoMax']:
     7073                contourLevelTxt = wx.StaticText(dataDisplay,-1,' Contour level: '+'%.2f'%(drawingData['contourLevel']*generalData['Map']['rhoMax']))
     7074                slideSizer.Add(contourLevelTxt,0,wx.ALIGN_CENTER_VERTICAL)
     7075                contourLevel = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(100*drawingData['contourLevel']))
     7076                contourLevel.SetRange(1,100)
     7077                contourLevel.Bind(wx.EVT_SLIDER, OnContourLevel)
     7078                slideSizer.Add(contourLevel,1,wx.EXPAND|wx.RIGHT)
     7079                mapSizeTxt = wx.StaticText(dataDisplay,-1,' Map radius, A: '+'%.1f'%(drawingData['mapSize']))
     7080                slideSizer.Add(mapSizeTxt,0,wx.ALIGN_CENTER_VERTICAL)
     7081                mapSize = wx.Slider(dataDisplay,style=wx.SL_HORIZONTAL,value=int(10*drawingData['mapSize']))
     7082                mapSize.SetRange(1,100)
     7083                mapSize.Bind(wx.EVT_SLIDER, OnMapSize)
     7084                slideSizer.Add(mapSize,1,wx.EXPAND|wx.RIGHT)
     7085           
     7086            slopSizer.Add(slideSizer,1,wx.EXPAND|wx.RIGHT)
     7087            slopSizer.Add((10,5),0)
     7088            slopSizer.SetMinSize(wx.Size(350,10))
     7089            return slopSizer
     7090           
     7091        def ShowSizer():
     7092           
     7093            def OnBackColor(event):
     7094                drawingData['backColor'] = event.GetValue()
     7095                G2plt.PlotStructure(G2frame,data)
     7096   
     7097            def OnShowABC(event):
     7098                drawingData['showABC'] = showABC.GetValue()
     7099                G2plt.PlotStructure(G2frame,data)
     7100   
     7101            def OnShowUnitCell(event):
     7102                drawingData['unitCellBox'] = unitCellBox.GetValue()
     7103                G2plt.PlotStructure(G2frame,data)
     7104   
     7105            def OnShowHyd(event):
     7106                drawingData['showHydrogen'] = showHydrogen.GetValue()
     7107                FindBondsDraw()
     7108                G2plt.PlotStructure(G2frame,data)
     7109               
     7110            def OnViewPoint(event):
     7111                Obj = event.GetEventObject()
     7112                viewPt = Obj.GetValue().split()
     7113                try:
     7114                    VP = [float(viewPt[i]) for i in range(3)]
     7115                except (ValueError,IndexError):
     7116                    VP = drawingData['viewPoint'][0]
     7117                Obj.SetValue('%.3f %.3f %.3f'%(VP[0],VP[1],VP[2]))
     7118                drawingData['viewPoint'][0] = VP
     7119                G2plt.PlotStructure(G2frame,data)
     7120               
     7121            def OnViewDir(event):
     7122                Obj = event.GetEventObject()
     7123                viewDir = Obj.GetValue().split()
     7124                try:
     7125                    Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
     7126                    VD = np.array([float(viewDir[i]) for i in range(3)])
     7127                    VC = np.inner(Amat,VD)
     7128                    VC /= np.sqrt(np.sum(VC**2))
     7129                    V = np.array(drawingData['viewDir'])
     7130                    VB = np.inner(Amat,V)
     7131                    VB /= np.sqrt(np.sum(VB**2))
     7132                    VX = np.cross(VC,VB)
     7133                    A = acosd(max((2.-np.sum((VB-VC)**2))/2.,-1.))
     7134                    QV = G2mth.AVdeg2Q(A,VX)
     7135                    Q = drawingData['Quaternion']
     7136                    drawingData['Quaternion'] = G2mth.prodQQ(Q,QV)
     7137                except (ValueError,IndexError):
     7138                    VD = drawingData['viewDir']
     7139                Obj.SetValue('%.3f %.3f %.3f'%(VD[0],VD[1],VD[2]))
     7140                drawingData['viewDir'] = VD
     7141                G2plt.PlotStructure(G2frame,data)
     7142                               
     7143            showSizer = wx.BoxSizer(wx.VERTICAL)           
     7144            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
     7145            lineSizer.Add(wx.StaticText(dataDisplay,-1,' Background color:'),0,wx.ALIGN_CENTER_VERTICAL)
     7146            backColor = wcs.ColourSelect(dataDisplay, -1,colour=drawingData['backColor'],size=wx.Size(25,25))
     7147            backColor.Bind(wcs.EVT_COLOURSELECT, OnBackColor)
     7148            lineSizer.Add(backColor,0,wx.ALIGN_CENTER_VERTICAL)
     7149            lineSizer.Add(wx.StaticText(dataDisplay,-1,' View Dir.:'),0,wx.ALIGN_CENTER_VERTICAL)
     7150            VD = drawingData['viewDir']
     7151            viewDir = wx.TextCtrl(dataDisplay,value='%.3f %.3f %.3f'%(VD[0],VD[1],VD[2]),
     7152                style=wx.TE_PROCESS_ENTER,size=wx.Size(140,20),name='viewDir')
     7153            viewDir.Bind(wx.EVT_TEXT_ENTER,OnViewDir)
     7154            viewDir.Bind(wx.EVT_KILL_FOCUS,OnViewDir)
     7155            lineSizer.Add(viewDir,0,wx.ALIGN_CENTER_VERTICAL)
     7156            showSizer.Add(lineSizer)
     7157            showSizer.Add((0,5),0)
     7158           
     7159            lineSizer = wx.BoxSizer(wx.HORIZONTAL)
     7160            showABC = wx.CheckBox(dataDisplay,-1,label=' Show view point?')
     7161            showABC.Bind(wx.EVT_CHECKBOX, OnShowABC)
     7162            showABC.SetValue(drawingData['showABC'])
     7163            lineSizer.Add(showABC,0,wx.ALIGN_CENTER_VERTICAL)
     7164            lineSizer.Add(wx.StaticText(dataDisplay,-1,' View Point:'),0,wx.ALIGN_CENTER_VERTICAL)
     7165            VP = drawingData['viewPoint'][0]
     7166            viewPoint = wx.TextCtrl(dataDisplay,value='%.3f %.3f %.3f'%(VP[0],VP[1],VP[2]),
     7167                style=wx.TE_PROCESS_ENTER,size=wx.Size(140,20),name='viewPoint')
     7168            viewPoint.Bind(wx.EVT_TEXT_ENTER,OnViewPoint)
     7169            viewPoint.Bind(wx.EVT_KILL_FOCUS,OnViewPoint)
     7170            lineSizer.Add(viewPoint,0,wx.ALIGN_CENTER_VERTICAL)
     7171            showSizer.Add(lineSizer)
     7172            showSizer.Add((0,5),0)
     7173           
     7174            line2Sizer = wx.BoxSizer(wx.HORIZONTAL)
     7175   
     7176            unitCellBox = wx.CheckBox(dataDisplay,-1,label=' Show unit cell?')
     7177            unitCellBox.Bind(wx.EVT_CHECKBOX, OnShowUnitCell)
     7178            unitCellBox.SetValue(drawingData['unitCellBox'])
     7179            line2Sizer.Add(unitCellBox,0,wx.ALIGN_CENTER_VERTICAL)
     7180   
     7181            showHydrogen = wx.CheckBox(dataDisplay,-1,label=' Show hydrogens?')
     7182            showHydrogen.Bind(wx.EVT_CHECKBOX, OnShowHyd)
     7183            showHydrogen.SetValue(drawingData['showHydrogen'])
     7184            line2Sizer.Add(showHydrogen,0,wx.ALIGN_CENTER_VERTICAL)
     7185            showSizer.Add(line2Sizer)
     7186            return showSizer
     7187           
     7188        def RadSizer():
     7189           
     7190            def OnSizeHatoms(event):
     7191                try:
     7192                    value = max(0.1,min(1.2,float(sizeH.GetValue())))
     7193                except ValueError:
     7194                    value = 0.5
     7195                drawingData['sizeH'] = value
     7196                sizeH.SetValue("%.2f"%(value))
     7197                G2plt.PlotStructure(G2frame,data)
     7198               
     7199            def OnRadFactor(event):
     7200                try:
     7201                    value = max(0.1,min(1.2,float(radFactor.GetValue())))
     7202                except ValueError:
     7203                    value = 0.85
     7204                drawingData['radiusFactor'] = value
     7205                radFactor.SetValue("%.2f"%(value))
     7206                FindBondsDraw()
     7207                G2plt.PlotStructure(G2frame,data)
     7208           
     7209            radSizer = wx.BoxSizer(wx.HORIZONTAL)
     7210            radSizer.Add(wx.StaticText(dataDisplay,-1,' Hydrogen radius, A:  '),0,wx.ALIGN_CENTER_VERTICAL)
     7211            sizeH = wx.TextCtrl(dataDisplay,-1,value='%.2f'%(drawingData['sizeH']),size=wx.Size(60,20),style=wx.TE_PROCESS_ENTER)
     7212            sizeH.Bind(wx.EVT_TEXT_ENTER,OnSizeHatoms)
     7213            sizeH.Bind(wx.EVT_KILL_FOCUS,OnSizeHatoms)
     7214            radSizer.Add(sizeH,0,wx.ALIGN_CENTER_VERTICAL)
     7215   
     7216            radSizer.Add(wx.StaticText(dataDisplay,-1,' Bond search factor:  '),0,wx.ALIGN_CENTER_VERTICAL)
     7217            radFactor = wx.TextCtrl(dataDisplay,value='%.2f'%(drawingData['radiusFactor']),size=wx.Size(60,20),style=wx.TE_PROCESS_ENTER)
     7218            radFactor.Bind(wx.EVT_TEXT_ENTER,OnRadFactor)
     7219            radFactor.Bind(wx.EVT_KILL_FOCUS,OnRadFactor)
     7220            radSizer.Add(radFactor,0,wx.ALIGN_CENTER_VERTICAL)
     7221            return radSizer
     7222
     7223        G2frame.dataFrame.SetStatusText('')
     7224        drawOptions.DestroyChildren()
     7225        dataDisplay = wx.Panel(drawOptions)
     7226        mainSizer = wx.BoxSizer(wx.VERTICAL)
     7227        mainSizer.Add((5,5),0)
     7228        mainSizer.Add(wx.StaticText(dataDisplay,-1,' Drawing controls:'),0,wx.ALIGN_CENTER_VERTICAL)
     7229        mainSizer.Add((5,5),0)       
     7230        mainSizer.Add(SlopSizer(),0)
     7231        mainSizer.Add((5,5),0)
     7232        mainSizer.Add(ShowSizer(),0,)
     7233        mainSizer.Add((5,5),0)
     7234        mainSizer.Add(RadSizer(),0,)
     7235
     7236        dataDisplay.SetSizer(mainSizer)
     7237        Size = mainSizer.Fit(G2frame.dataFrame)
     7238        Size[1] += 35                           #compensate for status bar
     7239        dataDisplay.SetSize(Size)
     7240        G2frame.dataFrame.setSizePosLeft(Size)
     7241
     7242################################################################################
     7243####  Texture routines
     7244################################################################################
     7245       
     7246    def UpdateTexture():
     7247        G2frame.dataFrame.SetStatusText('')
     7248        generalData = data['General']       
     7249        SGData = generalData['SGData']
     7250        try:
     7251            textureData = generalData['SH Texture']
     7252        except KeyError:            #fix old files!
     7253            textureData = generalData['SH Texture'] = {'Order':0,'Model':'cylindrical',
     7254                'Sample omega':[False,0.0],'Sample chi':[False,0.0],'Sample phi':[False,0.0],
     7255                'SH Coeff':[False,{}],'SHShow':False,'PFhkl':[0,0,1],
     7256                'PFxyz':[0,0,1.],'PlotType':'Pole figure'}
     7257        if 'SHShow' not in textureData:     #another fix
     7258            textureData.update({'SHShow':False,'PFhkl':[0,0,1],'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
     7259        try:                        #another fix!
     7260            x = textureData['PlotType']
     7261        except KeyError:
     7262            textureData.update({'PFxyz':[0,0,1.],'PlotType':'Pole figure'})
     7263        shModels = ['cylindrical','none','shear - 2/m','rolling - mmm']
     7264        SamSym = dict(zip(shModels,['0','-1','2/m','mmm']))
     7265        if generalData['doPawley'] and G2gd.GetPatternTreeItemId(G2frame,G2frame.root,'Sequental results'):
     7266            G2frame.dataFrame.RefineTexture.Enable(True)
     7267        shAngles = ['omega','chi','phi']
     7268       
     7269        def SetSHCoef():
     7270            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],SamSym[textureData['Model']],textureData['Order'])
     7271            newSHCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
     7272            SHCoeff = textureData['SH Coeff'][1]
     7273            for cofName in SHCoeff:
     7274                if cofName in  cofNames:
     7275                    newSHCoef[cofName] = SHCoeff[cofName]
     7276            return newSHCoef
     7277       
     7278        def OnShOrder(event):
     7279            Obj = event.GetEventObject()
     7280            textureData['Order'] = int(Obj.GetValue())
     7281            textureData['SH Coeff'][1] = SetSHCoef()
     7282            wx.CallAfter(UpdateTexture)
     7283            G2plt.PlotTexture(G2frame,data)
     7284                       
     7285        def OnShModel(event):
     7286            Obj = event.GetEventObject()
     7287            textureData['Model'] = Obj.GetValue()
     7288            textureData['SH Coeff'][1] = SetSHCoef()
     7289            wx.CallAfter(UpdateTexture)
     7290            G2plt.PlotTexture(G2frame,data)
     7291           
     7292        def OnSHRefine(event):
     7293            Obj = event.GetEventObject()
     7294            textureData['SH Coeff'][0] = Obj.GetValue()
     7295           
     7296        def OnSHShow(event):
     7297            Obj = event.GetEventObject()
     7298            textureData['SHShow'] = Obj.GetValue()
     7299            wx.CallAfter(UpdateTexture)
     7300           
     7301        def OnProjSel(event):
     7302            Obj = event.GetEventObject()
     7303            G2frame.Projection = Obj.GetValue()
     7304            G2plt.PlotTexture(G2frame,data)
     7305           
     7306        def OnColorSel(event):
     7307            Obj = event.GetEventObject()
     7308            G2frame.ContourColor = Obj.GetValue()
     7309            G2plt.PlotTexture(G2frame,data)
     7310           
     7311        def OnAngRef(event):
     7312            Obj = event.GetEventObject()
     7313            textureData[angIndx[Obj.GetId()]][0] = Obj.GetValue()
     7314           
     7315        def OnAngValue(event):
     7316            Obj = event.GetEventObject()
     7317            try:
     7318                value =  float(Obj.GetValue())
     7319            except ValueError:
     7320                value = textureData[valIndx[Obj.GetId()]][1]
     7321            Obj.SetValue('%8.2f'%(value))
     7322            textureData[valIndx[Obj.GetId()]][1] = value
     7323           
     7324        def OnODFValue(event):
     7325            Obj = event.GetEventObject()
     7326            try:
     7327                value =  float(Obj.GetValue())
     7328            except ValueError:
     7329                value = textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]]
     7330            Obj.SetValue('%8.3f'%(value))
     7331            textureData['SH Coeff'][1][ODFIndx[Obj.GetId()]] = value
     7332            G2plt.PlotTexture(G2frame,data)
     7333           
     7334        def OnPfType(event):
     7335            Obj = event.GetEventObject()
     7336            textureData['PlotType'] = Obj.GetValue()
     7337            wx.CallAfter(UpdateTexture)
     7338            G2plt.PlotTexture(G2frame,data)
     7339           
     7340        def OnPFValue(event):
     7341            Obj = event.GetEventObject()
     7342            Saxis = Obj.GetValue().split()
     7343            if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:               
     7344                try:
     7345                    hkl = [int(Saxis[i]) for i in range(3)]
     7346                except (ValueError,IndexError):
     7347                    hkl = textureData['PFhkl']
     7348                if not np.any(np.array(hkl)):       #can't be all zeros!
     7349                    hkl = textureData['PFhkl']
     7350                Obj.SetValue('%d %d %d'%(hkl[0],hkl[1],hkl[2]))
     7351                textureData['PFhkl'] = hkl
     7352            else:
     7353                try:
     7354                    xyz = [float(Saxis[i]) for i in range(3)]
     7355                except (ValueError,IndexError):
     7356                    xyz = textureData['PFxyz']
     7357                if not np.any(np.array(xyz)):       #can't be all zeros!
     7358                    xyz = textureData['PFxyz']
     7359                Obj.SetValue('%3.1f %3.1f %3.1f'%(xyz[0],xyz[1],xyz[2]))
     7360                textureData['PFxyz'] = xyz
     7361            G2plt.PlotTexture(G2frame,data)
     7362
     7363        if Texture.GetSizer():
     7364            Texture.GetSizer().Clear(True)
     7365        mainSizer = wx.BoxSizer(wx.VERTICAL)
     7366        titleSizer = wx.BoxSizer(wx.HORIZONTAL)
     7367        titleSizer.Add(wx.StaticText(Texture,-1,'Spherical harmonics texture data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
     7368        titleSizer.Add(wx.StaticText(Texture,-1,
     7369            ' Texture Index J = %7.3f'%(G2lat.textureIndex(textureData['SH Coeff'][1]))),
     7370            0,wx.ALIGN_CENTER_VERTICAL)
     7371        mainSizer.Add(titleSizer,0)
     7372        mainSizer.Add((0,5),0)
     7373        shSizer = wx.FlexGridSizer(1,6,5,5)
     7374        shSizer.Add(wx.StaticText(Texture,-1,'Texture model: '),0,wx.ALIGN_CENTER_VERTICAL)
     7375        shModel = wx.ComboBox(Texture,-1,value=textureData['Model'],choices=shModels,
     7376            style=wx.CB_READONLY|wx.CB_DROPDOWN)
     7377        shModel.Bind(wx.EVT_COMBOBOX,OnShModel)
     7378        shSizer.Add(shModel,0,wx.ALIGN_CENTER_VERTICAL)
     7379        shSizer.Add(wx.StaticText(Texture,-1,'  Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
     7380        shOrder = wx.ComboBox(Texture,-1,value=str(textureData['Order']),choices=[str(2*i) for i in range(18)],
     7381            style=wx.CB_READONLY|wx.CB_DROPDOWN)
     7382        shOrder.Bind(wx.EVT_COMBOBOX,OnShOrder)
     7383        shSizer.Add(shOrder,0,wx.ALIGN_CENTER_VERTICAL)
     7384        shRef = wx.CheckBox(Texture,-1,label=' Refine texture?')
     7385        shRef.SetValue(textureData['SH Coeff'][0])
     7386        shRef.Bind(wx.EVT_CHECKBOX, OnSHRefine)
     7387        shSizer.Add(shRef,0,wx.ALIGN_CENTER_VERTICAL)
     7388        shShow = wx.CheckBox(Texture,-1,label=' Show coeff.?')
     7389        shShow.SetValue(textureData['SHShow'])
     7390        shShow.Bind(wx.EVT_CHECKBOX, OnSHShow)
     7391        shSizer.Add(shShow,0,wx.ALIGN_CENTER_VERTICAL)
     7392        mainSizer.Add(shSizer,0,0)
     7393        mainSizer.Add((0,5),0)
     7394        PTSizer = wx.FlexGridSizer(2,4,5,5)
     7395        PTSizer.Add(wx.StaticText(Texture,-1,' Texture plot type: '),0,wx.ALIGN_CENTER_VERTICAL)
     7396        choices = ['Axial pole distribution','Pole figure','Inverse pole figure']           
     7397        pfType = wx.ComboBox(Texture,-1,value=str(textureData['PlotType']),choices=choices,
     7398            style=wx.CB_READONLY|wx.CB_DROPDOWN)
     7399        pfType.Bind(wx.EVT_COMBOBOX,OnPfType)
     7400        PTSizer.Add(pfType,0,wx.ALIGN_CENTER_VERTICAL)
     7401        if 'Axial' not in textureData['PlotType']:
     7402            PTSizer.Add(wx.StaticText(Texture,-1,' Projection type: '),0,wx.ALIGN_CENTER_VERTICAL)
     7403            projSel = wx.ComboBox(Texture,-1,value=G2frame.Projection,choices=['equal area','stereographic','3D display'],
     7404                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     7405            projSel.Bind(wx.EVT_COMBOBOX,OnProjSel)
     7406            PTSizer.Add(projSel,0,wx.ALIGN_CENTER_VERTICAL)
     7407        if textureData['PlotType'] in ['Pole figure','Axial pole distribution']:
     7408            PTSizer.Add(wx.StaticText(Texture,-1,' Pole figure HKL: '),0,wx.ALIGN_CENTER_VERTICAL)
     7409            PH = textureData['PFhkl']
     7410            pfVal = wx.TextCtrl(Texture,-1,'%d %d %d'%(PH[0],PH[1],PH[2]),style=wx.TE_PROCESS_ENTER)
     7411        else:
     7412            PTSizer.Add(wx.StaticText(Texture,-1,' Inverse pole figure XYZ: '),0,wx.ALIGN_CENTER_VERTICAL)
     7413            PX = textureData['PFxyz']
     7414            pfVal = wx.TextCtrl(Texture,-1,'%3.1f %3.1f %3.1f'%(PX[0],PX[1],PX[2]),style=wx.TE_PROCESS_ENTER)
     7415        pfVal.Bind(wx.EVT_TEXT_ENTER,OnPFValue)
     7416        pfVal.Bind(wx.EVT_KILL_FOCUS,OnPFValue)
     7417        PTSizer.Add(pfVal,0,wx.ALIGN_CENTER_VERTICAL)
     7418        if 'Axial' not in textureData['PlotType']:
     7419            PTSizer.Add(wx.StaticText(Texture,-1,' Color scheme'),0,wx.ALIGN_CENTER_VERTICAL)
     7420            choice = [m for m in mpl.cm.datad.keys() if not m.endswith("_r")]
     7421            choice.sort()
     7422            colorSel = wx.ComboBox(Texture,-1,value=G2frame.ContourColor,choices=choice,
     7423                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     7424            colorSel.Bind(wx.EVT_COMBOBOX,OnColorSel)
     7425            PTSizer.Add(colorSel,0,wx.ALIGN_CENTER_VERTICAL)       
     7426        mainSizer.Add(PTSizer,0,wx.ALIGN_CENTER_VERTICAL)
     7427        mainSizer.Add((0,5),0)
     7428        if textureData['SHShow']:
     7429            mainSizer.Add(wx.StaticText(Texture,-1,'Spherical harmonic coefficients: '),0,wx.ALIGN_CENTER_VERTICAL)
     7430            mainSizer.Add((0,5),0)
     7431            ODFSizer = wx.FlexGridSizer(2,8,2,2)
     7432            ODFIndx = {}
     7433            ODFkeys = textureData['SH Coeff'][1].keys()
     7434            ODFkeys.sort()
     7435            for item in ODFkeys:
     7436                ODFSizer.Add(wx.StaticText(Texture,-1,item),0,wx.ALIGN_CENTER_VERTICAL)
     7437                ODFval = wx.TextCtrl(Texture,wx.ID_ANY,'%8.3f'%(textureData['SH Coeff'][1][item]),style=wx.TE_PROCESS_ENTER)
     7438                ODFIndx[ODFval.GetId()] = item
     7439                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
     7440                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
     7441                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
     7442            mainSizer.Add(ODFSizer,0,wx.ALIGN_CENTER_VERTICAL)
     7443            mainSizer.Add((0,5),0)
     7444        mainSizer.Add((0,5),0)
     7445        mainSizer.Add(wx.StaticText(Texture,-1,'Sample orientation angles: '),0,wx.ALIGN_CENTER_VERTICAL)
     7446        mainSizer.Add((0,5),0)
     7447        angSizer = wx.BoxSizer(wx.HORIZONTAL)
     7448        angIndx = {}
     7449        valIndx = {}
     7450        for item in ['Sample omega','Sample chi','Sample phi']:
     7451            angRef = wx.CheckBox(Texture,-1,label=item+': ')
     7452            angRef.SetValue(textureData[item][0])
     7453            angIndx[angRef.GetId()] = item
     7454            angRef.Bind(wx.EVT_CHECKBOX, OnAngRef)
     7455            angSizer.Add(angRef,0,wx.ALIGN_CENTER_VERTICAL)
     7456            angVal = wx.TextCtrl(Texture,wx.ID_ANY,'%8.2f'%(textureData[item][1]),style=wx.TE_PROCESS_ENTER)
     7457            valIndx[angVal.GetId()] = item
     7458            angVal.Bind(wx.EVT_TEXT_ENTER,OnAngValue)
     7459            angVal.Bind(wx.EVT_KILL_FOCUS,OnAngValue)
     7460            angSizer.Add(angVal,0,wx.ALIGN_CENTER_VERTICAL)
     7461            angSizer.Add((5,0),0)
     7462        mainSizer.Add(angSizer,0,wx.ALIGN_CENTER_VERTICAL)
     7463        Texture.SetSizer(mainSizer,True)
     7464        mainSizer.Fit(G2frame.dataFrame)
     7465        Size = mainSizer.GetMinSize()
     7466        Size[0] += 40
     7467        Size[1] = max(Size[1],250) + 35
     7468        Texture.SetSize(Size)
     7469        Texture.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
     7470        Size[1] = min(Size[1],450)
     7471        G2frame.dataFrame.setSizePosLeft(Size)
     7472
     7473################################################################################
     7474##### DData routines
     7475################################################################################
     7476       
     7477    def UpdateDData():
     7478        G2frame.dataFrame.SetStatusText('')
     7479        UseList = data['Histograms']
     7480        if UseList:
     7481            G2frame.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,True)
     7482            G2frame.Refine.Enable(True)
     7483        else:
     7484            G2frame.dataFrame.DataMenu.Enable(G2gd.wxID_DATADELETE,False)
     7485            G2frame.Refine.Enable(False)           
     7486        generalData = data['General']       
     7487        SGData = generalData['SGData']
     7488        keyList = UseList.keys()
     7489        keyList.sort()
     7490        PWDR = any(['PWDR' in item for item in keyList])
     7491        Indx = {}
     7492       
     7493        def PlotSizer():
     7494
     7495            def OnPlotSel(event):
     7496                Obj = event.GetEventObject()
     7497                generalData['Data plot type'] = Obj.GetStringSelection()
     7498                wx.CallAfter(UpdateDData)
     7499                G2plt.PlotSizeStrainPO(G2frame,data)
     7500               
     7501            def OnPOhkl(event):
     7502                Obj = event.GetEventObject()
     7503                Saxis = Obj.GetValue().split()
     7504                try:
     7505                    hkl = [int(Saxis[i]) for i in range(3)]
     7506                except (ValueError,IndexError):
     7507                    hkl = generalData['POhkl']
     7508                if not np.any(np.array(hkl)):
     7509                    hkl = generalData['POhkl']
     7510                generalData['POhkl'] = hkl
     7511                h,k,l = hkl
     7512                Obj.SetValue('%3d %3d %3d'%(h,k,l))
     7513                G2plt.PlotSizeStrainPO(G2frame,data)
     7514           
     7515            plotSizer = wx.BoxSizer(wx.VERTICAL)
     7516            choice = ['None','Mustrain','Size','Preferred orientation']
     7517            plotSel = wx.RadioBox(DData,-1,'Select plot type:',choices=choice,
     7518                majorDimension=2,style=wx.RA_SPECIFY_COLS)
     7519            plotSel.SetStringSelection(generalData['Data plot type'])
     7520            plotSel.Bind(wx.EVT_RADIOBOX,OnPlotSel)   
     7521            plotSizer.Add(plotSel)
     7522            if generalData['Data plot type'] == 'Preferred orientation':
     7523                POhklSizer = wx.BoxSizer(wx.HORIZONTAL)
     7524                POhklSizer.Add(wx.StaticText(DData,-1,' Plot preferred orientation for H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
     7525                h,k,l = generalData['POhkl']
     7526                poAxis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
     7527                poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOhkl)
     7528                poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOhkl)
     7529                POhklSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
     7530                plotSizer.Add(POhklSizer)           
     7531            return plotSizer
     7532           
     7533        def ScaleSizer():
     7534           
     7535            def OnScaleRef(event):
     7536                Obj = event.GetEventObject()
     7537                UseList[Indx[Obj.GetId()]]['Scale'][1] = Obj.GetValue()
     7538               
     7539            def OnScaleVal(event):
     7540                Obj = event.GetEventObject()
     7541                try:
     7542                    scale = float(Obj.GetValue())
     7543                    if scale > 0:
     7544                        UseList[Indx[Obj.GetId()]]['Scale'][0] = scale
     7545                except ValueError:
     7546                    pass
     7547                Obj.SetValue("%.4f"%(UseList[Indx[Obj.GetId()]]['Scale'][0]))          #reset in case of error
     7548                           
     7549            scaleSizer = wx.BoxSizer(wx.HORIZONTAL)
     7550            if 'PWDR' in item:
     7551                scaleRef = wx.CheckBox(DData,-1,label=' Phase fraction: ')
     7552            elif 'HKLF' in item:
     7553                scaleRef = wx.CheckBox(DData,-1,label=' Scale factor: ')               
     7554            scaleRef.SetValue(UseList[item]['Scale'][1])
     7555            Indx[scaleRef.GetId()] = item
     7556            scaleRef.Bind(wx.EVT_CHECKBOX, OnScaleRef)
     7557            scaleSizer.Add(scaleRef,0,wx.ALIGN_CENTER_VERTICAL)
     7558            scaleVal = wx.TextCtrl(DData,wx.ID_ANY,
     7559                '%.4f'%(UseList[item]['Scale'][0]),style=wx.TE_PROCESS_ENTER)
     7560            Indx[scaleVal.GetId()] = item
     7561            scaleVal.Bind(wx.EVT_TEXT_ENTER,OnScaleVal)
     7562            scaleVal.Bind(wx.EVT_KILL_FOCUS,OnScaleVal)
     7563            scaleSizer.Add(scaleVal,0,wx.ALIGN_CENTER_VERTICAL)
     7564            return scaleSizer
     7565           
     7566        def OnUseData(event):
     7567            Obj = event.GetEventObject()
     7568            hist = Indx[Obj.GetId()]
     7569            UseList[hist]['Use'] = Obj.GetValue()
     7570           
     7571        def OnShowData(event):
     7572            Obj = event.GetEventObject()
     7573            hist = Indx[Obj.GetId()]
     7574            UseList[hist]['Show'] = Obj.GetValue()
     7575            wx.CallAfter(UpdateDData)
     7576            G2plt.PlotSizeStrainPO(G2frame,data)
     7577           
     7578        def OnCopyData(event):
     7579            #how about HKLF data? This is only for PWDR data
     7580            Obj = event.GetEventObject()
     7581            hist = Indx[Obj.GetId()]
     7582            sourceDict = UseList[hist]
     7583            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
     7584            copyDict = {}
     7585            for name in copyNames:
     7586                copyDict[name] = copy.deepcopy(sourceDict[name])        #force copy
     7587            keyList = ['All',]+UseList.keys()
     7588            if UseList:
     7589                copyList = []
     7590                dlg = wx.MultiChoiceDialog(G2frame,
     7591                    'Copy parameters to which histograms?', 'Copy parameters',
     7592                    keyList, wx.CHOICEDLG_STYLE)
     7593                try:
     7594                    if dlg.ShowModal() == wx.ID_OK:
     7595                        result = dlg.GetSelections()
     7596                        for i in result:
     7597                            copyList.append(keyList[i])
     7598                        if 'All' in copyList:
     7599                            copyList = keyList[1:]
     7600                        for item in copyList:
     7601                            UseList[item].update(copy.deepcopy(copyDict))
     7602                        wx.CallAfter(UpdateDData)
     7603                finally:
     7604                    dlg.Destroy()
     7605                   
     7606        def OnCopyFlags(event):
     7607            Obj = event.GetEventObject()
     7608            hist = Indx[Obj.GetId()]
     7609            sourceDict = UseList[hist]
     7610            copyDict = {}
     7611            copyNames = ['Scale','Pref.Ori.','Size','Mustrain','HStrain','Extinction']
     7612            for name in copyNames:
     7613                if name in ['Scale','Extinction','HStrain']:
     7614                    copyDict[name] = sourceDict[name][1]
     7615                elif name in ['Size','Mustrain']:
     7616                    copyDict[name] = [sourceDict[name][0],sourceDict[name][2],sourceDict[name][4]]
     7617                elif name == 'Pref.Ori.':
     7618                    copyDict[name] = [sourceDict[name][0],sourceDict[name][2]]
     7619                    if sourceDict[name][0] == 'SH':
     7620                        SHterms = sourceDict[name][5]
     7621                        SHflags = {}
     7622                        for item in SHterms:
     7623                            SHflags[item] = SHterms[item][1]
     7624                        copyDict[name].append(SHflags)                       
     7625            keyList = ['All',]+UseList.keys()
     7626            if UseList:
     7627                copyList = []
     7628                dlg = wx.MultiChoiceDialog(G2frame,
     7629                    'Copy parameters to which histograms?', 'Copy parameters',
     7630                    keyList, wx.CHOICEDLG_STYLE)
     7631                try:
     7632                    if dlg.ShowModal() == wx.ID_OK:
     7633                        result = dlg.GetSelections()
     7634                        for i in result:
     7635                            copyList.append(keyList[i])
     7636                        if 'All' in copyList:
     7637                            copyList = keyList[1:]
     7638                        for item in copyList:
     7639                            UseList[item]                           
     7640                            for name in copyNames:
     7641                                if name in ['Scale','Extinction','HStrain']:
     7642                                    UseList[item][name][1] = copy.copy(copyDict[name])
     7643                                elif name in ['Size','Mustrain']:
     7644                                    UseList[item][name][0] = copy.copy(copyDict[name][0])
     7645                                    UseList[item][name][2] = copy.copy(copyDict[name][1])
     7646                                    UseList[item][name][4] = copy.copy(copyDict[name][2])
     7647                                elif name == 'Pref.Ori.':
     7648                                    UseList[item][name][0] = copy.copy(copyDict[name][0])
     7649                                    UseList[item][name][2] = copy.copy(copyDict[name][1])
     7650                                    if sourceDict[name][0] == 'SH':
     7651                                        SHflags = copy.copy(copyDict[name][2])
     7652                                        SHterms = copy.copy(sourceDict[name][5])
     7653                                        for item in SHflags:
     7654                                            SHterms[item][1] = copy.copy(SHflags[item])                                             
     7655                        wx.CallAfter(UpdateDData)
     7656                finally:
     7657                    dlg.Destroy()
     7658           
     7659           
     7660        def OnLGmixRef(event):
     7661            Obj = event.GetEventObject()
     7662            hist,name = Indx[Obj.GetId()]
     7663            UseList[hist][name][2][2] = Obj.GetValue()
     7664           
     7665        def OnLGmixVal(event):
     7666            Obj = event.GetEventObject()
     7667            hist,name = Indx[Obj.GetId()]
     7668            try:
     7669                value = float(Obj.GetValue())
     7670                if 0.1 <= value <= 1:
     7671                    UseList[hist][name][1][2] = value
     7672                else:
     7673                    raise ValueError
     7674            except ValueError:
     7675                pass
     7676            Obj.SetValue("%.4f"%(UseList[hist][name][1][2]))          #reset in case of error
     7677
     7678        def OnSizeType(event):
     7679            Obj = event.GetEventObject()
     7680            hist = Indx[Obj.GetId()]
     7681            UseList[hist]['Size'][0] = Obj.GetValue()
     7682            G2plt.PlotSizeStrainPO(G2frame,data)
     7683            wx.CallAfter(UpdateDData)
     7684           
     7685        def OnSizeRef(event):
     7686            Obj = event.GetEventObject()
     7687            hist,pid = Indx[Obj.GetId()]
     7688            if UseList[hist]['Size'][0] == 'ellipsoidal':
     7689                UseList[hist]['Size'][5][pid] = Obj.GetValue()               
     7690            else:
     7691                UseList[hist]['Size'][2][pid] = Obj.GetValue()
     7692           
     7693        def OnSizeVal(event):
     7694            Obj = event.GetEventObject()
     7695            hist,pid = Indx[Obj.GetId()]
     7696            if UseList[hist]['Size'][0] == 'ellipsoidal':
     7697                try:
     7698                    size = float(Obj.GetValue())
     7699                    if pid < 3 and size <= 0.001:            #10A lower limit!
     7700                        raise ValueError
     7701                    UseList[hist]['Size'][4][pid] = size                   
     7702                except ValueError:
     7703                    pass
     7704                Obj.SetValue("%.3f"%(UseList[hist]['Size'][4][pid]))          #reset in case of error
     7705            else:
     7706                try:
     7707                    size = float(Obj.GetValue())
     7708                    if size <= 0.001:            #10A lower limit!
     7709                        raise ValueError
     7710                    UseList[hist]['Size'][1][pid] = size
     7711                except ValueError:
     7712                    pass
     7713                Obj.SetValue("%.3f"%(UseList[hist]['Size'][1][pid]))          #reset in case of error
     7714            G2plt.PlotSizeStrainPO(G2frame,data)
     7715           
     7716        def OnSizeAxis(event):           
     7717            Obj = event.GetEventObject()
     7718            hist = Indx[Obj.GetId()]
     7719            Saxis = Obj.GetValue().split()
     7720            try:
     7721                hkl = [int(Saxis[i]) for i in range(3)]
     7722            except (ValueError,IndexError):
     7723                hkl = UseList[hist]['Size'][3]
     7724            if not np.any(np.array(hkl)):
     7725                hkl = UseList[hist]['Size'][3]
     7726            UseList[hist]['Size'][3] = hkl
     7727            h,k,l = hkl
     7728            Obj.SetValue('%3d %3d %3d'%(h,k,l))
     7729                       
     7730        def OnStrainType(event):
     7731            Obj = event.GetEventObject()
     7732            hist = Indx[Obj.GetId()]
     7733            UseList[hist]['Mustrain'][0] = Obj.GetValue()
     7734            wx.CallAfter(UpdateDData)
     7735            G2plt.PlotSizeStrainPO(G2frame,data)
     7736           
     7737        def OnStrainRef(event):
     7738            Obj = event.GetEventObject()
     7739            hist,pid = Indx[Obj.GetId()]
     7740            if UseList[hist]['Mustrain'][0] == 'generalized':
     7741                UseList[hist]['Mustrain'][5][pid] = Obj.GetValue()
     7742            else:
     7743                UseList[hist]['Mustrain'][2][pid] = Obj.GetValue()
     7744           
     7745        def OnStrainVal(event):
     7746            Snames = G2spc.MustrainNames(SGData)
     7747            Obj = event.GetEventObject()
     7748            hist,pid = Indx[Obj.GetId()]
     7749            try:
     7750                strain = float(Obj.GetValue())
     7751                if UseList[hist]['Mustrain'][0] == 'generalized':
     7752                    if '4' in Snames[pid] and strain < 0:
     7753                        raise ValueError
     7754                    UseList[hist]['Mustrain'][4][pid] = strain
     7755                else:
     7756                    if strain <= 0:
     7757                        raise ValueError
     7758                    UseList[hist]['Mustrain'][1][pid] = strain
     7759            except ValueError:
     7760                pass
     7761            if UseList[hist]['Mustrain'][0] == 'generalized':
     7762                Obj.SetValue("%.3f"%(UseList[hist]['Mustrain'][4][pid]))          #reset in case of error
     7763            else:
     7764                Obj.SetValue("%.1f"%(UseList[hist]['Mustrain'][1][pid]))          #reset in case of error
     7765            G2plt.PlotSizeStrainPO(G2frame,data)
     7766           
     7767        def OnStrainAxis(event):
     7768            Obj = event.GetEventObject()
     7769            hist = Indx[Obj.GetId()]
     7770            Saxis = Obj.GetValue().split()
     7771            try:
     7772                hkl = [int(Saxis[i]) for i in range(3)]
     7773            except (ValueError,IndexError):
     7774                hkl = UseList[hist]['Mustrain'][3]
     7775            if not np.any(np.array(hkl)):
     7776                hkl = UseList[hist]['Mustrain'][3]
     7777            UseList[hist]['Mustrain'][3] = hkl
     7778            h,k,l = hkl
     7779            Obj.SetValue('%3d %3d %3d'%(h,k,l))
     7780            G2plt.PlotSizeStrainPO(G2frame,data)
     7781           
     7782        def OnHstrainRef(event):
     7783            Obj = event.GetEventObject()
     7784            hist,pid = Indx[Obj.GetId()]
     7785            UseList[hist]['HStrain'][1][pid] = Obj.GetValue()
     7786           
     7787        def OnHstrainVal(event):
     7788            Snames = G2spc.HStrainNames(SGData)
     7789            Obj = event.GetEventObject()
     7790            hist,pid = Indx[Obj.GetId()]
     7791            try:
     7792                strain = float(Obj.GetValue())
     7793                UseList[hist]['HStrain'][0][pid] = strain
     7794            except ValueError:
     7795                pass
     7796            Obj.SetValue("%.5f"%(UseList[hist]['HStrain'][0][pid]))          #reset in case of error
     7797
     7798        def OnPOVal(event):
     7799            Obj = event.GetEventObject()
     7800            hist = Indx[Obj.GetId()]
     7801            try:
     7802                mdVal = float(Obj.GetValue())
     7803                if mdVal > 0:
     7804                    UseList[hist]['Pref.Ori.'][1] = mdVal
     7805            except ValueError:
     7806                pass
     7807            Obj.SetValue("%.3f"%(UseList[hist]['Pref.Ori.'][1]))          #reset in case of error
     7808           
     7809        def OnPOAxis(event):
     7810            Obj = event.GetEventObject()
     7811            hist = Indx[Obj.GetId()]
     7812            Saxis = Obj.GetValue().split()
     7813            try:
     7814                hkl = [int(Saxis[i]) for i in range(3)]
     7815            except (ValueError,IndexError):
     7816                hkl = UseList[hist]['Pref.Ori.'][3]
     7817            if not np.any(np.array(hkl)):
     7818                hkl = UseList[hist]['Pref.Ori.'][3]
     7819            UseList[hist]['Pref.Ori.'][3] = hkl
     7820            h,k,l = hkl
     7821            Obj.SetValue('%3d %3d %3d'%(h,k,l))
     7822           
     7823        def OnPOOrder(event):
     7824            Obj = event.GetEventObject()
     7825            hist = Indx[Obj.GetId()]
     7826            Order = int(Obj.GetValue())
     7827            UseList[hist]['Pref.Ori.'][4] = Order
     7828            UseList[hist]['Pref.Ori.'][5] = SetPOCoef(Order,hist)
     7829            wx.CallAfter(UpdateDData)
     7830
     7831        def OnPOType(event):
     7832            Obj = event.GetEventObject()
     7833            hist = Indx[Obj.GetId()]
     7834            if 'March' in Obj.GetValue():
     7835                UseList[hist]['Pref.Ori.'][0] = 'MD'
     7836            else:
     7837                UseList[hist]['Pref.Ori.'][0] = 'SH'
     7838            wx.CallAfter(UpdateDData)           
     7839   
     7840        def OnPORef(event):
     7841            Obj = event.GetEventObject()
     7842            hist = Indx[Obj.GetId()]
     7843            UseList[hist]['Pref.Ori.'][2] = Obj.GetValue()
     7844               
     7845        def SetPOCoef(Order,hist):
     7846            cofNames = G2lat.GenSHCoeff(SGData['SGLaue'],'0',Order,False)     #cylindrical & no M
     7847            newPOCoef = dict(zip(cofNames,np.zeros(len(cofNames))))
     7848            POCoeff = UseList[hist]['Pref.Ori.'][5]
     7849            for cofName in POCoeff:
     7850                if cofName in  cofNames:
     7851                    newPOCoef[cofName] = POCoeff[cofName]
     7852            return newPOCoef
     7853       
     7854        def OnExtRef(event):
     7855            Obj = event.GetEventObject()
     7856            UseList[Indx[Obj.GetId()]]['Extinction'][1] = Obj.GetValue()
     7857           
     7858        def OnExtVal(event):
     7859            Obj = event.GetEventObject()
     7860            try:
     7861                ext = float(Obj.GetValue())
     7862                if ext >= 0:
     7863                    UseList[Indx[Obj.GetId()]]['Extinction'][0] = ext
     7864            except ValueError:
     7865                pass
     7866            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][0]))
     7867           
     7868        def OnTbarVal(event):
     7869            Obj = event.GetEventObject()
     7870            try:
     7871                tbar = float(Obj.GetValue())
     7872                if tbar >= 0:
     7873                    UseList[Indx[Obj.GetId()]]['Extinction'][2]['Tbar'] = tbar
     7874            except ValueError:
     7875                pass
     7876            Obj.SetValue("%.2f"%(UseList[Indx[Obj.GetId()]]['Extinction'][2]['Tbar']))
     7877           
     7878        def OnEval(event):
     7879            Obj = event.GetEventObject()
     7880            item = Indx[Obj.GetId()]
     7881            try:
     7882                val = float(Obj.GetValue())
     7883                if val >= 0:
     7884                    UseList[item[0]]['Extinction'][2][item[1]][0] = val
     7885            except ValueError:
     7886                pass
     7887            Obj.SetValue("%9.3g"%(UseList[item[0]]['Extinction'][2][item[1]][0]))
     7888           
     7889        def OnEref(event):
     7890            Obj = event.GetEventObject()
     7891            item = Indx[Obj.GetId()]
     7892            UseList[item[0]]['Extinction'][2][item[1]][1] = Obj.GetValue()
     7893
     7894        def OnSCExtType(event):
     7895            Obj = event.GetEventObject()
     7896            item = Indx[Obj.GetId()]
     7897            UseList[item[0]]['Extinction'][item[1]] = Obj.GetValue()
     7898            wx.CallAfter(UpdateDData)
     7899               
     7900        def checkAxis(axis):
     7901            if not np.any(np.array(axis)):
     7902                return False
     7903            return axis
     7904           
     7905        def TopSizer(name,choices,parm,OnType):
     7906            topSizer = wx.BoxSizer(wx.HORIZONTAL)
     7907            topSizer.Add(wx.StaticText(DData,-1,name),0,wx.ALIGN_CENTER_VERTICAL)
     7908            sizeType = wx.ComboBox(DData,wx.ID_ANY,value=UseList[item][parm][0],choices=choices,
     7909                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     7910            sizeType.Bind(wx.EVT_COMBOBOX, OnType)
     7911            Indx[sizeType.GetId()] = item
     7912            topSizer.Add(sizeType)
     7913            topSizer.Add((5,0),0)
     7914            return topSizer
     7915           
     7916        def LGmixSizer(name,OnVal,OnRef):
     7917            lgmixSizer = wx.BoxSizer(wx.HORIZONTAL)
     7918            lgmixRef = wx.CheckBox(DData,-1,label='LGmix')
     7919            lgmixRef.thisown = False
     7920            lgmixRef.SetValue(UseList[item][name][2][2])
     7921            Indx[lgmixRef.GetId()] = [item,name]
     7922            lgmixRef.Bind(wx.EVT_CHECKBOX, OnRef)
     7923            lgmixSizer.Add(lgmixRef,0,wx.ALIGN_CENTER_VERTICAL)
     7924            lgmixVal = wx.TextCtrl(DData,wx.ID_ANY,
     7925                '%.4f'%(UseList[item][name][1][2]),style=wx.TE_PROCESS_ENTER)
     7926            Indx[lgmixVal.GetId()] = [item,name]
     7927            lgmixVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
     7928            lgmixVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
     7929            lgmixSizer.Add(lgmixVal,0,wx.ALIGN_CENTER_VERTICAL)
     7930            return lgmixSizer
     7931                       
     7932        def IsoSizer(name,parm,fmt,OnVal,OnRef):
     7933            isoSizer = wx.BoxSizer(wx.HORIZONTAL)
     7934            sizeRef = wx.CheckBox(DData,-1,label=name)
     7935            sizeRef.thisown = False
     7936            sizeRef.SetValue(UseList[item][parm][2][0])
     7937            Indx[sizeRef.GetId()] = [item,0]
     7938            sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
     7939            isoSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
     7940            sizeVal = wx.TextCtrl(DData,wx.ID_ANY,
     7941                fmt%(UseList[item][parm][1][0]),style=wx.TE_PROCESS_ENTER)
     7942            Indx[sizeVal.GetId()] = [item,0]
     7943            sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
     7944            sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
     7945            isoSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
     7946            return isoSizer
     7947           
     7948        def UniSizer(parm,OnAxis):
     7949            uniSizer = wx.BoxSizer(wx.HORIZONTAL)
     7950            uniSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
     7951            h,k,l = UseList[item][parm][3]
     7952            Axis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
     7953            Indx[Axis.GetId()] = item
     7954            Axis.Bind(wx.EVT_TEXT_ENTER,OnAxis)
     7955            Axis.Bind(wx.EVT_KILL_FOCUS,OnAxis)
     7956            uniSizer.Add(Axis,0,wx.ALIGN_CENTER_VERTICAL)
     7957            return uniSizer
     7958           
     7959        def UniDataSizer(parmName,parm,fmt,OnVal,OnRef):
     7960            dataSizer = wx.BoxSizer(wx.HORIZONTAL)
     7961            parms = zip([' Equatorial '+parmName,' Axial '+parmName],
     7962                UseList[item][parm][1],UseList[item][parm][2],range(2))
     7963            for Pa,val,ref,id in parms:
     7964                sizeRef = wx.CheckBox(DData,-1,label=Pa)
     7965                sizeRef.thisown = False
     7966                sizeRef.SetValue(ref)
     7967                Indx[sizeRef.GetId()] = [item,id]
     7968                sizeRef.Bind(wx.EVT_CHECKBOX, OnRef)
     7969                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
     7970                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,fmt%(val),style=wx.TE_PROCESS_ENTER)
     7971                Indx[sizeVal.GetId()] = [item,id]
     7972                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnVal)
     7973                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnVal)
     7974                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
     7975                dataSizer.Add((5,0),0)
     7976            return dataSizer
     7977           
     7978        def EllSizeDataSizer():
     7979            parms = zip(['S11','S22','S33','S12','S13','S23'],UseList[item]['Size'][4],
     7980                UseList[item]['Size'][5],range(6))
     7981            dataSizer = wx.FlexGridSizer(1,6,5,5)
     7982            for Pa,val,ref,id in parms:
     7983                sizeRef = wx.CheckBox(DData,-1,label=Pa)
     7984                sizeRef.thisown = False
     7985                sizeRef.SetValue(ref)
     7986                Indx[sizeRef.GetId()] = [item,id]
     7987                sizeRef.Bind(wx.EVT_CHECKBOX, OnSizeRef)
     7988                dataSizer.Add(sizeRef,0,wx.ALIGN_CENTER_VERTICAL)
     7989                sizeVal = wx.TextCtrl(DData,wx.ID_ANY,'%.3f'%(val),style=wx.TE_PROCESS_ENTER)
     7990                Indx[sizeVal.GetId()] = [item,id]
     7991                sizeVal.Bind(wx.EVT_TEXT_ENTER,OnSizeVal)
     7992                sizeVal.Bind(wx.EVT_KILL_FOCUS,OnSizeVal)
     7993                dataSizer.Add(sizeVal,0,wx.ALIGN_CENTER_VERTICAL)
     7994            return dataSizer
     7995           
     7996        def GenStrainDataSizer():
     7997            Snames = G2spc.MustrainNames(SGData)
     7998            numb = len(Snames)
     7999            if len(UseList[item]['Mustrain'][4]) < numb:
     8000                UseList[item]['Mustrain'][4] = numb*[0.0,]
     8001                UseList[item]['Mustrain'][5] = numb*[False,]
     8002            parms = zip(Snames,UseList[item]['Mustrain'][4],UseList[item]['Mustrain'][5],range(numb))
     8003            dataSizer = wx.FlexGridSizer(1,6,5,5)
     8004            for Pa,val,ref,id in parms:
     8005                strainRef = wx.CheckBox(DData,-1,label=Pa)
     8006                strainRef.thisown = False
     8007                strainRef.SetValue(ref)
     8008                Indx[strainRef.GetId()] = [item,id]
     8009                strainRef.Bind(wx.EVT_CHECKBOX, OnStrainRef)
     8010                dataSizer.Add(strainRef,0,wx.ALIGN_CENTER_VERTICAL)
     8011                strainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
     8012                Indx[strainVal.GetId()] = [item,id]
     8013                strainVal.Bind(wx.EVT_TEXT_ENTER,OnStrainVal)
     8014                strainVal.Bind(wx.EVT_KILL_FOCUS,OnStrainVal)
     8015                dataSizer.Add(strainVal,0,wx.ALIGN_CENTER_VERTICAL)
     8016            return dataSizer
     8017           
     8018        def HstrainSizer():
     8019            hstrainSizer = wx.FlexGridSizer(1,6,5,5)
     8020            Hsnames = G2spc.HStrainNames(SGData)
     8021            parms = zip(Hsnames,UseList[item]['HStrain'][0],UseList[item]['HStrain'][1],range(len(Hsnames)))
     8022            for Pa,val,ref,id in parms:
     8023                hstrainRef = wx.CheckBox(DData,-1,label=Pa)
     8024                hstrainRef.thisown = False
     8025                hstrainRef.SetValue(ref)
     8026                Indx[hstrainRef.GetId()] = [item,id]
     8027                hstrainRef.Bind(wx.EVT_CHECKBOX, OnHstrainRef)
     8028                hstrainSizer.Add(hstrainRef,0,wx.ALIGN_CENTER_VERTICAL)
     8029                hstrainVal = wx.TextCtrl(DData,wx.ID_ANY,'%.5f'%(val),style=wx.TE_PROCESS_ENTER)
     8030                Indx[hstrainVal.GetId()] = [item,id]
     8031                hstrainVal.Bind(wx.EVT_TEXT_ENTER,OnHstrainVal)
     8032                hstrainVal.Bind(wx.EVT_KILL_FOCUS,OnHstrainVal)
     8033                hstrainSizer.Add(hstrainVal,0,wx.ALIGN_CENTER_VERTICAL)
     8034            return hstrainSizer
     8035           
     8036        def PoTopSizer(POData):
     8037            poSizer = wx.FlexGridSizer(1,6,5,5)
     8038            choice = ['March-Dollase','Spherical harmonics']
     8039            POtype = choice[['MD','SH'].index(POData[0])]
     8040            poSizer.Add(wx.StaticText(DData,-1,' Preferred orientation model '),0,wx.ALIGN_CENTER_VERTICAL)
     8041            POType = wx.ComboBox(DData,wx.ID_ANY,value=POtype,choices=choice,
     8042                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     8043            Indx[POType.GetId()] = item
     8044            POType.Bind(wx.EVT_COMBOBOX, OnPOType)
     8045            poSizer.Add(POType)
     8046            if POData[0] == 'SH':
     8047                poSizer.Add(wx.StaticText(DData,-1,' Harmonic order: '),0,wx.ALIGN_CENTER_VERTICAL)
     8048                poOrder = wx.ComboBox(DData,wx.ID_ANY,value=str(POData[4]),choices=[str(2*i) for i in range(18)],
     8049                    style=wx.CB_READONLY|wx.CB_DROPDOWN)
     8050                Indx[poOrder.GetId()] = item
     8051                poOrder.Bind(wx.EVT_COMBOBOX,OnPOOrder)
     8052                poSizer.Add(poOrder,0,wx.ALIGN_CENTER_VERTICAL)
     8053                poRef = wx.CheckBox(DData,-1,label=' Refine? ')
     8054                poRef.SetValue(POData[2])
     8055                Indx[poRef.GetId()] = item
     8056                poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
     8057                poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
     8058            return poSizer
     8059           
     8060        def MDDataSizer(POData):
     8061            poSizer = wx.BoxSizer(wx.HORIZONTAL)
     8062            poRef = wx.CheckBox(DData,-1,label=' March-Dollase ratio: ')
     8063            poRef.SetValue(POData[2])
     8064            Indx[poRef.GetId()] = item
     8065            poRef.Bind(wx.EVT_CHECKBOX,OnPORef)
     8066            poSizer.Add(poRef,0,wx.ALIGN_CENTER_VERTICAL)
     8067            poVal = wx.TextCtrl(DData,wx.ID_ANY,
     8068                '%.3f'%(POData[1]),style=wx.TE_PROCESS_ENTER)
     8069            Indx[poVal.GetId()] = item
     8070            poVal.Bind(wx.EVT_TEXT_ENTER,OnPOVal)
     8071            poVal.Bind(wx.EVT_KILL_FOCUS,OnPOVal)
     8072            poSizer.Add(poVal,0,wx.ALIGN_CENTER_VERTICAL)
     8073            poSizer.Add(wx.StaticText(DData,-1,' Unique axis, H K L: '),0,wx.ALIGN_CENTER_VERTICAL)
     8074            h,k,l =POData[3]
     8075            poAxis = wx.TextCtrl(DData,-1,'%3d %3d %3d'%(h,k,l),style=wx.TE_PROCESS_ENTER)
     8076            Indx[poAxis.GetId()] = item
     8077            poAxis.Bind(wx.EVT_TEXT_ENTER,OnPOAxis)
     8078            poAxis.Bind(wx.EVT_KILL_FOCUS,OnPOAxis)
     8079            poSizer.Add(poAxis,0,wx.ALIGN_CENTER_VERTICAL)
     8080            return poSizer
     8081           
     8082        def SHDataSizer(POData):
     8083            textJ = G2lat.textureIndex(POData[5])
     8084            mainSizer.Add(wx.StaticText(DData,-1,' Spherical harmonic coefficients: '+'Texture index: %.3f'%(textJ)),0,wx.ALIGN_CENTER_VERTICAL)
     8085            mainSizer.Add((0,5),0)
     8086            ODFSizer = wx.FlexGridSizer(2,8,2,2)
     8087            ODFIndx = {}
     8088            ODFkeys = POData[5].keys()
     8089            ODFkeys.sort()
     8090            for odf in ODFkeys:
     8091                ODFSizer.Add(wx.StaticText(DData,-1,odf),0,wx.ALIGN_CENTER_VERTICAL)
     8092                ODFval = wx.TextCtrl(DData,wx.ID_ANY,'%8.3f'%(POData[5][odf]),style=wx.TE_PROCESS_ENTER)
     8093                ODFIndx[ODFval.GetId()] = odf
     8094#                ODFval.Bind(wx.EVT_TEXT_ENTER,OnODFValue)
     8095#                ODFval.Bind(wx.EVT_KILL_FOCUS,OnODFValue)
     8096                ODFSizer.Add(ODFval,0,wx.ALIGN_CENTER_VERTICAL)
     8097            return ODFSizer
     8098           
     8099        def ExtSizer():           
     8100            extSizer = wx.BoxSizer(wx.HORIZONTAL)
     8101            extRef = wx.CheckBox(DData,-1,label=' Extinction: ')
     8102            extRef.SetValue(UseList[item]['Extinction'][1])
     8103            Indx[extRef.GetId()] = item
     8104            extRef.Bind(wx.EVT_CHECKBOX, OnExtRef)
     8105            extSizer.Add(extRef,0,wx.ALIGN_CENTER_VERTICAL)
     8106            extVal = wx.TextCtrl(DData,wx.ID_ANY,
     8107                '%.2f'%(UseList[item]['Extinction'][0]),style=wx.TE_PROCESS_ENTER)
     8108            Indx[extVal.GetId()] = item
     8109            extVal.Bind(wx.EVT_TEXT_ENTER,OnExtVal)
     8110            extVal.Bind(wx.EVT_KILL_FOCUS,OnExtVal)
     8111            extSizer.Add(extVal,0,wx.ALIGN_CENTER_VERTICAL)
     8112            return extSizer
     8113       
     8114        def SCExtSizer():
     8115            extSizer = wx.BoxSizer(wx.VERTICAL)
     8116            typeSizer = wx.BoxSizer(wx.HORIZONTAL)           
     8117            typeSizer.Add(wx.StaticText(DData,-1,' Extinction type: '),0,wx.ALIGN_CENTER_VERTICAL)
     8118            Choices = ['Primary','Secondary Type I','Secondary Type II','Secondary Type I & II']
     8119            typeTxt = wx.ComboBox(DData,-1,choices=Choices,value=UseList[item]['Extinction'][1],
     8120                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     8121            Indx[typeTxt.GetId()] = [item,1]
     8122            typeTxt.Bind(wx.EVT_COMBOBOX,OnSCExtType)
     8123            typeSizer.Add(typeTxt)
     8124            typeSizer.Add(wx.StaticText(DData,-1,' Approx: '),0,wx.ALIGN_CENTER_VERTICAL)
     8125            Choices=['Lorentzian','Gaussian']
     8126            approxTxT = wx.ComboBox(DData,-1,choices=Choices,value=UseList[item]['Extinction'][0],
     8127                style=wx.CB_READONLY|wx.CB_DROPDOWN)
     8128            Indx[approxTxT.GetId()] = [item,0]
     8129            approxTxT.Bind(wx.EVT_COMBOBOX,OnSCExtType)
     8130            typeSizer.Add(approxTxT)
     8131            extSizer.Add(typeSizer,0,wx.ALIGN_CENTER_VERTICAL)
     8132            extSizer.Add((0,5),)
     8133            valSizer =wx.BoxSizer(wx.HORIZONTAL)
     8134            valSizer.Add(wx.StaticText(DData,-1,' Tbar(mm):'),0,wx.ALIGN_CENTER_VERTICAL)
     8135            tbarVal = wx.TextCtrl(DData,wx.ID_ANY,
     8136                '%.3f'%(UseList[item]['Extinction'][2]['Tbar']),style=wx.TE_PROCESS_ENTER)
     8137            Indx[tbarVal.GetId()] = item
     8138            tbarVal.Bind(wx.EVT_TEXT_ENTER,OnTbarVal)
     8139            tbarVal.Bind(wx.EVT_KILL_FOCUS,OnTbarVal)
     8140            valSizer.Add(tbarVal,0,wx.ALIGN_CENTER_VERTICAL)
     8141            if 'Primary' in UseList[item]['Extinction'][1]:
     8142                Ekey = ['Ep',]
     8143            elif 'Secondary Type II' == UseList[item]['Extinction'][1]:
     8144                Ekey = ['Es',]
     8145            elif 'Secondary Type I' == UseList[item]['Extinction'][1]:
     8146                Ekey = ['Eg',]
     8147            else:
     8148                Ekey = ['Eg','Es']
     8149            for ekey in Ekey:
     8150                Eref = wx.CheckBox(DData,-1,label=ekey+' : ')
     8151                Eref.SetValue(UseList[item]['Extinction'][2][ekey][1])
     8152                Indx[Eref.GetId()] = [item,ekey]
     8153                Eref.Bind(wx.EVT_CHECKBOX, OnEref)
     8154                valSizer.Add(Eref,0,wx.ALIGN_CENTER_VERTICAL)
     8155                Eval = wx.TextCtrl(DData,wx.ID_ANY,
     8156                    '%9.3g'%(UseList[item]['Extinction'][2][ekey][0]),style=wx.TE_PROCESS_ENTER)
     8157                Indx[Eval.GetId()] = [item,ekey]
     8158                Eval.Bind(wx.EVT_TEXT_ENTER,OnEval)
     8159                Eval.Bind(wx.EVT_KILL_FOCUS,OnEval)
     8160                valSizer.Add(Eval,0,wx.ALIGN_CENTER_VERTICAL)
     8161
     8162            extSizer.Add(valSizer,0,wx.ALIGN_CENTER_VERTICAL)
     8163            return extSizer
     8164           
     8165        if DData.GetSizer():
     8166            DData.GetSizer().Clear(True)
     8167        mainSizer = wx.BoxSizer(wx.VERTICAL)
     8168        mainSizer.Add(wx.StaticText(DData,-1,'Histogram data for '+PhaseName+':'),0,wx.ALIGN_CENTER_VERTICAL)
     8169        if PWDR:
     8170            mainSizer.Add(PlotSizer())           
     8171           
     8172        for item in keyList:
     8173            histData = UseList[item]
     8174            if 'Use' not in UseList[item]:      #patch
     8175                UseList[item]['Use'] = True
     8176            showSizer = wx.BoxSizer(wx.HORIZONTAL)
     8177            showData = wx.CheckBox(DData,-1,label=' Show '+item)
     8178            showData.SetValue(UseList[item]['Show'])
     8179            Indx[showData.GetId()] = item
     8180            showData.Bind(wx.EVT_CHECKBOX, OnShowData)
     8181            showSizer.Add(showData,0,wx.ALIGN_CENTER_VERTICAL)
     8182            useData = wx.CheckBox(DData,-1,label='Use?')
     8183            Indx[useData.GetId()] = item
     8184            showSizer.Add(useData,0,wx.ALIGN_CENTER_VERTICAL)
     8185            useData.Bind(wx.EVT_CHECKBOX, OnUseData)
     8186            useData.SetValue(UseList[item]['Use'])
     8187            copyData = wx.Button(DData,-1,label=' Copy?')
     8188            Indx[copyData.GetId()] = item
     8189            copyData.Bind(wx.EVT_BUTTON,OnCopyData)
     8190            showSizer.Add(copyData,wx.ALIGN_CENTER_VERTICAL)
     8191            copyFlags = wx.Button(DData,-1,label=' Copy flags?')
     8192            Indx[copyFlags.GetId()] = item
     8193            copyFlags.Bind(wx.EVT_BUTTON,OnCopyFlags)
     8194            showSizer.Add(copyFlags,wx.ALIGN_CENTER_VERTICAL)
     8195            mainSizer.Add((5,5),0)
     8196            mainSizer.Add(showSizer,0,wx.ALIGN_CENTER_VERTICAL)
     8197            mainSizer.Add((0,5),0)
     8198           
     8199            if UseList[item]['Show']:
     8200                mainSizer.Add(ScaleSizer())
     8201                mainSizer.Add((0,5),0)
     8202               
     8203            if item[:4] == 'PWDR' and UseList[item]['Show']:
     8204                if UseList[item]['Size'][0] == 'isotropic':
     8205                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
     8206                    isoSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
     8207                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
     8208                    isoSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
     8209                    mainSizer.Add(isoSizer)
     8210                    mainSizer.Add(IsoSizer(u' Cryst. size(\xb5m): ','Size','%.3f',
     8211                        OnSizeVal,OnSizeRef),0,wx.ALIGN_CENTER_VERTICAL)
     8212                elif UseList[item]['Size'][0] == 'uniaxial':
     8213                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
     8214                    uniSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
     8215                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
     8216                    uniSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
     8217                    uniSizer.Add(UniSizer('Size',OnSizeAxis),0,wx.ALIGN_CENTER_VERTICAL)
     8218                    mainSizer.Add(uniSizer)
     8219                    mainSizer.Add(UniDataSizer(u'size(\xb5m): ','Size','%.3f',OnSizeVal,OnSizeRef))
     8220                elif UseList[item]['Size'][0] == 'ellipsoidal':
     8221                    ellSizer = wx.BoxSizer(wx.HORIZONTAL)
     8222                    ellSizer.Add(TopSizer(' Size model: ',['isotropic','uniaxial','ellipsoidal'],
     8223                        'Size',OnSizeType),0,wx.ALIGN_CENTER_VERTICAL)
     8224                    ellSizer.Add(LGmixSizer('Size',OnLGmixVal,OnLGmixRef))
     8225                    mainSizer.Add(ellSizer)
     8226                    mainSizer.Add(EllSizeDataSizer())
     8227                mainSizer.Add((0,5),0)                   
     8228               
     8229                if UseList[item]['Mustrain'][0] == 'isotropic':
     8230                    isoSizer = wx.BoxSizer(wx.HORIZONTAL)
     8231                    isoSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
     8232                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
     8233                    isoSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
     8234                    mainSizer.Add(isoSizer)
     8235                    mainSizer.Add(IsoSizer(' microstrain: ','Mustrain','%.1f',
     8236                        OnStrainVal,OnStrainRef),0,wx.ALIGN_CENTER_VERTICAL)                   
     8237                    mainSizer.Add((0,5),0)
     8238                elif UseList[item]['Mustrain'][0] == 'uniaxial':
     8239                    uniSizer = wx.BoxSizer(wx.HORIZONTAL)
     8240                    uniSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
     8241                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
     8242                    uniSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
     8243                    uniSizer.Add(UniSizer('Mustrain',OnStrainAxis),0,wx.ALIGN_CENTER_VERTICAL)
     8244                    mainSizer.Add(uniSizer)
     8245                    mainSizer.Add(UniDataSizer('mustrain: ','Mustrain','%.1f',OnStrainVal,OnStrainRef))
     8246                elif UseList[item]['Mustrain'][0] == 'generalized':
     8247                    genSizer = wx.BoxSizer(wx.HORIZONTAL)
     8248                    genSizer.Add(TopSizer(' Mustrain model: ',['isotropic','uniaxial','generalized',],
     8249                        'Mustrain',OnStrainType),0,wx.ALIGN_CENTER_VERTICAL)
     8250                    genSizer.Add(LGmixSizer('Mustrain',OnLGmixVal,OnLGmixRef))
     8251                    mainSizer.Add(genSizer)
     8252                    mainSizer.Add(GenStrainDataSizer())                       
     8253                mainSizer.Add((0,5),0)
     8254               
     8255                mainSizer.Add(wx.StaticText(DData,-1,' Hydrostatic/elastic strain:'))
     8256                mainSizer.Add(HstrainSizer())
     8257                   
     8258                #texture  'Pref. Ori.':['MD',1.0,False,[0,0,1],0,[]] last two for 'SH' are SHorder & coeff
     8259                poSizer = wx.BoxSizer(wx.VERTICAL)
     8260                POData = UseList[item]['Pref.Ori.']
     8261                poSizer.Add(PoTopSizer(POData))
     8262                if POData[0] == 'MD':
     8263                    poSizer.Add(MDDataSizer(POData))
     8264                else:           #'SH'
     8265                    if POData[4]:       #SH order > 0
     8266                        poSizer.Add(SHDataSizer(POData))
     8267                       
     8268                mainSizer.Add(poSizer)
     8269                mainSizer.Add((0,5),0)               
     8270                #Extinction  'Extinction':[0.0,False]
     8271                mainSizer.Add(ExtSizer())
     8272                mainSizer.Add((0,5),0)
     8273            elif item[:4] == 'HKLF' and UseList[item]['Show']:
     8274                mainSizer.Add((0,5),0)               
     8275                mainSizer.Add(SCExtSizer())
     8276                mainSizer.Add((0,5),0)
     8277                pass
     8278        mainSizer.Add((5,5),0)
     8279
     8280        DData.SetSizer(mainSizer,True)
     8281        mainSizer.FitInside(G2frame.dataFrame)
     8282        Size = mainSizer.GetMinSize()
     8283        Size[0] += 40
     8284        Size[1] = max(Size[1],290) + 35
     8285        DData.SetSize(Size)
     8286        DData.SetScrollbars(10,10,Size[0]/10-4,Size[1]/10-1)
     8287        Size[1] = min(Size[1],450)
     8288        G2frame.dataFrame.setSizePosLeft(Size)
     8289       
     8290    def OnHklfAdd(event):
     8291        UseList = data['Histograms']
     8292        keyList = UseList.keys()
     8293        TextList = []
     8294        if G2frame.PatternTree.GetCount():
     8295            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
     8296            while item:
     8297                name = G2frame.PatternTree.GetItemText(item)
     8298                if name not in keyList and 'HKLF' in name:
     8299                    TextList.append(name)
     8300                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)                       
     8301            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
     8302            try:
     8303                if dlg.ShowModal() == wx.ID_OK:
     8304                    result = dlg.GetSelections()
     8305                    for i in result:
     8306                        histoName = TextList[i]
     8307                        UseList[histoName] = {'Histogram':histoName,'Show':False,'Scale':[1.0,True],
     8308                            'Extinction':['Lorentzian','Secondary Type I',
     8309                            {'Tbar':0.0,'Eg':[0.0,False],'Es':[0.0,False],'Ep':[0.0,False]},]}                       
     8310                    data['Histograms'] = UseList
     8311                    wx.BeginBusyCursor()
     8312                    UpdateHKLFdata(histoName)
     8313                    wx.EndBusyCursor()
     8314                    wx.CallAfter(UpdateDData)
     8315            finally:
     8316                dlg.Destroy()
     8317               
     8318    def UpdateHKLFdata(histoName):
     8319        generalData = data['General']
     8320        Id = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
     8321        reflData = G2frame.PatternTree.GetItemPyData(Id)[1]
     8322        SGData = generalData['SGData']
     8323        Cell = generalData['Cell'][1:7]
     8324        G,g = G2lat.cell2Gmat(Cell)
     8325        for ref in reflData:
     8326            H = ref[:3]
     8327            ref[4] = np.sqrt(1./G2lat.calc_rDsq2(H,G))
     8328            iabsnt,ref[3],ref[11],ref[12] = G2spc.GenHKLf(H,SGData)
     8329        G2frame.PatternTree.SetItemPyData(Id,[histoName,reflData])
     8330       
     8331    def OnPwdrAdd(event):
     8332        generalData = data['General']
     8333        SGData = generalData['SGData']
     8334        UseList = data['Histograms']
     8335        newList = []
     8336        NShkl = len(G2spc.MustrainNames(SGData))
     8337        NDij = len(G2spc.HStrainNames(SGData))
     8338        keyList = UseList.keys()
     8339        TextList = ['All PWDR']
     8340        if G2frame.PatternTree.GetCount():
     8341            item, cookie = G2frame.PatternTree.GetFirstChild(G2frame.root)
     8342            while item:
     8343                name = G2frame.PatternTree.GetItemText(item)
     8344                if name not in keyList and 'PWDR' in name:
     8345                    TextList.append(name)
     8346                item, cookie = G2frame.PatternTree.GetNextChild(G2frame.root, cookie)
     8347            dlg = wx.MultiChoiceDialog(G2frame, 'Which new data to use?', 'Use data', TextList, wx.CHOICEDLG_STYLE)
     8348            try:
     8349                if dlg.ShowModal() == wx.ID_OK:
     8350                    result = dlg.GetSelections()
     8351                    for i in result: newList.append(TextList[i])
     8352                    if 'All PWDR' in newList:
     8353                        newList = TextList[1:]
     8354                    for histoName in newList:
     8355                        pId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,histoName)
     8356                        UseList[histoName] = {'Histogram':histoName,'Show':False,
     8357                            'Scale':[1.0,False],'Pref.Ori.':['MD',1.0,False,[0,0,1],0,{}],
     8358                            'Size':['isotropic',[4.,4.,1.0],[False,False,False],[0,0,1],
     8359                                [4.,4.,4.,0.,0.,0.],6*[False,]],
     8360                            'Mustrain':['isotropic',[1000.0,1000.0,1.0],[False,False,False],[0,0,1],
     8361                                NShkl*[0.01,],NShkl*[False,]],
     8362                            'HStrain':[NDij*[0.0,],NDij*[False,]],                         
     8363                            'Extinction':[0.0,False]}
     8364                        refList = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,pId,'Reflection Lists'))
     8365                        refList[generalData['Name']] = []                       
     8366                    data['Histograms'] = UseList
     8367                    wx.CallAfter(UpdateDData)
     8368            finally:
     8369                dlg.Destroy()
     8370       
     8371    def OnDataDelete(event):
     8372        UseList = data['Histograms']
     8373        keyList = ['All',]+UseList.keys()
     8374        keyList.sort()
     8375        DelList = []
     8376        if UseList:
     8377            DelList = []
     8378            dlg = wx.MultiChoiceDialog(G2frame,
     8379                'Which histogram to delete from this phase?', 'Delete histogram',
     8380                keyList, wx.CHOICEDLG_STYLE)
     8381            try:
     8382                if dlg.ShowModal() == wx.ID_OK:
     8383                    result = dlg.GetSelections()
     8384                    for i in result:
     8385                        DelList.append(keyList[i])
     8386                    if 'All' in DelList:
     8387                        DelList = keyList[1:]
     8388                    for i in DelList:
     8389                        del UseList[i]
     8390                    wx.CallAfter(UpdateDData)
     8391            finally:
     8392                dlg.Destroy()
     8393
     8394################################################################################
     8395##### Pawley routines
     8396################################################################################
     8397
     8398    def FillPawleyReflectionsGrid():
     8399        G2frame.dataFrame.SetStatusText('')
     8400                       
     8401        def KeyEditPawleyGrid(event):
     8402            colList = G2frame.PawleyRefl.GetSelectedCols()
     8403            PawleyPeaks = data['Pawley ref']
     8404            if event.GetKeyCode() == wx.WXK_RETURN:
     8405                event.Skip(True)
     8406            elif event.GetKeyCode() == wx.WXK_CONTROL:
     8407                event.Skip(True)
     8408            elif event.GetKeyCode() == wx.WXK_SHIFT:
     8409                event.Skip(True)
     8410            elif colList:
     8411                G2frame.PawleyRefl.ClearSelection()
     8412                key = event.GetKeyCode()
     8413                for col in colList:
     8414                    if PawleyTable.GetTypeName(0,col) == wg.GRID_VALUE_BOOL:
     8415                        if key == 89: #'Y'
     8416                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=True
     8417                        elif key == 78:  #'N'
     8418                            for row in range(PawleyTable.GetNumberRows()): PawleyPeaks[row][col]=False
     8419                        FillPawleyReflectionsGrid()
     8420           
     8421        if 'Pawley ref' in data:
     8422            PawleyPeaks = data['Pawley ref']                       
     8423            rowLabels = []
     8424            for i in range(len(PawleyPeaks)): rowLabels.append(str(i))
     8425            colLabels = ['h','k','l','mul','d','refine','Fsq(hkl)','sig(Fsq)']
     8426            Types = 4*[wg.GRID_VALUE_LONG,]+[wg.GRID_VALUE_FLOAT+':10,4',wg.GRID_VALUE_BOOL,]+ \
     8427                2*[wg.GRID_VALUE_FLOAT+':10,2',]
     8428            PawleyTable = G2gd.Table(PawleyPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
     8429            G2frame.PawleyRefl.SetTable(PawleyTable, True)
     8430            G2frame.PawleyRefl.Bind(wx.EVT_KEY_DOWN, KeyEditPawleyGrid)                 
     8431            for r in range(G2frame.PawleyRefl.GetNumberRows()):
     8432                for c in range(G2frame.PawleyRefl.GetNumberCols()):
     8433                    if c in [5,6]:
     8434                        G2frame.PawleyRefl.SetReadOnly(r,c,isReadOnly=False)
     8435                    else:
     8436                        G2frame.PawleyRefl.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
     8437            G2frame.PawleyRefl.SetMargins(0,0)
     8438            G2frame.PawleyRefl.AutoSizeColumns(False)
     8439            G2frame.dataFrame.setSizePosLeft([500,300])
     8440                   
     8441    def OnPawleyLoad(event):
     8442        generalData = data['General']
     8443        dmin = generalData['Pawley dmin']
     8444        cell = generalData['Cell'][1:7]
     8445        A = G2lat.cell2A(cell)
     8446        SGData = generalData['SGData']
     8447        HKLd = np.array(G2lat.GenHLaue(dmin,SGData,A))
     8448        PawleyPeaks = []
     8449        wx.BeginBusyCursor()
     8450        try:
     8451            for h,k,l,d in HKLd:
     8452                ext,mul = G2spc.GenHKLf([h,k,l],SGData)[:2]
     8453                if not ext:
     8454                    mul *= 2        #for powder multiplicity
     8455                    PawleyPeaks.append([h,k,l,mul,d,False,100.0,1.0])
     8456        finally:
     8457            wx.EndBusyCursor()
     8458        data['Pawley ref'] = PawleyPeaks
     8459        FillPawleyReflectionsGrid()
     8460       
     8461    def OnPawleyEstimate(event):
     8462        try:
     8463            Refs = data['Pawley ref']
     8464            Histograms = data['Histograms']
     8465        except KeyError:
     8466            print '**** Error - no histograms defined for this phase ****'
     8467            return
     8468        HistoNames = Histograms.keys()
     8469        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
     8470        xdata = G2frame.PatternTree.GetItemPyData(PatternId)[1]
     8471        Inst = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Instrument Parameters'))
     8472        Inst = dict(zip(Inst[3],Inst[1]))
     8473        Sample = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Sample Parameters'))
     8474        if 'Lam' in Inst:
     8475            wave = Inst['Lam']
     8476        else:
     8477            wave = Inst['Lam1']
     8478        posCorr = Inst['Zero']
     8479        const = 9.e-2/(np.pi*Sample['Gonio. radius'])                  #shifts in microns
     8480       
     8481        wx.BeginBusyCursor()
     8482        try:
     8483            for ref in Refs:
     8484                pos = 2.0*asind(wave/(2.0*ref[4]))
     8485                if 'Bragg' in Sample['Type']:
     8486                    pos -= const*(4.*Sample['Shift'][0]*cosd(pos/2.0)+ \
     8487                        Sample['Transparency'][0]*sind(pos)*100.0)            #trans(=1/mueff) in cm
     8488                else:               #Debye-Scherrer - simple but maybe not right
     8489                    pos -= const*(Sample['DisplaceX'][0]*cosd(pos)+Sample['DisplaceY'][0]*sind(pos))
     8490                indx = np.searchsorted(xdata[0],pos)
     8491                try:
     8492                    FWHM = max(0.001,G2pwd.getFWHM(pos,Inst))/2.
     8493                    dx = xdata[0][indx+1]-xdata[0][indx]
     8494                    ref[6] = FWHM*(xdata[1][indx]-xdata[4][indx])*cosd(pos/2.)**3/dx
     8495                    Lorenz = 1./(2.*sind(xdata[0][indx]/2.)**2*cosd(xdata[0][indx]/2.))           #Lorentz correction
     8496                    pola,dIdPola = G2pwd.Polarization(Inst['Polariz.'],xdata[0][indx],Inst['Azimuth'])
     8497                    ref[6] /= (Lorenz*pola*ref[3])
     8498                except IndexError:
     8499                    pass
     8500        finally:
     8501            wx.EndBusyCursor()
     8502        FillPawleyReflectionsGrid()
     8503
     8504    def OnPawleyUpdate(event):
     8505        try:
     8506            Refs = data['Pawley ref']
     8507            Histograms = data['Histograms']
     8508        except KeyError:
     8509            print '**** Error - no histograms defined for this phase ****'
     8510            return
     8511        HistoNames = Histograms.keys()
     8512        PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root,HistoNames[0])
     8513        refData = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))[PhaseName]
     8514        wx.BeginBusyCursor()
     8515        try:
     8516            for iref,ref in enumerate(Refs):
     8517                try:
     8518                    ref[6] = abs(refData[iref][9])
     8519                    ref[7] = 1.0
     8520                except IndexError:
     8521                    pass
     8522        finally:
     8523            wx.EndBusyCursor()
     8524        FillPawleyReflectionsGrid()
     8525                           
     8526    def OnPawleyDelete(event):          #doesn't work
     8527        dlg = wx.MessageDialog(G2frame,'Do you really want to delete selected Pawley reflections?','Delete',
     8528            wx.YES_NO | wx.ICON_QUESTION)
     8529        try:
     8530            result = dlg.ShowModal()
     8531            if result == wx.ID_YES:
     8532                Refs = data['Pawley ref']
     8533                Ind = G2frame.PawleyRefl.GetSelectedRows()
     8534                Ind.sort()
     8535                Ind.reverse()
     8536                for ind in Ind:
     8537                    Refs = np.delete(Refs,ind,0)
     8538                data['Pawley ref'] = Refs
     8539                FillPawleyReflectionsGrid()
     8540        finally:
     8541            dlg.Destroy()
     8542
     8543################################################################################
     8544##### Fourier routines
     8545################################################################################
     8546
     8547    def FillMapPeaksGrid():
     8548                       
     8549        def RowSelect(event):
     8550            r,c =  event.GetRow(),event.GetCol()
     8551            if r < 0 and c < 0:
     8552                if MapPeaks.IsSelection():
     8553                    MapPeaks.ClearSelection()
     8554                else:
     8555                    for row in range(MapPeaks.GetNumberRows()):
     8556                        MapPeaks.SelectRow(row,True)
     8557                   
     8558            elif c < 0:                   #only row clicks
     8559                if event.ControlDown():                   
     8560                    if r in MapPeaks.GetSelectedRows():
     8561                        MapPeaks.DeselectRow(r)
     8562                    else:
     8563                        MapPeaks.SelectRow(r,True)
     8564                elif event.ShiftDown():
     8565                    for row in range(r+1):
     8566                        MapPeaks.SelectRow(row,True)
     8567                else:
     8568                    MapPeaks.ClearSelection()
     8569                    MapPeaks.SelectRow(r,True)
     8570            elif r < 0:                 #a column pick
     8571                mapPeaks = data['Map Peaks']
     8572                c =  event.GetCol()
     8573                if colLabels[c] == 'mag':
     8574                    mapPeaks = G2mth.sortArray(mapPeaks,0,reverse=True)
     8575                elif colLabels[c] == 'dzero':
     8576                    mapPeaks = G2mth.sortArray(mapPeaks,4)
     8577                else:
     8578                    return
     8579                data['Map Peaks'] = mapPeaks
     8580                wx.CallAfter(FillMapPeaksGrid)
     8581            G2plt.PlotStructure(G2frame,data)                   
     8582           
     8583        G2frame.dataFrame.setSizePosLeft([450,300])
     8584        G2frame.dataFrame.SetStatusText('')
     8585        if 'Map Peaks' in data:
     8586            G2frame.dataFrame.SetStatusText('Select mag or dzero columns to sort')
     8587            mapPeaks = data['Map Peaks']                       
     8588            rowLabels = []
     8589            for i in range(len(mapPeaks)): rowLabels.append(str(i))
     8590            colLabels = ['mag','x','y','z','dzero']
     8591            Types = 5*[wg.GRID_VALUE_FLOAT+':10,4',]
     8592            G2frame.MapPeaksTable = G2gd.Table(mapPeaks,rowLabels=rowLabels,colLabels=colLabels,types=Types)
     8593            MapPeaks.SetTable(G2frame.MapPeaksTable, True)
     8594            MapPeaks.Bind(wg.EVT_GRID_LABEL_LEFT_CLICK, RowSelect)
     8595            for r in range(MapPeaks.GetNumberRows()):
     8596                for c in range(MapPeaks.GetNumberCols()):
     8597                    MapPeaks.SetCellStyle(r,c,VERY_LIGHT_GREY,True)
     8598            MapPeaks.SetMargins(0,0)
     8599            MapPeaks.AutoSizeColumns(False)
     8600                   
     8601    def OnPeaksMove(event):
     8602        if 'Map Peaks' in data:
     8603            mapPeaks = data['Map Peaks']                       
     8604            Ind = MapPeaks.GetSelectedRows()
     8605            for ind in Ind:
     8606                x,y,z,d = mapPeaks[ind][1:]
     8607                AtomAdd(x,y,z,'C')
     8608   
     8609    def OnPeaksClear(event):
     8610        data['Map Peaks'] = []
     8611        FillMapPeaksGrid()
     8612        G2plt.PlotStructure(G2frame,data)
     8613       
     8614    def OnPeaksDelete(event):
     8615        if 'Map Peaks' in data:
     8616            mapPeaks = data['Map Peaks']
     8617            Ind = MapPeaks.GetSelectedRows()
     8618            Ind.sort()
     8619            Ind.reverse()
     8620            for ind in Ind:
     8621                mapPeaks = np.delete(mapPeaks,ind,0)
     8622            data['Map Peaks'] = mapPeaks
     8623        FillMapPeaksGrid()
     8624        G2plt.PlotStructure(G2frame,data)
     8625               
     8626    def OnPeaksUnique(event):
     8627        if 'Map Peaks' in data:
     8628            mapPeaks = data['Map Peaks']
     8629            Ind = MapPeaks.GetSelectedRows()
     8630            if Ind:
     8631                wx.BeginBusyCursor()
     8632                try:
     8633                    Ind = G2mth.PeaksUnique(data,Ind)
     8634                    for r in range(MapPeaks.GetNumberRows()):
     8635                        if r in Ind:
     8636                            MapPeaks.SelectRow(r,addToSelected=True)
     8637                        else:
     8638                            MapPeaks.DeselectRow(r)
     8639                finally:
     8640                    wx.EndBusyCursor()
     8641                G2plt.PlotStructure(G2frame,data)
     8642               
     8643    def OnPeaksViewPoint(event):
     8644        # set view point
     8645        indx = MapPeaks.GetSelectedRows()
     8646        if not indx:
     8647            print '***** ERROR - no peaks selected'
     8648            return
     8649        mapPeaks = data['Map Peaks']
     8650        drawingData = data['Drawing']
     8651        drawingData['viewPoint'][0] = mapPeaks[indx[0]][1:4]
     8652        G2plt.PlotStructure(G2frame,data)
     8653   
     8654    def OnPeaksDistVP(event):
     8655        # distance to view point
     8656        indx = MapPeaks.GetSelectedRows()
     8657        if not indx:
     8658            print '***** ERROR - no peaks selected'
     8659            return
     8660        generalData = data['General']
     8661        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
     8662        mapPeaks = data['Map Peaks']
     8663        drawingData = data['Drawing']
     8664        viewPt = np.array(drawingData['viewPoint'][0])
     8665        print ' Distance from view point at %.3f %.3f %.3f to:'%(viewPt[0],viewPt[1],viewPt[2])
     8666        colLabels = [MapPeaks.GetColLabelValue(c) for c in range(MapPeaks.GetNumberCols())]
     8667        cx = colLabels.index('x')
     8668        cm = colLabels.index('mag')
     8669        for i in indx:
     8670            peak = mapPeaks[i]
     8671            Dx = np.array(peak[cx:cx+3])-viewPt
     8672            dist = np.sqrt(np.sum(np.inner(Amat,Dx)**2,axis=0))
     8673            print 'Peak: %5d mag= %8.2f distance = %.3f'%(i,peak[cm],dist)
     8674
     8675    def OnPeaksDA(event):
     8676        #distance, angle
     8677        indx = MapPeaks.GetSelectedRows()
     8678        if len(indx) not in [2,3]:
     8679            print '**** ERROR - wrong number of atoms for distance or angle calculation'
     8680            return
     8681        generalData = data['General']
     8682        Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])           
     8683        mapPeaks = data['Map Peaks']
     8684        xyz = []
     8685        for i in indx:
     8686            xyz.append(mapPeaks[i][1:4])
     8687        if len(indx) == 2:
     8688            print ' distance for atoms %s = %.3f'%(str(indx),G2mth.getRestDist(xyz,Amat))
     8689        else:
     8690            print ' angle for atoms %s = %.2f'%(str(indx),G2mth.getRestAngle(xyz,Amat))
     8691                                   
     8692    def OnFourierMaps(event):
     8693        generalData = data['General']
     8694        mapData = generalData['Map']
     8695        reflName = mapData['RefList']
     8696        phaseName = generalData['Name']
     8697        if 'PWDR' in reflName:
     8698            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
     8699            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
     8700            reflData = reflSets[phaseName]
     8701        elif 'HKLF' in reflName:
     8702            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
     8703            reflData = G2frame.PatternTree.GetItemPyData(PatternId)[1]
     8704        mapData.update(G2mth.FourierMap(data,reflData))
     8705        mapData['Flip'] = False
     8706        mapSig = np.std(mapData['rho'])
     8707        if not data['Drawing']:                 #if new drawing - no drawing data!
     8708            SetupDrawingData()
     8709        data['Drawing']['contourLevel'] = 1.
     8710        data['Drawing']['mapSize'] = 10.
     8711        print mapData['MapType']+' computed: rhomax = %.3f rhomin = %.3f sigma = %.3f'%(np.max(mapData['rho']),np.min(mapData['rho']),mapSig)
     8712        UpdateDrawAtoms()
     8713        G2plt.PlotStructure(G2frame,data)
     8714       
     8715    def OnFourClear(event):
     8716        generalData = data['General']
     8717        generalData['Map'] = mapDefault
     8718        G2plt.PlotStructure(G2frame,data)
     8719       
     8720    def printRho(SGLaue,rho,rhoMax):                         
     8721# map printing for testing purposes
     8722        dim = len(rho.shape)
     8723        if dim == 2:
     8724            ix,jy = rho.shape
     8725            for j in range(jy):
     8726                line = ''
     8727                if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
     8728                    line += (jy-j)*'  '
     8729                for i in range(ix):
     8730                    r = int(100*rho[i,j]/rhoMax)
     8731                    line += '%4d'%(r)
     8732                print line+'\n'
     8733        else:
     8734            ix,jy,kz = rho.shape
     8735            for k in range(kz):
     8736                print 'k = ',k
     8737                for j in range(jy):
     8738                    line = ''
     8739                    if SGLaue in ['3','3m1','31m','6/m','6/mmm']:
     8740                        line += (jy-j)*'  '
     8741                    for i in range(ix):
     8742                        r = int(100*rho[i,j,k]/rhoMax)
     8743                        line += '%4d'%(r)
     8744                    print line+'\n'
     8745## keep this               
     8746   
     8747    def OnSearchMaps(event):
     8748       
     8749#        def FindBondsPeaks(peaks):                    #uses numpy & masks - very fast even for proteins!
     8750#            import numpy.ma as ma
     8751#            Amat,Bmat = G2lat.cell2AB(generalData['Cell'][1:7])
     8752#            for peak in peaks:
     8753#                peak[-1] = []
     8754#            Indx = range(len(peaks))
     8755#            Peaks = []
     8756#            Radii = []
     8757#            for peak in peaks:
     8758#                Peaks.append(np.array(peak[1:4]))
     8759#                Radii.append(1.0)
     8760#            Atoms = np.array(Atoms)
     8761#            Radii = np.array(Radii)
     8762#            IAR = zip(Indx,Atoms,Radii)
     8763#            for atomA in IAR:
     8764#                Dx = Atoms-atomA[1]
     8765#                dist = ma.masked_less(np.sqrt(np.sum(np.inner(Amat,Dx)**2,axis=0)),0.5) #gets rid of G2frame & disorder "bonds" < 0.5A
     8766#                sumR = atomA[3]+Radii
     8767#                IndB = ma.nonzero(ma.masked_greater(dist-data['Drawing']['radiusFactor']*sumR,0.))                 #get indices of bonded atoms
     8768#                i = atomA[0]
     8769#                for j in IndB[0]:
     8770#                    if Styles[i] == 'polyhedra':
     8771#                        atomData[i][-2].append(np.inner(Amat,Dx[j]))
     8772#                    elif Styles[j] != 'polyhedra' and j > i:
     8773#                        atomData[i][-2].append(Dx[j]*Radii[i]/sumR[j])
     8774#                        atomData[j][-2].append(-Dx[j]*Radii[j]/sumR[j])
     8775                           
     8776        peaks = []
     8777        mags = []
     8778        print ' Begin fourier map search - can take some time'
     8779        time0 = time.time()
     8780        generalData = data['General']
     8781        mapData = generalData['Map']
     8782        if len(mapData['rho']):
     8783            pgbar = wx.ProgressDialog('Map search','No. Peaks found =',1001.0,
     8784                style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
     8785            screenSize = wx.ClientDisplayRect()
     8786            Size = pgbar.GetSize()
     8787            Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
     8788            pgbar.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
     8789            pgbar.SetSize(Size)
     8790            try:
     8791                peaks,mags,dzeros = G2mth.SearchMap(data,keepDup=True,Pgbar=pgbar)
     8792            finally:
     8793                pgbar.Destroy()
     8794            sortIdx = np.argsort(mags.flatten())
     8795            if len(peaks):
     8796                data['Map Peaks'] = np.concatenate((mags,peaks,dzeros),axis=1)           
     8797                print ' Map search finished, time = %.2fs'%(time.time()-time0)
     8798            Page = G2frame.dataDisplay.FindPage('Map peaks')
     8799            G2frame.dataDisplay.ChangeSelection(Page)
     8800            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.MapPeaksMenu)
     8801            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksMove, id=G2gd.wxID_PEAKSMOVE)
     8802            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDA, id=G2gd.wxID_PEAKSDA)
     8803            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksUnique, id=G2gd.wxID_PEAKSUNIQUE)
     8804            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDelete, id=G2gd.wxID_PEAKSDELETE)
     8805            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksClear, id=G2gd.wxID_PEAKSCLEAR)
     8806            UpdateDrawAtoms()
     8807            FillMapPeaksGrid()
     8808        else:
     8809            print 'No map available'
     8810       
     8811    def OnChargeFlip(event):
     8812        generalData = data['General']
     8813        mapData = generalData['Map']
     8814        flipData = generalData['Flip']
     8815        reflName = flipData['RefList']
     8816        phaseName = generalData['Name']
     8817        if 'PWDR' in reflName:
     8818            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
     8819            reflSets = G2frame.PatternTree.GetItemPyData(G2gd.GetPatternTreeItemId(G2frame,PatternId,'Reflection Lists'))
     8820            reflData = reflSets[phaseName]
     8821        elif 'HKLF' in reflName:
     8822            PatternId = G2gd.GetPatternTreeItemId(G2frame,G2frame.root, reflName)
     8823            reflData = G2frame.PatternTree.GetItemPyData(PatternId)[1]
     8824        else:
     8825            print '**** ERROR - No data defined for charge flipping'
     8826            return
     8827        pgbar = wx.ProgressDialog('Charge flipping','Residual Rcf =',101.0,
     8828            style = wx.PD_ELAPSED_TIME|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)
     8829        screenSize = wx.ClientDisplayRect()
     8830        Size = pgbar.GetSize()
     8831        Size = (int(Size[0]*1.2),Size[1]) # increase size a bit along x
     8832        pgbar.SetPosition(wx.Point(screenSize[2]-Size[0]-305,screenSize[1]+5))
     8833        pgbar.SetSize(Size)
     8834        try:
     8835            mapData.update(G2mth.ChargeFlip(data,reflData,pgbar))
     8836        finally:
     8837            pgbar.Destroy()
     8838        mapData['Flip'] = True       
     8839        mapSig = np.std(mapData['rho'])
     8840        if not data['Drawing']:                 #if new drawing - no drawing data!
     8841            SetupDrawingData()
     8842        data['Drawing']['contourLevel'] = 1.
     8843        data['Drawing']['mapSize'] = 10.
     8844        print ' Charge flip map computed: rhomax = %.3f rhomin = %.3f sigma = %.3f'%(np.max(mapData['rho']),np.min(mapData['rho']),mapSig)
     8845        if mapData['Rcf'] < 99.:
     8846            OnSearchMaps(event)             #does a plot structure at end
     8847        else:
     8848            print 'Bad charge flip map - no peak search done'
     8849               
     8850    def OnTextureRefine(event):
     8851        print 'refine texture?'
     8852        event.Skip()       
     8853           
     8854    def OnTextureClear(event):
     8855        print 'clear texture?'
     8856        event.Skip()
     8857
     8858    def OnPageChanged(event):
     8859        page = event.GetSelection()
     8860        text = G2frame.dataDisplay.GetPageText(page)
     8861        if text == 'Atoms':
     8862            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.AtomsMenu)
     8863            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomAdd, id=G2gd.wxID_ATOMSEDITADD)
     8864            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomViewAdd, id=G2gd.wxID_ATOMSVIEWADD)
     8865            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomInsert, id=G2gd.wxID_ATOMSEDITINSERT)
     8866            G2frame.dataFrame.Bind(wx.EVT_MENU, OnAtomViewInsert, id=G2gd.wxID_ATOMVIEWINSERT)
     8867            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomDelete, id=G2gd.wxID_ATOMSEDITDELETE)
     8868            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomRefine, id=G2gd.wxID_ATOMSREFINE)
     8869            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomModify, id=G2gd.wxID_ATOMSMODIFY)
     8870            G2frame.dataFrame.Bind(wx.EVT_MENU, AtomTransform, id=G2gd.wxID_ATOMSTRANSFORM)
     8871            G2frame.dataFrame.Bind(wx.EVT_MENU, OnReloadDrawAtoms, id=G2gd.wxID_RELOADDRAWATOMS)
     8872            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDistAngle, id=G2gd.wxID_ATOMSDISAGL)
     8873            FillAtomsGrid()
     8874        elif text == 'General':
     8875            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataGeneral)
     8876            G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourierMaps, id=G2gd.wxID_FOURCALC)
     8877            G2frame.dataFrame.Bind(wx.EVT_MENU, OnSearchMaps, id=G2gd.wxID_FOURSEARCH)
     8878            G2frame.dataFrame.Bind(wx.EVT_MENU, OnChargeFlip, id=G2gd.wxID_CHARGEFLIP)
     8879            G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourClear, id=G2gd.wxID_FOURCLEAR)
     8880            UpdateGeneral()
     8881        elif text == 'Data':
     8882            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataMenu)
     8883            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPwdrAdd, id=G2gd.wxID_PWDRADD)
     8884            G2frame.dataFrame.Bind(wx.EVT_MENU, OnHklfAdd, id=G2gd.wxID_HKLFADD)
     8885            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDataDelete, id=G2gd.wxID_DATADELETE)
     8886            UpdateDData()
     8887            G2plt.PlotSizeStrainPO(G2frame,data,Start=True)
     8888        elif text == 'Draw Options':
     8889            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataDrawOptions)
     8890            UpdateDrawOptions()
     8891            G2plt.PlotStructure(G2frame,data)
     8892        elif text == 'Draw Atoms':
     8893            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DrawAtomsMenu)
     8894            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomStyle, id=G2gd.wxID_DRAWATOMSTYLE)
     8895            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomLabel, id=G2gd.wxID_DRAWATOMLABEL)
     8896            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomColor, id=G2gd.wxID_DRAWATOMCOLOR)
     8897            G2frame.dataFrame.Bind(wx.EVT_MENU, ResetAtomColors, id=G2gd.wxID_DRAWATOMRESETCOLOR)
     8898            G2frame.dataFrame.Bind(wx.EVT_MENU, SetViewPoint, id=G2gd.wxID_DRAWVIEWPOINT)
     8899            G2frame.dataFrame.Bind(wx.EVT_MENU, AddSymEquiv, id=G2gd.wxID_DRAWADDEQUIV)
     8900            G2frame.dataFrame.Bind(wx.EVT_MENU, TransformSymEquiv, id=G2gd.wxID_DRAWTRANSFORM)
     8901            G2frame.dataFrame.Bind(wx.EVT_MENU, FillCoordSphere, id=G2gd.wxID_DRAWFILLCOORD)           
     8902            G2frame.dataFrame.Bind(wx.EVT_MENU, FillUnitCell, id=G2gd.wxID_DRAWFILLCELL)
     8903            G2frame.dataFrame.Bind(wx.EVT_MENU, DrawAtomsDelete, id=G2gd.wxID_DRAWDELETE)
     8904            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawDistVP, id=G2gd.wxID_DRAWDISTVP)
     8905            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawDAT, id=G2gd.wxID_DRAWDISAGLTOR)
     8906            G2frame.dataFrame.Bind(wx.EVT_MENU, OnDrawPlane, id=G2gd.wxID_DRAWPLANE)
     8907            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRBOND)
     8908            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRANGLE)
     8909            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRPLANE)
     8910            G2frame.dataFrame.Bind(wx.EVT_MENU, OnRestraint, id=G2gd.wxID_DRAWRESTRCHIRAL)
     8911            UpdateDrawAtoms()
     8912            G2plt.PlotStructure(G2frame,data)
     8913        elif text == 'Pawley reflections':
     8914            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.PawleyMenu)
     8915            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyLoad, id=G2gd.wxID_PAWLEYLOAD)
     8916            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyEstimate, id=G2gd.wxID_PAWLEYESTIMATE)
     8917            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyUpdate, id=G2gd.wxID_PAWLEYUPDATE)
     8918            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPawleyDelete, id=G2gd.wxID_PAWLEYDELETE)           
     8919            FillPawleyReflectionsGrid()
     8920        elif text == 'Texture':
     8921            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.TextureMenu)
     8922            G2frame.dataFrame.Bind(wx.EVT_MENU, OnTextureRefine, id=G2gd.wxID_REFINETEXTURE)
     8923            G2frame.dataFrame.Bind(wx.EVT_MENU, OnTextureClear, id=G2gd.wxID_CLEARTEXTURE)
     8924            UpdateTexture()                       
     8925            G2plt.PlotTexture(G2frame,data,Start=True)
     8926        elif text == 'Map peaks':
     8927            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.MapPeaksMenu)
     8928            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksMove, id=G2gd.wxID_PEAKSMOVE)
     8929            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksViewPoint, id=G2gd.wxID_PEAKSVIEWPT)
     8930            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDistVP, id=G2gd.wxID_PEAKSDISTVP)
     8931            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDA, id=G2gd.wxID_PEAKSDA)
     8932            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksUnique, id=G2gd.wxID_PEAKSUNIQUE)
     8933            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksDelete, id=G2gd.wxID_PEAKSDELETE)
     8934            G2frame.dataFrame.Bind(wx.EVT_MENU, OnPeaksClear, id=G2gd.wxID_PEAKSCLEAR)
     8935            FillMapPeaksGrid()
     8936            G2plt.PlotStructure(G2frame,data)
     8937           
     8938        else:
     8939            G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.BlankMenu)
     8940        event.Skip()
     8941       
     8942    General = wx.Window(G2frame.dataDisplay)
     8943    G2frame.dataDisplay.AddPage(General,'General')
     8944    G2frame.dataFrame.SetMenuBar(G2frame.dataFrame.DataGeneral)
     8945    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourierMaps, id=G2gd.wxID_FOURCALC)
     8946    G2frame.dataFrame.Bind(wx.EVT_MENU, OnSearchMaps, id=G2gd.wxID_FOURSEARCH)
     8947    G2frame.dataFrame.Bind(wx.EVT_MENU, OnChargeFlip, id=G2gd.wxID_CHARGEFLIP)
     8948    G2frame.dataFrame.Bind(wx.EVT_MENU, OnFourClear, id=G2gd.wxID_FOURCLEAR)
     8949    SetupGeneral()
     8950    GeneralData = data['General']
     8951    UpdateGeneral()
     8952
     8953    DData = wx.ScrolledWindow(G2frame.dataDisplay)
     8954    G2frame.dataDisplay.AddPage(DData,'Data')
     8955    Atoms = G2gd.GSGrid(G2frame.dataDisplay)
     8956    G2frame.dataDisplay.AddPage(Atoms,'Atoms')
     8957    drawOptions = wx.Window(G2frame.dataDisplay)
     8958    G2frame.dataDisplay.AddPage(drawOptions,'Draw Options')
     8959    drawAtoms = G2gd.GSGrid(G2frame.dataDisplay)
     8960    G2frame.dataDisplay.AddPage(drawAtoms,'Draw Atoms')
     8961    Texture = wx.ScrolledWindow(G2frame.dataDisplay)
     8962    G2frame.dataDisplay.AddPage(Texture,'Texture')
     8963    MapPeaks = G2gd.GSGrid(G2frame.dataDisplay)
     8964    G2frame.dataDisplay.AddPage(MapPeaks,'Map peaks')
     8965    G2frame.PawleyRefl = G2gd.GSGrid(G2frame.dataDisplay)
     8966    G2frame.dataDisplay.AddPage(G2frame.PawleyRefl,'Pawley reflections')
     8967           
     8968    G2frame.dataDisplay.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, OnPageChanged)
     8969    G2frame.dataDisplay.SetSelection(oldPage)
     8970>>>>>>> .r762
Note: See TracChangeset for help on using the changeset viewer.