def testSquare(self): vectors = Matrix(helpers.ascomplex(numpy.random.randn( numpy.random.randint(1,10),numpy.random.randint(1,10),2 ))) cov = vectors.H*vectors Xcov = vectors*vectors.H (Xval,Xvec) = numpy.linalg.eigh(Xcov) vec = Xvec.H*vectors self.assertTrue( vec.H*vec == cov )
def patch(self, nstd=2, alpha='auto', slope=0.5, minalpha=0.3, **kwargs): """ :param nstd: :param alpha: :param slope: :param minalpha: :param ** kwargs: get a matplotlib Ellipse patch representing the Mvn, all **kwargs are passed on to the call to matplotlib.patches.Ellipse not surprisingly Ellipse only works for 2d data. the number of standard deviations, 'nstd', is just a multiplier for the eigen values. So the standard deviations are projected, if you want volumetric standard deviations I think you need to multiply by sqrt(ndim) if you don't specify a value for alpha it is set to the exponential of the area, as if it has a fixed amount if ink that is spread over it's area. the 'slope' and 'minalpha' parameters control this auto-alpha: 'slope' controls how quickly the the alpha drops to zero 'minalpha' is used to make sure that very large elipses are not invisible. """ shape = self.dist.shape assert shape[ 1] == 2, 'this method can only produce patches for 2d data' if shape[0] < 2: kwargs = self._kwargs2Marker(**kwargs) coords = self.dist.getX(nstd=nstd) return matplotlib.lines.Line2D(coords[:, 0], coords[:, 1], **kwargs) if alpha == 'auto': alpha = numpy.max( [minalpha, numpy.exp(-slope * mvn.sqrt(self.dist.det()))]) facecolor = kwargs.get('facecolor', None) if facecolor is None: kwargs['alpha'] = alpha else: kwargs['facecolor'] = self._convertAlpha(facecolor, alpha) edgecolor = kwargs.get('edgecolor', None) if edgecolor is not None: kwargs['edgecolor'] = self._convertAlpha(edgecolor, alpha) else: kwargs['alpha'] = alpha #unpack the width and height from the scale matrix wh = nstd * mvn.sqrt(self.dist.var) wh[wh > 1e5] = 1e5 #convert from radius to diameters width, height = 2 * wh #calculate angle angle = 180 / numpy.pi * (numpy.angle( helpers.ascomplex(self.dist.vectors)[0])) #return an Ellipse patch return matplotlib.patches.Ellipse( #with the Mvn's mean at the centre xy=tuple(self.dist.mean.flatten()), #matching width and height width=width, height=height, #and rotation angle pulled from the vectors matrix angle=angle, #while transmitting any kwargs. **kwargs)
def patch(self, nstd=2, alpha='auto', slope=0.5, minalpha=0.3, **kwargs): """ :param nstd: :param alpha: :param slope: :param minalpha: :param ** kwargs: get a matplotlib Ellipse patch representing the Mvn, all **kwargs are passed on to the call to matplotlib.patches.Ellipse not surprisingly Ellipse only works for 2d data. the number of standard deviations, 'nstd', is just a multiplier for the eigen values. So the standard deviations are projected, if you want volumetric standard deviations I think you need to multiply by sqrt(ndim) if you don't specify a value for alpha it is set to the exponential of the area, as if it has a fixed amount if ink that is spread over it's area. the 'slope' and 'minalpha' parameters control this auto-alpha: 'slope' controls how quickly the the alpha drops to zero 'minalpha' is used to make sure that very large elipses are not invisible. """ shape = self.dist.shape assert shape[1] == 2,'this method can only produce patches for 2d data' if shape[0] < 2: kwargs = self._kwargs2Marker(**kwargs) coords = self.dist.getX(nstd = nstd) return matplotlib.lines.Line2D( coords[:, 0], coords[:, 1], **kwargs ) if alpha == 'auto': alpha = numpy.max([ minalpha, numpy.exp(-slope*mvn.sqrt(self.dist.det())) ]) facecolor = kwargs.get('facecolor', None) if facecolor is None: kwargs['alpha'] = alpha else: kwargs['facecolor'] = self._convertAlpha(facecolor,alpha) edgecolor = kwargs.get('edgecolor', None) if edgecolor is not None: kwargs['edgecolor'] = self._convertAlpha(edgecolor,alpha) else: kwargs['alpha'] = alpha #unpack the width and height from the scale matrix wh = nstd*mvn.sqrt(self.dist.var) wh[wh>1e5] = 1e5 #convert from radius to diameters width,height = 2*wh #calculate angle angle = 180/numpy.pi*( numpy.angle(helpers.ascomplex(self.dist.vectors)[0]) ) #return an Ellipse patch return matplotlib.patches.Ellipse( #with the Mvn's mean at the centre xy=tuple(self.dist.mean.flatten()), #matching width and height width=width, height=height, #and rotation angle pulled from the vectors matrix angle=angle, #while transmitting any kwargs. **kwargs )