Пример #1
0
class ternaryfaces_folded:
    def __init__(self, ax, ellabels=['A', 'B', 'C', 'D'], offset=None, nintervals=10., outlinealpha=0.2):
        self.outlinealpha=outlinealpha
        self.nint=1.*nintervals
        self.delta=1./self.nint
        self.ternaryplot=TernaryPlot(ax, outline=False)
        self.ax=ax
        self.offset=offset
        #self.ax.set_xlim(-.1, 2.6)
        #self.ax.set_ylim(-.1, 3.**.5/2+.1)
        self.ax.set_ylim(-.1-3.**.5/4., .1+3.**.5/4.)
        self.cartendpts=numpy.float32([[0, 0], [.5, numpy.sqrt(3.)/2.], [1, 0]])
        self.ellabels=ellabels
        self.scalefcn=lambda ntern:(self.nint-ntern)/self.nint
        shift=0.
        self.shift_ntern=[]
        perminds=[0, 1, 2]
        self.perminds_ntern=[]
        for ntern in range(int(self.nint)+1):
            self.shift_ntern+=[shift]
            shift+=self.delta*1.5+0.5*self.scalefcn(ntern)
            self.perminds_ntern+=[perminds]
            #if ntern%2==0:
            perminds=[perminds[i] for i in [1, 2, 0]]
#            else:
#                perminds=[perminds[i] for i in [1, 0, 2]]
            
        self.ax.set_xlim(-.1, shift+self.delta*1.5+1.*self.scalefcn(ntern)+.1)
                
        self.patch_xyc=lambda x, y, c, **kwargs:self.ax.add_patch(CirclePolygon((x, y),radius=self.delta/3.**.5,resolution=6, color=c, **kwargs))
        self.outline()
        if offset is None:
            self.offset=self.delta
    
    def xy_ntern(self, x, y, ntern):
        if ntern%2==1:
            y=-1.*y+3.**.5/2
        y-=3.**.5/2/2.
        y*=self.scalefcn(ntern)
        x*=self.scalefcn(ntern)
        x+=self.shift_ntern[ntern]
        return x, y
    
    def invert_xy_ntern(self, x, y, ntern):
        x-=self.shift_ntern[ntern]
        x/=self.scalefcn(ntern)
        y/=self.scalefcn(ntern)
        y+=3.**.5/2/2.
        if ntern%2==1:
            y=-1.*y+3.**.5/2
        return x, y
        
    def outline(self):
        for ntern in range(int(self.nint)):
            for i, ep in enumerate(self.cartendpts):
                for ep2 in self.cartendpts[i+1:]:
                    x, y=self.xy_ntern(numpy.array([ep[0], ep2[0]]), numpy.array([ep[1], ep2[1]]), ntern)
                    self.ax.plot(x, y, 'k-', alpha=self.outlinealpha)
        
    def label(self, **kwargs):#takeabs is to avoid a negative sign for ~0 negative compositions
        for count, (va, y) in enumerate(zip(['top','bottom'], [-3.**.5/4.-self.offset, 3.**.5/4.+self.offset])):
            self.ax.text(count*.5, y, self.ellabels[count], ha='center', va=va, **kwargs)
        for i in range(0, int(self.nint)):
            y=(3.**.5/4.)*self.scalefcn(i)+self.offset
            yd=(3.**.5/4.)*self.scalefcn(i)+self.offset*1.5
            if i%2==1:
                va='bottom'
                vad='top'
                yd*=-1
            else:
                va='top'
                y*=-1
                vad='bottom'
            x=self.shift_ntern[i+1]+.5*self.scalefcn(i+1)
            self.ax.text(x, y, self.ellabels[(i+2)%3], ha='center', va=va, **kwargs)
            
            if i==int(self.nint)-1:
                x+=self.scalefcn(i+1)+self.offset
                yd=0.
                vad='center'
                had='left'
            else:
                had='center'
            self.ax.text(x, yd, self.ellabels[3]+(r'$_{%d}$' %(int(round(100*(i+1)*self.delta)))), ha=had, va=vad, **kwargs)
            
    def toCart(self, quatcomps, ntern):
        qc=numpy.array(quatcomps)
        perminds=self.perminds_ntern[ntern]
        x, y=self.ternaryplot.toCart(qc[:, perminds])
        x, y=self.xy_ntern(x, y, ntern)
        return x, y
    
    def scatter(self, quatcomps, c, s='patch', **kwargs):
        if s=='patch':
            patchfcn=lambda x, y, c:self.patch_xyc(x, y, c, **kwargs)
        else:
            patchfcn=None
        quatcomps=numpy.int32(numpy.round(quatcomps*self.nint))
        for ntern in range(int(self.nint)):
            ba=quatcomps[:, -1]==ntern
            self.shellcomps=quatcomps[ba]
            shellc=c[ba]
            self.shellcomps=self.shellcomps[:, :-1]/(self.nint-ntern)
            if len(self.shellcomps)==0:
                continue
            x, y=self.toCart(self.shellcomps, ntern)
            if patchfcn is None:
                self.ax.scatter(x, y, c=shellc, **kwargs)
            else:
                map(patchfcn, x, y, shellc)
        ba=quatcomps[:, -1]==self.nint
        if True in ba:
            self.shellcomps=quatcomps[ba]#only 1 comp but might be duplicated
            shellc=c[ba]
            if patchfcn is None:
                for cv in shellc:
                    self.ax.scatter(self.shift_ntern[-1], 0, c=cv, s=s, **kwargs)
            else:
                [patchfcn(self.shift_ntern[-1], 0, cv) for cv in shellc]
 
    def toComp(self, x, y, skipinds=range(4)):#takes a single x,y coord from the axes and gets the tirangle by trial and error and converts to a,b,c,d/ skipinds must be the same as that used in .scatter()
        c=numpy.zeros(4, dtype='float64')
        for ntern in range(int(self.nint)):
            xi, yi=self.invert_xy_ntern(x, y, ntern)
            abc=self.ternaryplot.toComp([[xi, yi]])
            if numpy.all((abc>=0.)&(abc<=1.)):
                print ntern
                c[self.perminds_ntern[ntern]]=abc*(self.nint-ntern)
                c[-1]=ntern
                c*=self.delta
                return c
        
        xcrit, garb=self.xy_ntern(.5,0,ntern)#in the last ternay plot take the x mid-point. y value deosnt' matter
        if x>xcrit:
            return numpy.float64([0, 0, 0, 1])
        return None
class ternaryfaces_shells:
    def __init__(self,
                 ax,
                 ellabels=['A', 'B', 'C', 'D'],
                 offset=None,
                 nintervals=10.,
                 outlinealpha=0.2,
                 patchscale=1.):
        self.outlinealpha = outlinealpha
        self.nint = 1. * nintervals
        self.delta = 1. / self.nint
        self.ternaryplot = TernaryPlot(ax, outline=False)
        self.ax = ax
        self.ax.set_aspect(1.)
        #self.ax.set_xlim(-.1, 2.6)
        #self.ax.set_ylim(-.1, 3.**.5/2+.1)
        self.ax.set_ylim(-.1 - 3.**.5 / 4., .1 + 3.**.5 / 4.)
        self.cartendpts = numpy.float32([[0, 0], [.5, numpy.sqrt(3.) / 2.],
                                         [1, 0]])
        self.ellabels = ellabels
        self.scalefcn = lambda nshell: (self.nint - 4. * nshell) / self.nint
        shift = 0.
        self.shift_nshell = []
        for nshell in range(int(self.nint // 4) + 1):
            self.shift_nshell += [shift]
            shift += self.delta * 2. + 2. * self.scalefcn(nshell)
        self.ax.set_xlim(-.1, shift + self.delta + 1. * self.scalefcn(nshell))
        #self.fig, self.axis = plt.subplot(nrows=nrows, ncols=ncols, sharex=True, sharey=True)
        #self.nrows = nrows
        #self.ncols = ncols
        self.point_list = []

        self.patch_xyc = lambda x, y, c, **kwargs: self.ax.add_patch(
            CirclePolygon((x, y),
                          radius=patchscale * self.delta / 3.**.5,
                          resolution=6,
                          color=c,
                          **kwargs))
        if outlinealpha > 0:
            self.outline()
        if offset is None:
            self.offset = self.delta
        self.qindsfortern_skipind = [
            [1, 2, 3], [2, 3, 0], [3, 0, 1], [0, 1, 2]
        ]  #sets the order of elements assuming mirror over y for skipA and skipC

    #

    def xy_skipind(self, x, y, skipind, nshell):

        if skipind % 2 == 0:
            y = -1. * y + 3.**.5 / 2
        y -= 3.**.5 / 2 / 2.
        y *= self.scalefcn(nshell)
        x += ([0.5, 1, 1.5, 0.][skipind])
        x *= self.scalefcn(nshell)
        x += self.shift_nshell[nshell]
        return x, y

    def invert_xy_skipind(self, x, y, skipind, nshell):
        x -= self.shift_nshell[nshell]
        x /= self.scalefcn(nshell)
        x -= ([0.5, 1, 1.5, 0.][skipind])
        y /= self.scalefcn(nshell)
        y += 3.**.5 / 2 / 2.
        if skipind % 2 == 0:
            y = -1. * y + 3.**.5 / 2
        return x, y

    def outline(self, **kwargs):
        for nshell in range(int(self.nint // 4) + int(self.nint % 4 > 0)):
            for skipind in range(4):
                skipfirstline = skipind != 3
                for i, ep in enumerate(self.cartendpts):
                    for ep2 in self.cartendpts[i + 1:]:
                        if skipfirstline:
                            skipfirstline = False
                            continue
                        x, y = self.xy_skipind(numpy.array([ep[0], ep2[0]]),
                                               numpy.array([ep[1], ep2[1]]),
                                               skipind, nshell)
                        self.ax.plot(x,
                                     y,
                                     'k-',
                                     alpha=self.outlinealpha,
                                     **kwargs)

    def label(
        self,
        onlyterns=False,
        allelements=False,
        primeelements=False,
        **kwargs
    ):  #takeabs is to avoid a negative sign for ~0 negative compositions
        for va, xst, y, inds in zip(
            ['top', 'bottom'], [0, .5],
            [-3.**.5 / 4. - self.offset, 3.**.5 / 4. + self.offset],
            [[0, 2, 0], [1, 3, 1]]):
            for count, i in enumerate(inds):
                self.ax.text(xst + count * 1.,
                             y,
                             self.ellabels[i],
                             ha='center',
                             va=va,
                             **kwargs)
        if onlyterns:
            return
        for nshell in range(1, int(self.nint // 4) + int(self.nint % 4 > 0)):
            for va, xst, y, inds in zip(['top', 'bottom'], [0, .5], [
                    -3.**.5 / 4. * self.scalefcn(nshell) - self.offset,
                    3.**.5 / 4. * self.scalefcn(nshell) + self.offset
            ], [[2, 0], [3, 1]]):
                for count, i in enumerate(inds):
                    l = self.ellabels[i]
                    if primeelements:
                        l += "$'$" * nshell
                    else:
                        l += (r'$_{%d}$' %
                              int(round(100 * (1. - 3 * nshell * self.delta))))
                    x = (xst + (count + 1) * 1.
                         ) * self.scalefcn(nshell) + self.shift_nshell[nshell]
                    if allelements:
                        temp = copy.copy(self.ellabels)
                        temp.pop(i)
                        l += ''.join([
                            el + (r'$_{%d}$' %
                                  int(round(100 * (nshell * self.delta))))
                            for el in temp
                        ])
                    self.ax.text(x, y, l, ha='center', va=va, **kwargs)

    def toCart(
        self,
        quatcomps,
        skipinds=range(4),
        nshell=0
    ):  #binary and ternary lines need to be plotted multiple times so returns  set of (inds,x,y)
        qc = numpy.array(quatcomps)
        #qc=qc[(qc==0.).sum(axis=1)>0]
        #        x=numpy.empty(len(qc), dtype='float32')
        #        y=numpy.empty(len(qc), dtype='float32')

        inds_x_y = []
        for si in skipinds:
            inds = numpy.where(qc[:, si] == 0.)[0]
            if len(inds) == 0:
                continue
            xt, yt = self.ternaryplot.toCart(
                qc[inds][:, self.qindsfortern_skipind[si]])
            x, y = self.xy_skipind(xt, yt, si, nshell)
            inds_x_y += [(inds, x, y)]
        return inds_x_y

    def scatter(self, quatcomps, c, skipinds=range(4), s='patch', **kwargs):
        if s == 'patch':
            patchfcn = lambda x, y, c: self.patch_xyc(x, y, c, **kwargs)
        else:
            patchfcn = None
        quatcomps = numpy.int32(numpy.round(quatcomps * self.nint))
        for nshell in range(int(self.nint // 4) + int(self.nint % 4 > 0)):
            ba = ((quatcomps == nshell).sum(axis=1, dtype='int32') > 0) & (
                (quatcomps >= nshell).prod(axis=1, dtype='int32') > 0)
            self.shellcomps = quatcomps[ba]
            shellc = c[ba]
            self.shellcomps = (self.shellcomps - nshell) / (self.nint -
                                                            4. * nshell)
            inds_x_y = self.toCart(self.shellcomps,
                                   skipinds=skipinds,
                                   nshell=nshell)
            for inds, x, y in inds_x_y:
                if patchfcn is None:
                    #self.ax.scatter(x, y, c=shellc[inds], s=s, **kwargs)
                    self.point_list.append(
                        self.ax.scatter(x,
                                        y,
                                        c=shellc[inds],
                                        s=s,
                                        picker=True,
                                        **kwargs))
                else:
                    map(patchfcn, x, y, shellc[inds])
        if self.nint % 4 == 0:  #single point with no frame
            ba = (quatcomps == self.nint // 4).prod(axis=1, dtype='int32') > 0
            if True in ba:
                self.shellcomps = quatcomps[
                    ba]  #only 1 comp but might be duplicated
                shellc = c[ba]

                if patchfcn is None:
                    for cv in shellc:
                        #self.ax.scatter(self.shift_nshell[-1], 0, c=cv, s=s, **kwargs)
                        self.point_list.append(
                            self.ax.scatter(self.shift_nshell[-1],
                                            0,
                                            c=cv,
                                            s=s,
                                            picker=True,
                                            **kwargs))
                else:
                    [patchfcn(self.shift_nshell[-1], 0, cv) for cv in shellc]
        #Returns a list with all the points in the scatterplot
        return self.point_list

    def quatscatter(self,
                    quatcomps,
                    c,
                    skipinds=range(4),
                    azim=-60,
                    elev=30,
                    alphaall=.2,
                    alphashell=1.,
                    fontsize=14,
                    outline=True,
                    **kwargs):
        numsubs = int(self.nint // 4) + 1
        quatcomps = numpy.int32(numpy.round(quatcomps * self.nint))
        for nshell in range(int(self.nint // 4) + int(self.nint % 4 > 0)):
            ba = ((quatcomps == nshell).sum(axis=1, dtype='int32') > 0) & (
                (quatcomps >= nshell).prod(axis=1, dtype='int32') > 0)
            shellcomps = quatcomps[ba]
            shellc = c[ba]

            q = QuaternaryPlot((1, numsubs, nshell + 1), outline=outline)
            if alphaall > 0:
                q.scatter(quatcomps * 1. / self.nint,
                          c=c,
                          alpha=alphaall,
                          **kwargs)
            if alphashell > 0:
                q.scatter(shellcomps * 1. / self.nint,
                          c=shellc,
                          alpha=alphashell,
                          **kwargs)
            if fontsize > 0:
                q.label(ha='center', va='center', fontsize=fontsize)
            q.set_projection(azim=azim, elev=elev)

        if self.nint % 4 == 0:  #single point with no frame
            ba = (quatcomps == self.nint // 4).prod(axis=1, dtype='int32') > 0
            if True in ba:
                shellcomps = quatcomps[
                    ba]  #only 1 comp but might be duplicated
                shellc = c[ba]
                q = QuaternaryPlot((1, numsubs, numsubs), outline=outline)
                q.scatter(quatcomps * 1. / self.nint,
                          c=c,
                          alpha=alphaall,
                          **kwargs)
                q.scatter(shellcomps * 1. / self.nint,
                          c=shellc,
                          alpha=alphashell,
                          **kwargs)
                if fontsize > 0:
                    q.label(ha='center', va='center', fontsize=fontsize)
                q.set_projection(azim=azim, elev=elev)

    def quatplot3D(self,
                   quatcomps,
                   c,
                   skipinds=range(4),
                   azim=-60,
                   elev=30,
                   alphaall=.2,
                   alphashell=1.,
                   fontsize=14,
                   outline=True,
                   **kwargs):
        numsubs = int(self.nint // 4) + 1
        quatcomps = numpy.int32(numpy.round(quatcomps * self.nint))
        for nshell in range(int(self.nint // 4) + int(self.nint % 4 > 0)):
            ba = ((quatcomps == nshell).sum(axis=1, dtype='int32') > 0) & (
                (quatcomps >= nshell).prod(axis=1, dtype='int32') > 0)
            shellcomps = quatcomps[ba]
            shellc = c[ba]

            q = QuaternaryPlot((1, numsubs, nshell + 1), outline=outline)
            if alphaall > 0:
                q.plot3D(quatcomps * 1. / self.nint,
                         c,
                         alpha=alphaall,
                         **kwargs)
            if alphashell > 0:
                q.plot3D(shellcomps * 1. / self.nint,
                         shellc,
                         alpha=alphashell,
                         **kwargs)
            if fontsize > 0:
                q.label(ha='center', va='center', fontsize=fontsize)
            q.set_projection(azim=azim, elev=elev)

        if self.nint % 4 == 0:  #single point with no frame
            ba = (quatcomps == self.nint // 4).prod(axis=1, dtype='int32') > 0
            if True in ba:
                shellcomps = quatcomps[
                    ba]  #only 1 comp but might be duplicated
                shellc = c[ba]
                q = QuaternaryPlot((1, numsubs, numsubs), outline=outline)
                q.plot3D(quatcomps * 1. / self.nint,
                         c,
                         alpha=alphaall,
                         **kwargs)
                q.plot3D(shellcomps * 1. / self.nint,
                         shellc,
                         alpha=alphashell,
                         **kwargs)
                if fontsize > 0:
                    q.label(ha='center', va='center', fontsize=fontsize)
                q.set_projection(azim=azim, elev=elev)

    def toComp(
        self, x, y, skipinds=range(4)
    ):  #takes a single x,y coord from the axes and gets the tirangle by trial and error and converts to a,b,c,d/ skipinds must be the same as that used in .scatter()
        c = numpy.zeros(4, dtype='float64')
        for nshell in range(int(self.nint // 4) + int(self.nint % 4 > 0)):
            for si in skipinds:
                xi, yi = self.invert_xy_skipind(x, y, si, nshell)
                abc = self.ternaryplot.toComp([[xi, yi]])
                if numpy.all((abc >= 0.) & (abc <= 1.)):
                    c[self.qindsfortern_skipind[si]] = numpy.round(
                        (abc * (self.nint - 4. * nshell) + nshell))
                    c[si] = nshell
                    c *= self.delta
                    return c
        if self.nint % 4 == 0:  #if there is an equi-atomic  single point outside the triangles, then count it as clicked if outside triagnels with x bigger than middle of the last triangle,
            xcrit, garb = self.xy_skipind(
                .5, 0, si, nshell
            )  #in the last ternay plot take the x mid-point. y value deosnt' matter
            if x > xcrit:
                return numpy.ones(4, dtype='float64') / 4.
        return None
Y = cmp.values / 100

#define subset Xsubset, Ysubset that is fed to the GPR model
#and Xfit where fitting is done

x = np.linspace(np.min(X[:, 0]), np.max(X[:, 0]), 50)
y = np.linspace(np.min(X[:, 1]), np.max(X[:, 1]), 50)
xv, yv = np.meshgrid(x, y)
Xfit_ = np.array([xv.flatten(), yv.flatten()])
idx = []
for i in range(len(Xfit_.T)):
    if is_in_hull(Xfit_[:, i], X):
        idx.append(i)

Xfit = Xfit_[:, idx]

#%% Predict using gaussian process regressor
kernel = RBF([1.0]) + WhiteKernel(noise_level=0.0336)
gpr = GaussianProcessRegressor(kernel=kernel)
gpr.fit(Xsubset, Ysubset)
Ygpr, Ystd = gpr.predict(Xfit.T, return_std=True)

#%% plot predictions
ax = pylab.gca()
stp = TernaryPlot(ax, ellabels=cmp.columns)
x, y = stp.toCart(Ygpr)
plt.scatter(x, y, s=10, c=Ystd)
stp.label(fontsize=16)
plt.colorbar()
plt.show()
class ternaryfaces_shells:
    def __init__(self, ax, ellabels=['A', 'B', 'C', 'D'], offset=None, nintervals=10., outlinealpha=0.2, patchscale=1.):
        self.outlinealpha=outlinealpha
        self.nint=1.*nintervals
        self.delta=1./self.nint
        self.ternaryplot=TernaryPlot(ax, outline=False)
        self.ax=ax
        self.ax.set_aspect(1.)
        #self.ax.set_xlim(-.1, 2.6)
        #self.ax.set_ylim(-.1, 3.**.5/2+.1)
        self.ax.set_ylim(-.1-3.**.5/4., .1+3.**.5/4.)
        self.cartendpts=numpy.float32([[0, 0], [.5, numpy.sqrt(3.)/2.], [1, 0]])
        self.ellabels=ellabels
        self.scalefcn=lambda nshell:(self.nint-4.*nshell)/self.nint
        shift=0.
        self.shift_nshell=[]
        for nshell in range(int(self.nint//4)+1):
            self.shift_nshell+=[shift]
            shift+=self.delta*2.+2.*self.scalefcn(nshell)
        self.ax.set_xlim(-.1, shift+self.delta+1.*self.scalefcn(nshell))
        
        self.patch_xyc=lambda x, y, c, **kwargs:self.ax.add_patch(CirclePolygon((x, y),radius=patchscale*self.delta/3.**.5,resolution=6, color=c, **kwargs))
        if outlinealpha>0:
            self.outline()
        if offset is None:
            self.offset=self.delta
        self.qindsfortern_skipind=[[1, 2, 3], [2, 3, 0], [3, 0, 1], [0, 1, 2]]#sets the order of elements assuming mirror over y for skipA and skipC
    def xy_skipind(self, x, y, skipind, nshell):
        
        if skipind%2==0:
            y=-1.*y+3.**.5/2
        y-=3.**.5/2/2.
        y*=self.scalefcn(nshell)
        x+=([0.5, 1, 1.5, 0.][skipind])
        x*=self.scalefcn(nshell)
        x+=self.shift_nshell[nshell]
        return x, y
    
    def invert_xy_skipind(self, x, y, skipind, nshell):
        x-=self.shift_nshell[nshell]
        x/=self.scalefcn(nshell)
        x-=([0.5, 1, 1.5, 0.][skipind])
        y/=self.scalefcn(nshell)
        y+=3.**.5/2/2.
        if skipind%2==0:
            y=-1.*y+3.**.5/2
        return x, y
        
    def outline(self, **kwargs):
        for nshell in range(int(self.nint//4)+int(self.nint%4>0)):
            for skipind in range(4):
                skipfirstline=skipind!=3
                for i, ep in enumerate(self.cartendpts):
                    for ep2 in self.cartendpts[i+1:]:
                        if skipfirstline:
                            skipfirstline=False
                            continue
                        x, y=self.xy_skipind(numpy.array([ep[0], ep2[0]]), numpy.array([ep[1], ep2[1]]), skipind, nshell)
                        self.ax.plot(x, y, 'k-', alpha=self.outlinealpha, **kwargs)
        
    def label(self, onlyterns=False, allelements=False, primeelements=False, **kwargs):#takeabs is to avoid a negative sign for ~0 negative compositions
        for va, xst, y, inds in zip(['top', 'bottom'], [0, .5], [-3.**.5/4.-self.offset, 3.**.5/4.+self.offset], [[0, 2, 0], [1, 3, 1]]):
            for count, i in enumerate(inds):
                self.ax.text(xst+count*1., y, self.ellabels[i], ha='center', va=va, **kwargs)
        if onlyterns:
            return
        for nshell in range(1, int(self.nint//4)+int(self.nint%4>0)):
            for va, xst, y, inds in zip(['top', 'bottom'], [0, .5], [-3.**.5/4.*self.scalefcn(nshell)-self.offset, 3.**.5/4.*self.scalefcn(nshell)+self.offset], [[2, 0], [3, 1]]):
                for count, i in enumerate(inds):
                    l=self.ellabels[i]
                    if primeelements:
                        l+="$'$"*nshell
                    else:
                        l+=(r'$_{%d}$' %int(round(100*(1.-3*nshell*self.delta))))
                    x=(xst+(count+1)*1.)*self.scalefcn(nshell)+self.shift_nshell[nshell]
                    if allelements:
                        temp=copy.copy(self.ellabels)
                        temp.pop(i)
                        l+=''.join([el+(r'$_{%d}$' %int(round(100*(nshell*self.delta)))) for el in temp])
                    self.ax.text(x, y, l, ha='center', va=va, **kwargs)
    
    def toCart(self, quatcomps, skipinds=range(4), nshell=0):#binary and ternary lines need to be plotted multiple times so returns  set of (inds,x,y)
        qc=numpy.array(quatcomps)
        #qc=qc[(qc==0.).sum(axis=1)>0]
#        x=numpy.empty(len(qc), dtype='float32')
#        y=numpy.empty(len(qc), dtype='float32')
        
        inds_x_y=[]
        for si in skipinds:
            inds=numpy.where(qc[:, si]==0.)[0]
            if len(inds)==0:
                continue
            xt, yt=self.ternaryplot.toCart(qc[inds][:, self.qindsfortern_skipind[si]])
            x, y=self.xy_skipind(xt, yt, si, nshell)
            inds_x_y+=[(inds, x, y)]
        return inds_x_y
    
    def scatter(self, quatcomps, c, skipinds=range(4), s='patch', **kwargs):
        if s=='patch':
            patchfcn=lambda x, y, c:self.patch_xyc(x, y, c, **kwargs)
        else:
            patchfcn=None
        quatcomps=numpy.int32(numpy.round(quatcomps*self.nint))
        for nshell in range(int(self.nint//4)+int(self.nint%4>0)):
            ba=((quatcomps==nshell).sum(axis=1, dtype='int32')>0)&((quatcomps>=nshell).prod(axis=1, dtype='int32')>0)
            self.shellcomps=quatcomps[ba]
            shellc=c[ba]
            self.shellcomps=(self.shellcomps-nshell)/(self.nint-4.*nshell)
            inds_x_y=self.toCart(self.shellcomps, skipinds=skipinds, nshell=nshell)
            for inds, x, y in inds_x_y:
                if patchfcn is None:
                    self.ax.scatter(x, y, c=shellc[inds], s=s, **kwargs)
                else:
                    map(patchfcn, x, y, shellc[inds])
        if self.nint%4==0: #single point with no frame
            ba=(quatcomps==self.nint//4).prod(axis=1, dtype='int32')>0
            if True in ba:
                self.shellcomps=quatcomps[ba]#only 1 comp but might be duplicated
                shellc=c[ba]
                
                if patchfcn is None:
                    for cv in shellc:
                        self.ax.scatter(self.shift_nshell[-1], 0, c=cv, s=s, **kwargs)
                else:
                    [patchfcn(self.shift_nshell[-1], 0, cv) for cv in shellc]
                    
    def quatscatter(self, quatcomps, c, skipinds=range(4), azim=-60, elev=30, alphaall=.2, alphashell=1., fontsize=14, outline=True,  **kwargs):
        numsubs=int(self.nint//4)+1
        quatcomps=numpy.int32(numpy.round(quatcomps*self.nint))
        for nshell in range(int(self.nint//4)+int(self.nint%4>0)):
            ba=((quatcomps==nshell).sum(axis=1, dtype='int32')>0)&((quatcomps>=nshell).prod(axis=1, dtype='int32')>0)
            shellcomps=quatcomps[ba]
            shellc=c[ba]
            
            q=QuaternaryPlot((1, numsubs, nshell+1), outline=outline)
            if alphaall>0:
                q.scatter(quatcomps*1./self.nint,c=c, alpha=alphaall, **kwargs)
            if alphashell>0:
                q.scatter(shellcomps*1./self.nint,c=shellc, alpha=alphashell, **kwargs)
            if fontsize>0:
                q.label(ha='center', va='center', fontsize=fontsize)
            q.set_projection(azim=azim, elev=elev)

        if self.nint%4==0: #single point with no frame
            ba=(quatcomps==self.nint//4).prod(axis=1, dtype='int32')>0
            if True in ba:
                shellcomps=quatcomps[ba]#only 1 comp but might be duplicated
                shellc=c[ba]
                q=QuaternaryPlot((1, numsubs, numsubs), outline=outline)
                q.scatter(quatcomps*1./self.nint,c=c, alpha=alphaall, **kwargs)
                q.scatter(shellcomps*1./self.nint,c=shellc, alpha=alphashell, **kwargs)
                if fontsize>0:
                    q.label(ha='center', va='center', fontsize=fontsize)
                q.set_projection(azim=azim, elev=elev)
    def quatplot3D(self, quatcomps, c, skipinds=range(4), azim=-60, elev=30, alphaall=.2, alphashell=1., fontsize=14, outline=True,  **kwargs):
        numsubs=int(self.nint//4)+1
        quatcomps=numpy.int32(numpy.round(quatcomps*self.nint))
        for nshell in range(int(self.nint//4)+int(self.nint%4>0)):
            ba=((quatcomps==nshell).sum(axis=1, dtype='int32')>0)&((quatcomps>=nshell).prod(axis=1, dtype='int32')>0)
            shellcomps=quatcomps[ba]
            shellc=c[ba]
            
            q=QuaternaryPlot((1, numsubs, nshell+1), outline=outline)
            if alphaall>0:
                q.plot3D(quatcomps*1./self.nint,c, alpha=alphaall, **kwargs)
            if alphashell>0:
                q.plot3D(shellcomps*1./self.nint,shellc, alpha=alphashell, **kwargs)
            if fontsize>0:
                q.label(ha='center', va='center', fontsize=fontsize)
            q.set_projection(azim=azim, elev=elev)

        if self.nint%4==0: #single point with no frame
            ba=(quatcomps==self.nint//4).prod(axis=1, dtype='int32')>0
            if True in ba:
                shellcomps=quatcomps[ba]#only 1 comp but might be duplicated
                shellc=c[ba]
                q=QuaternaryPlot((1, numsubs, numsubs), outline=outline)
                q.plot3D(quatcomps*1./self.nint,c, alpha=alphaall, **kwargs)
                q.plot3D(shellcomps*1./self.nint,shellc, alpha=alphashell, **kwargs)
                if fontsize>0:
                    q.label(ha='center', va='center', fontsize=fontsize)
                q.set_projection(azim=azim, elev=elev)
                
    def toComp(self, x, y, skipinds=range(4)):#takes a single x,y coord from the axes and gets the tirangle by trial and error and converts to a,b,c,d/ skipinds must be the same as that used in .scatter()
        c=numpy.zeros(4, dtype='float64')
        for nshell in range(int(self.nint//4)+int(self.nint%4>0)):
            for si in skipinds:
                xi, yi=self.invert_xy_skipind(x, y, si, nshell)
                abc=self.ternaryplot.toComp([[xi, yi]])
                if numpy.all((abc>=0.)&(abc<=1.)):
                    c[self.qindsfortern_skipind[si]]=numpy.round((abc*(self.nint-4.*nshell)+nshell))
                    c[si]=nshell
                    c*=self.delta
                    return c
        if self.nint%4==0:#if there is an equi-atomic  single point outside the triangles, then count it as clicked if outside triagnels with x bigger than middle of the last triangle,
            xcrit, garb=self.xy_skipind(.5,0,si, nshell)#in the last ternay plot take the x mid-point. y value deosnt' matter
            if x>xcrit:
                return numpy.ones(4, dtype='float64')/4.
        return None
Пример #5
0
class ternaryfaces:
    def __init__(self,
                 ax,
                 ellabels=['A', 'B', 'C', 'D'],
                 offset=None,
                 nintervals=10.,
                 outlinealpha=0.4):
        self.outlinealpha = outlinealpha
        self.ternaryplot = TernaryPlot(ax, outline=False)
        self.ax = ax

        self.ax.set_xlim(-.1, 2.6)
        self.ax.set_ylim(-.1, 3.**.5 / 2 + .1)
        self.cartendpts = numpy.float32([[0, 0], [.5, numpy.sqrt(3.) / 2.],
                                         [1, 0]])
        self.ellabels = ellabels
        self.outline()
        self.nint = 1. * nintervals
        self.delta = 1. / self.nint
        self.patch_xyc = lambda x, y, c, **kwargs: self.ax.add_patch(
            CirclePolygon((x, y),
                          radius=self.delta / 3.**.5,
                          resolution=6,
                          color=c,
                          **kwargs))
        if offset is None:
            self.offset = self.delta
        self.qindsfortern_skipind = [
            [1, 2, 3], [2, 3, 0], [3, 0, 1], [0, 1, 2]
        ]  #sets the order of elements assuming mirror over y for skipA and skipC

    def xy_skipind(self, x, y, skipind):
        x += ([0.5, 1, 1.5, 0.][skipind])
        if skipind % 2 == 0:
            y = -1. * y + 3.**.5 / 2
        return x, y

    def invert_xy_skipind(self, x, y, skipind):
        x -= ([0.5, 1, 1.5, 0.][skipind])
        if skipind % 2 == 0:
            y = -1. * y + 3.**.5 / 2
        return x, y

    def outline(self):
        for skipind in range(4):
            skipfirstline = skipind != 3
            for i, ep in enumerate(self.cartendpts):
                for ep2 in self.cartendpts[i + 1:]:
                    if skipfirstline:
                        skipfirstline = False
                        continue
                    x, y = self.xy_skipind(numpy.array([ep[0], ep2[0]]),
                                           numpy.array([ep[1], ep2[1]]),
                                           skipind)
                    self.ax.plot(x, y, 'k-', alpha=self.outlinealpha)

    def label(
        self, **kwargs
    ):  #takeabs is to avoid a negative sign for ~0 negative compositions
        for va, xst, y, inds in zip(['top', 'bottom'], [0, .5],
                                    [-self.offset, 3.**.5 / 2 + self.offset],
                                    [[0, 2, 0], [1, 3, 1]]):
            for count, i in enumerate(inds):
                self.ax.text(xst + count * 1.,
                             y,
                             self.ellabels[i],
                             ha='center',
                             va=va,
                             **kwargs)

    def toCart(
        self, quatcomps, skipinds=range(4)
    ):  #binary and ternary lines need to be plotted multiple times so returns  set of (inds,x,y)
        qc = numpy.array(quatcomps)
        #qc=qc[(qc==0.).sum(axis=1)>0]
        #        x=numpy.empty(len(qc), dtype='float32')
        #        y=numpy.empty(len(qc), dtype='float32')

        inds_x_y = []
        for si in skipinds:
            inds = numpy.where(qc[:, si] == 0.)[0]
            if len(inds) == 0:
                continue
            xt, yt = self.ternaryplot.toCart(
                qc[inds][:, self.qindsfortern_skipind[si]])
            x, y = self.xy_skipind(xt, yt, si)
            inds_x_y += [(inds, x, y)]
        return inds_x_y

    def scatter(self, quatcomps, c, skipinds=range(4), s='patch', **kwargs):
        if s == 'patch':
            patchfcn = lambda x, y, c: self.patch_xyc(x, y, c, **kwargs)
        else:
            patchfcn = None
        inds_x_y = self.toCart(quatcomps, skipinds=skipinds)
        for inds, x, y in inds_x_y:
            if patchfcn is None:
                self.ax.scatter(x, y, c=c[inds], s=s, **kwargs)
            else:
                map(patchfcn, x, y, c[inds])

    def toComp(
        self, x, y, skipinds=range(4)
    ):  #takes a single x,y coord from the axes and gets the tirangle by trial and error and converts to a,b,c,d/ skipinds must be the same as that used in .scatter()
        c = numpy.zeros(4, dtype='float64')
        for si in skipinds:
            xi, yi = self.invert_xy_skipind(x, y, si)
            abc = self.ternaryplot.toComp([[xi, yi]])
            if numpy.all((abc >= 0.) & (abc <= 1.)):
                c[self.qindsfortern_skipind[si]] = abc
                return c
        return None
z=numpy.zeros(3, dtype='float64')
ctr2=numpy.ones(3, dtype='float64')/2.
endmembers=[]
lineendpairs=[]
#iterate over 4 end members and draw a line from there to center of opposing face, e.g. (0,.33,.33,.33)
for i in range(3):
    a=copy.copy(z)
    a[i]=1.
    b=copy.copy(ctr2)
    b[i]=0.
    q.line(a, b, fmt='b-')
    q.scatter([b], c='b', s=15)
    endmembers+=[a]
    lineendpairs+=[[a, b]]
#convert the end members and pairs of endpts to cartesian
xy_lineendpairs=[numpy.array(q.toCart(ls)).T for ls in lineendpairs]
xy_endmembers=numpy.array(q.toCart(endmembers)).T

#choose the composition of a phase and draw the trivial phase field lines
phcomp=numpy.array([.5, .3, .2])
q.scatter([phcomp], c='r', s=20)
for i in range(3):
    a=copy.copy(z)
    a[i]=1.
    q.line(a, phcomp, fmt='r-')

# iterate over all 4 phase field triangular boundaries (triangle defined by 3 points, the phase p0 and 2 end members p1,p2) and all 4 composition lines. find intersections
p0=numpy.array(q.toCart([phcomp])).T[0]
xy_intr_dlist=[]
for countends, (p1) in enumerate(xy_endmembers):
    for countlines, (l0, l1) in enumerate(xy_lineendpairs):
Пример #7
0
z = numpy.zeros(3, dtype='float64')
ctr2 = numpy.ones(3, dtype='float64') / 2.
endmembers = []
lineendpairs = []
#iterate over 4 end members and draw a line from there to center of opposing face, e.g. (0,.33,.33,.33)
for i in range(3):
    a = copy.copy(z)
    a[i] = 1.
    b = copy.copy(ctr2)
    b[i] = 0.
    q.line(a, b, fmt='b-')
    q.scatter([b], c='b', s=15)
    endmembers += [a]
    lineendpairs += [[a, b]]
#convert the end members and pairs of endpts to cartesian
xy_lineendpairs = [numpy.array(q.toCart(ls)).T for ls in lineendpairs]
xy_endmembers = numpy.array(q.toCart(endmembers)).T

#choose the composition of a phase and draw the trivial phase field lines
phcomp = numpy.array([.5, .3, .2])
q.scatter([phcomp], c='r', s=20)
for i in range(3):
    a = copy.copy(z)
    a[i] = 1.
    q.line(a, phcomp, fmt='r-')

# iterate over all 4 phase field triangular boundaries (triangle defined by 3 points, the phase p0 and 2 end members p1,p2) and all 4 composition lines. find intersections
p0 = numpy.array(q.toCart([phcomp])).T[0]
xy_intr_dlist = []
for countends, (p1) in enumerate(xy_endmembers):
    for countlines, (l0, l1) in enumerate(xy_lineendpairs):
class ternaryfaces:
    def __init__(self, ax, ellabels=['A', 'B', 'C', 'D'], offset=None, nintervals=10., outlinealpha=0.4):
        self.outlinealpha=outlinealpha
        self.ternaryplot=TernaryPlot(ax, outline=False)
        self.ax=ax
        
        self.ax.set_xlim(-.1, 2.6)
        self.ax.set_ylim(-.1, 3.**.5/2+.1)
        self.cartendpts=numpy.float32([[0, 0], [.5, numpy.sqrt(3.)/2.], [1, 0]])
        self.ellabels=ellabels
        self.outline()
        self.nint=1.*nintervals
        self.delta=1./self.nint
        self.patch_xyc=lambda x, y, c, **kwargs:self.ax.add_patch(CirclePolygon((x, y),radius=self.delta/3.**.5,resolution=6, color=c, **kwargs))
        if offset is None:
            self.offset=self.delta
        self.qindsfortern_skipind=[[1, 2, 3], [2, 3, 0], [3, 0, 1], [0, 1, 2]]#sets the order of elements assuming mirror over y for skipA and skipC
        
    def xy_skipind(self, x, y, skipind):
        x+=([0.5, 1, 1.5, 0.][skipind])
        if skipind%2==0:
            y=-1.*y+3.**.5/2
        return x, y
    
    def invert_xy_skipind(self, x, y, skipind):
        x-=([0.5, 1, 1.5, 0.][skipind])
        if skipind%2==0:
            y=-1.*y+3.**.5/2
        return x, y
        
    def outline(self):
        for skipind in range(4):
            skipfirstline=skipind!=3
            for i, ep in enumerate(self.cartendpts):
                for ep2 in self.cartendpts[i+1:]:
                    if skipfirstline:
                        skipfirstline=False
                        continue
                    x, y=self.xy_skipind(numpy.array([ep[0], ep2[0]]), numpy.array([ep[1], ep2[1]]), skipind)
                    self.ax.plot(x, y, 'k-', alpha=self.outlinealpha)
        
    def label(self, **kwargs):#takeabs is to avoid a negative sign for ~0 negative compositions
        for va, xst, y, inds in zip(['top', 'bottom'], [0, .5], [-self.offset, 3.**.5/2+self.offset], [[0, 2, 0], [1, 3, 1]]):
            for count, i in enumerate(inds):
                self.ax.text(xst+count*1., y, self.ellabels[i], ha='center', va=va, **kwargs)
    
    def toCart(self, quatcomps, skipinds=range(4)):#binary and ternary lines need to be plotted multiple times so returns  set of (inds,x,y)
        qc=numpy.array(quatcomps)
        #qc=qc[(qc==0.).sum(axis=1)>0]
#        x=numpy.empty(len(qc), dtype='float32')
#        y=numpy.empty(len(qc), dtype='float32')
        
        inds_x_y=[]
        for si in skipinds:
            inds=numpy.where(qc[:, si]==0.)[0]
            if len(inds)==0:
                continue
            xt, yt=self.ternaryplot.toCart(qc[inds][:, self.qindsfortern_skipind[si]])
            x, y=self.xy_skipind(xt, yt, si)
            inds_x_y+=[(inds, x, y)]
        return inds_x_y
    
    def scatter(self, quatcomps, c, skipinds=range(4), s='patch', **kwargs):
        if s=='patch':
            patchfcn=lambda x, y, c:self.patch_xyc(x, y, c, **kwargs)
        else:
            patchfcn=None
        inds_x_y=self.toCart(quatcomps, skipinds=skipinds)
        for inds, x, y in inds_x_y:
            if patchfcn is None:
                self.ax.scatter(x, y, c=c[inds], s=s, **kwargs)
            else:
                map(patchfcn, x, y, c[inds])
                
    def toComp(self, x, y, skipinds=range(4)):#takes a single x,y coord from the axes and gets the tirangle by trial and error and converts to a,b,c,d/ skipinds must be the same as that used in .scatter()
        c=numpy.zeros(4, dtype='float64')
        for si in skipinds:
            xi, yi=self.invert_xy_skipind(x, y, si)
            abc=self.ternaryplot.toComp([[xi, yi]])
            if numpy.all((abc>=0.)&(abc<=1.)):
                c[self.qindsfortern_skipind[si]]=abc
                return c
        return None