def _set_clip(self): if not self._useDataClipping: return #self._logcache = None try: self._xmin, self._xmax except AttributeError: indx = arange(len(self._x)) else: if not hasattr(self, '_xsorted'): self._xsorted = self._is_sorted(self._x) if len(self._x) == 1: indx = [0] elif self._xsorted: # for really long signals, if we know they are sorted # on x we can save a lot of time using search sorted # since the alternative approach requires 3 O(len(x) ) ops indMin, indMax = searchsorted(self._x, array([self._xmin, self._xmax])) indMin = max(0, indMin - 1) indMax = min(indMax + 1, len(self._x)) skip = 0 if self._lod: # if level of detail is on, decimate the data # based on pixel width raise NotImplementedError('LOD deprecated') l, b, w, h = self.get_window_extent().get_bounds() skip = int((indMax - indMin) / w) if skip > 0: indx = arange(indMin, indMax, skip) else: indx = arange(indMin, indMax) else: indx = nonzero( logical_and(self._x >= self._xmin, self._x <= self._xmax)) self._xc = take(self._x, indx) self._yc = take(self._y, indx) # y data clipping for connected lines can introduce horizontal # line artifacts near the clip region. If you really need y # clipping for efficiency, consider using plot(y,x) instead. if (self._yc.shape == self._xc.shape and self._linestyle is None): try: self._ymin, self._ymax except AttributeError: indy = arange(len(self._yc)) else: indy = nonzero( logical_and(self._yc >= self._ymin, self._yc <= self._ymax)) else: indy = arange(len(self._yc)) self._xc = take(self._xc, indy) self._yc = take(self._yc, indy)
def _set_clip(self): if not self._useDataClipping: return # self._logcache = None try: self._xmin, self._xmax except AttributeError: indx = arange(len(self._x)) else: if not hasattr(self, "_xsorted"): self._xsorted = self._is_sorted(self._x) if len(self._x) == 1: indx = [0] elif self._xsorted: # for really long signals, if we know they are sorted # on x we can save a lot of time using search sorted # since the alternative approach requires 3 O(len(x) ) ops indMin, indMax = searchsorted(self._x, array([self._xmin, self._xmax])) indMin = max(0, indMin - 1) indMax = min(indMax + 1, len(self._x)) skip = 0 if self._lod: # if level of detail is on, decimate the data # based on pixel width raise NotImplementedError("LOD deprecated") l, b, w, h = self.get_window_extent().get_bounds() skip = int((indMax - indMin) / w) if skip > 0: indx = arange(indMin, indMax, skip) else: indx = arange(indMin, indMax) else: indx = nonzero(logical_and(self._x >= self._xmin, self._x <= self._xmax)) self._xc = take(self._x, indx) self._yc = take(self._y, indx) # y data clipping for connected lines can introduce horizontal # line artifacts near the clip region. If you really need y # clipping for efficiency, consider using plot(y,x) instead. if self._yc.shape == self._xc.shape and self._linestyle is None: try: self._ymin, self._ymax except AttributeError: indy = arange(len(self._yc)) else: indy = nonzero(logical_and(self._yc >= self._ymin, self._yc <= self._ymax)) else: indy = arange(len(self._yc)) self._xc = take(self._xc, indy) self._yc = take(self._yc, indy)
def entropy(y, bins): """ Return the entropy of the data in y \sum p_i log2(p_i) where p_i is the probability of observing y in the ith bin of bins. bins can be a number of bins or a range of bins; see hist Compare S with analytic calculation for a Gaussian x = mu + sigma*randn(200000) Sanalytic = 0.5 * ( 1.0 + log(2*pi*sigma**2.0) ) """ n,bins = hist(y, bins) n = n.astype(Float) n = take(n, nonzero(n)) # get the positive p = divide(n, len(y)) delta = bins[1]-bins[0] S = -1.0*asum(p*log(p)) + log(delta) #S = -1.0*asum(p*log(p)) return S
def _get_plottable(self): # If log scale is set, only pos data will be returned x, y = self._x, self._y try: logx = self._transform.get_funcx().get_type()==LOG10 except RuntimeError: logx = False # non-separable try: logy = self._transform.get_funcy().get_type()==LOG10 except RuntimeError: logy = False # non-separable if not logx and not logy: return x, y if self._logcache is not None: waslogx, waslogy, xcache, ycache = self._logcache if logx==waslogx and waslogy==logy: return xcache, ycache Nx = len(x) Ny = len(y) if logx: indx = greater(x, 0) else: indx = ones(len(x)) if logy: indy = greater(y, 0) else: indy = ones(len(y)) ind = nonzero(logical_and(indx, indy)) x = take(x, ind) y = take(y, ind) self._logcache = logx, logy, x, y return x, y
def __call__(self): 'Return the locations of the ticks' self.verify_intervals() b=self._base vmin, vmax = self.viewInterval.get_bounds() vmin = math.log(vmin)/math.log(b) vmax = math.log(vmax)/math.log(b) if vmax<vmin: vmin, vmax = vmax, vmin ticklocs = [] numdec = math.floor(vmax)-math.ceil(vmin) if self._subs is None: # autosub if numdec>10: subs = array([1.0]) elif numdec>6: subs = arange(2.0, b, 2.0) else: subs = arange(2.0, b) else: subs = self._subs for decadeStart in b**arange(math.floor(vmin),math.ceil(vmax)): ticklocs.extend( subs*decadeStart ) if(len(subs) and subs[0]==1.0): ticklocs.append(b**math.ceil(vmax)) ticklocs = array(ticklocs) ind = nonzero(logical_and(ticklocs>=b**vmin , ticklocs<=b**vmax)) ticklocs = take(ticklocs,ind) return ticklocs
def get_xyz_where(Z, Cond): """ Z and Cond are MxN matrices. Z are data and Cond is a boolean matrix where some condition is satisfied. Return value is x,y,z where x and y are the indices into Z and z are the values of Z at those indices. x,y,z are 1D arrays """ M, N = Z.shape z = ravel(Z) ind = nonzero(ravel(Cond)) x = arange(M) x.shape = M, 1 X = repeat(x, N, 1) x = ravel(X) y = arange(N) y.shape = 1, N Y = repeat(y, M) y = ravel(Y) x = take(x, ind) y = take(y, ind) z = take(z, ind) return x, y, z
def entropy(y, bins): """ Return the entropy of the data in y \sum p_i log2(p_i) where p_i is the probability of observing y in the ith bin of bins. bins can be a number of bins or a range of bins; see hist Compare S with analytic calculation for a Gaussian x = mu + sigma*randn(200000) Sanalytic = 0.5 * ( 1.0 + log(2*pi*sigma**2.0) ) """ n, bins = hist(y, bins) n = n.astype(Float) n = take(n, nonzero(n)) # get the positive p = divide(n, len(y)) delta = bins[1] - bins[0] S = -1.0 * asum(p * log(p)) + log(delta) #S = -1.0*asum(p*log(p)) return S
def __call__(self): 'Return the locations of the ticks' self.verify_intervals() b=self.base subs=self.subs vmin, vmax = self.viewInterval.get_bounds() vmin = math.log(vmin)/math.log(b) vmax = math.log(vmax)/math.log(b) if vmax<vmin: vmin, vmax = vmax, vmin ticklocs = [] for decadeStart in b**arange(math.floor(vmin),math.ceil(vmax)): ticklocs.extend( subs*decadeStart ) if(len(subs) and subs[0]==1.0): ticklocs.append(b**math.ceil(vmax)) ticklocs = array(ticklocs) ind = nonzero(logical_and(ticklocs>=b**vmin , ticklocs<=b**vmax)) ticklocs = take(ticklocs,ind) return ticklocs
def scanner(s): """ Split a string into mathtext and non-mathtext parts. mathtext is surrounded by $ symbols. quoted \$ are ignored All slash quotes dollar signs are ignored The number of unquoted dollar signs must be even Return value is a list of (substring, inmath) tuples """ if not len(s): return [(s, False)] #print 'testing', s, type(s) inddollar = nonzero(asarray(equal(s, '$'))) quoted = dict([(ind, 1) for ind in nonzero(asarray(equal(s, '\\')))]) indkeep = [ind for ind in inddollar if not quoted.has_key(ind - 1)] if len(indkeep) == 0: return [(s, False)] if len(indkeep) % 2: raise ValueError( 'Illegal string "%s" (must have balanced dollar signs)' % s) Ns = len(s) indkeep = [ind for ind in indkeep] # make sure we start with the first element if indkeep[0] != 0: indkeep.insert(0, 0) # and end with one past the end of the string indkeep.append(Ns + 1) Nkeep = len(indkeep) results = [] inmath = s[0] == '$' for i in range(Nkeep - 1): i0, i1 = indkeep[i], indkeep[i + 1] if not inmath: if i0 > 0: i0 += 1 else: i1 += 1 if i0 >= Ns: break results.append((s[i0:i1], inmath)) inmath = not inmath return results
def scanner(s): """ Split a string into mathtext and non-mathtext parts. mathtext is surrounded by $ symbols. quoted \$ are ignored All slash quotes dollar signs are ignored The number of unquoted dollar signs must be even Return value is a list of (substring, inmath) tuples """ if not len(s): return [(s, False)] #print 'testing', s, type(s) inddollar = nonzero(asarray(equal(s,'$'))) quoted = dict([ (ind,1) for ind in nonzero(asarray(equal(s,'\\')))]) indkeep = [ind for ind in inddollar if not quoted.has_key(ind-1)] if len(indkeep)==0: return [(s, False)] if len(indkeep)%2: raise ValueError('Illegal string "%s" (must have balanced dollar signs)'%s) Ns = len(s) indkeep = [ind for ind in indkeep] # make sure we start with the first element if indkeep[0]!=0: indkeep.insert(0,0) # and end with one past the end of the string indkeep.append(Ns+1) Nkeep = len(indkeep) results = [] inmath = s[0] == '$' for i in range(Nkeep-1): i0, i1 = indkeep[i], indkeep[i+1] if not inmath: if i0>0: i0 +=1 else: i1 += 1 if i0>=Ns: break results.append((s[i0:i1], inmath)) inmath = not inmath return results
def get_ind_under_point(self, event): 'get the index of the vertex under point if within epsilon tolerance' x, y = zip(*self.poly.verts) # display coords xt, yt = self.poly.get_transform().numerix_x_y(x, y) d = sqrt((xt-event.x)**2 + (yt-event.y)**2) indseq = nonzero(equal(d, amin(d))) ind = indseq[0] if d[ind]>=self.epsilon: ind = None return ind
def get_ind_under_point(self, event): 'get the index of the vertex under point if within epsilon tolerance' x, y = zip(*self.poly.verts) # display coords xt, yt = self.poly.get_transform().numerix_x_y(x, y) d = sqrt((xt - event.x)**2 + (yt - event.y)**2) indseq = nonzero(equal(d, amin(d))) ind = indseq[0] if d[ind] >= self.epsilon: ind = None return ind
def _get_numeric_clipped_data_in_range(self): # if the x or y clip is set, only plot the points in the # clipping region. If log scale is set, only pos data will be # returned try: self._xc, self._yc except AttributeError: x, y = self._x, self._y else: x, y = self._xc, self._yc try: logx = self._transform.get_funcx().get_type() == LOG10 except RuntimeError: logx = False # non-separable try: logy = self._transform.get_funcy().get_type() == LOG10 except RuntimeError: logy = False # non-separable if not logx and not logy: return x, y if self._logcache is not None: waslogx, waslogy, xcache, ycache = self._logcache if logx == waslogx and waslogy == logy: return xcache, ycache Nx = len(x) Ny = len(y) if logx: indx = greater(x, 0) else: indx = ones(len(x)) if logy: indy = greater(y, 0) else: indy = ones(len(y)) ind = nonzero(logical_and(indx, indy)) x = take(x, ind) y = take(y, ind) self._logcache = logx, logy, x, y return x, y
def get_xyz_where(Z, Cond): """ Z and Cond are MxN matrices. Z are data and Cond is a boolean matrix where some condition is satisfied. Return value is x,y,z where x and y are the indices into Z and z are the values of Z at those indices. x,y,z are 1D arrays """ M,N = Z.shape z = ravel(Z) ind = nonzero( ravel(Cond) ) x = arange(M); x.shape = M,1 X = repeat(x, N, 1) x = ravel(X) y = arange(N); y.shape = 1,N Y = repeat(y, M) y = ravel(Y) x = take(x, ind) y = take(y, ind) z = take(z, ind) return x,y,z
def break_linecontour(self, linecontour, rot, labelwidth, ind): "break a contour in two contours at the location of the label" lcsize = len(linecontour) hlw = int(labelwidth / 2) #length of label in screen coords ylabel = abs(hlw * sin(rot * pi / 180)) xlabel = abs(hlw * cos(rot * pi / 180)) trans = self.ax.transData slc = trans.seq_xy_tups(linecontour) x, y = slc[ind] xx = array(slc)[:, 0].copy() yy = array(slc)[:, 1].copy() #indices which are under the label inds = nonzero(((xx < x + xlabel) & (xx > x - xlabel)) & ((yy < y + ylabel) & (yy > y - ylabel))) if len(inds) > 0: #if the label happens to be over the beginning of the #contour, the entire contour is removed, i.e. #indices to be removed are #inds= [0,1,2,3,305,306,307] #should rewrite this in a better way linds = nonzero(inds[1:] - inds[:-1] != 1) if inds[0] == 0 and len(linds) != 0: ii = inds[linds[0]] lc1 = linecontour[ii + 1:inds[ii + 1]] lc2 = [] else: lc1 = linecontour[:inds[0]] lc2 = linecontour[inds[-1] + 1:] else: lc1 = linecontour[:ind] lc2 = linecontour[ind + 1:] if rot < 0: new_x1, new_y1 = x - xlabel, y + ylabel new_x2, new_y2 = x + xlabel, y - ylabel else: new_x1, new_y1 = x - xlabel, y - ylabel new_x2, new_y2 = x + xlabel, y + ylabel new_x1d, new_y1d = trans.inverse_xy_tup((new_x1, new_y1)) new_x2d, new_y2d = trans.inverse_xy_tup((new_x2, new_y2)) if rot > 0: if len(lc1) > 0 and (lc1[-1][0] <= new_x1d) and (lc1[-1][1] <= new_y1d): lc1.append((new_x1d, new_y1d)) if len(lc2) > 0 and (lc2[0][0] >= new_x2d) and (lc2[0][1] >= new_y2d): lc2.insert(0, (new_x2d, new_y2d)) else: if len(lc1) > 0 and ((lc1[-1][0] <= new_x1d) and (lc1[-1][1] >= new_y1d)): lc1.append((new_x1d, new_y1d)) if len(lc2) > 0 and ((lc2[0][0] >= new_x2d) and (lc2[0][1] <= new_y2d)): lc2.insert(0, (new_x2d, new_y2d)) return [lc1, lc2]
def contour_graph(z, level): '''calculate contour of z at level. z[y,x] has to be a 2d array. Returns a list of 4-element lists. Each entry represents one contour. Each entry is [interp_y, xind, yind, weight] where all four are 1d lists of equal size. Imagine a rectangular grid where the crossings are the points of z. All points of the result are located on this grid. For point n: if interp_y[n] is True, the point is on a vertical line, else on a horizontal line. If it is on a vertical line, xind[n] gives the corresponding index into z. The y position is between yind[n] and yind[n]+1. weight[n] is a number between 0.0 and 1.0 giving the position: 0 means the point is on yind[n] exactly, 1.0 means the point is on yind[n]+1 exactly. If the point is on a horizontal line, weight[n] denotes the position between xind[n] and xind[n]+1. result[lineidx][0..3][pointidx] ''' bw = (z>level) # "black and white" image of z horiz = (bw[:,:-1] != bw[:,1:]) # True where a contour crosses rows vert = (bw[:-1] != bw[1:]) # True where a contour crosses columns # for later readability up, down, left, right = 1, 4, 2, 8 # adjacency & up means crosspoint at y (top), & left: at x (left), # & down: at y+1, & right: at x+1 # adjacency[y, x] is the cell between x...x+1 and y...y+1 adjacency = (horiz[:-1,:]*up | vert[:,:-1]*left | horiz [1:,:]*down | vert[:,1:]*right) # calculate interpolation weights and store in horiz, vert # weight = (level - z[n])/(z[n+1]-z[n]) # -1 => dummy value (no crossing) horiz = where(horiz, (level-z[:,:-1]) / (z[:,1:]-z[:,:-1]), -1) vert = where(vert, (level-z[:-1]) / (z[1:]-z[:-1]), -1) result = [] def _appendpoint(line, x, y, direction): '''append the point adjacency[y,x], direction translated into grid coordinates and remove from adjacency. returns tuple (bool, x, y, weight) bool: False means on horizontal grid, True on vertical grid weight is the position between x and x+1 resp y and y+1''' adjacency[y, x] ^= direction # XOR out direction if direction & (up|down): if direction & down: y += 1 assert horiz[y,x] > -1 # for debugging line[0].append(False) line[1].append(x) line[2].append(y) line[3].append(horiz[y, x]) else: # direction is left or right if direction & right: x += 1 assert vert[y, x] > -1 # for debugging line[0].append(True) line[1].append(x) line[2].append(y) line[3].append(vert[y,x]) # end def opposite = {up:down, down:up, left:right, right:left} while any(adjacency != 0): # first look if there are any contours ending at the borders of z border = True # top border if any(adjacency[0] & up): x0 = nonzero(adjacency[0] & up)[0][0] # just take first one y0 = 0 orig = up # where we come from # bottom elif any(adjacency[-1] & down): x0 = nonzero(adjacency[-1] & down)[0][0] y0 = adjacency.shape[0] - 1 orig = down # left elif any(adjacency[:,0] & left): x0 = 0 y0 = nonzero(adjacency[:,0] & left)[0][0] orig = left # right border elif any(adjacency[:,-1] & right): x0 = adjacency.shape[1] - 1 y0 = nonzero(adjacency[:,-1] & right)[0][0] orig = right else: # pick an arbitrary point (all contours are closed loops now) m = adjacency.argmax() # FIXME: This is not very pretty! forward compatible?! x0, y0 = m%adjacency.shape[1], m/adjacency.shape[1] border = False # did not start from border adj = adjacency[y0, x0] if adj & up: orig = up elif adj & down: orig = down elif adj & left: orig = left else: # There can be only 2 or 4 ends, so adj&right only is an error raise 'Dead end at r%d,c%d -- should be impossible!'%(y0,x0) # okay now we have starting cell x0,y0 and direction orig. endofcontour = False # set when border reached or closed line = [[], [], [], []] while not endofcontour: # append last point _appendpoint(line, x0, y0, orig) # find next point adj = adjacency[y0, x0] if (adj | orig) == 15: # all directions possible, hm... # lets connect cross-wise # this might create weird results with multiple contours cont = opposite[orig] else: # only one continuation - no problem :-D cont = adj newx0 = x0 + {up:0, down:0, left:-1, right:1}[cont] newy0 = y0 + {up:-1, down:1, left:0, right:0}[cont] orig = opposite[cont] # out of bounds if border and ((not 0<=newx0<adjacency.shape[1]) or (not 0<=newy0<adjacency.shape[0])): _appendpoint(line, x0, y0, cont) endofcontour = True else: adjacency[y0, x0] ^= cont x0, y0 = newx0, newy0 # loop closed if adjacency[y0, x0] & orig == 0: _appendpoint(line, x0, y0, orig) adjacency[y0, x0] ^= orig endofcontour = True result.append(line) return result
def find(condition): "Return the indices where condition is true" return nonzero(condition)
def break_linecontour(self, linecontour, rot, labelwidth, ind): "break a contour in two contours at the location of the label" lcsize = len(linecontour) hlw = int(labelwidth/2) #length of label in screen coords ylabel = abs(hlw * sin(rot*pi/180)) xlabel = abs(hlw * cos(rot*pi/180)) trans = self.ax.transData slc = trans.seq_xy_tups(linecontour) x,y = slc[ind] xx= array(slc)[:,0].copy() yy=array(slc)[:,1].copy() #indices which are under the label inds=nonzero(((xx < x+xlabel) & (xx > x-xlabel)) & ((yy < y+ylabel) & (yy > y-ylabel))) if len(inds) >0: #if the label happens to be over the beginning of the #contour, the entire contour is removed, i.e. #indices to be removed are #inds= [0,1,2,3,305,306,307] #should rewrite this in a better way linds = nonzero(inds[1:]- inds[:-1] != 1) if inds[0] == 0 and len(linds) != 0: ii = inds[linds[0]] lc1 =linecontour[ii+1:inds[ii+1]] lc2 = [] else: lc1=linecontour[:inds[0]] lc2= linecontour[inds[-1]+1:] else: lc1=linecontour[:ind] lc2 = linecontour[ind+1:] if rot <0: new_x1, new_y1 = x-xlabel, y+ylabel new_x2, new_y2 = x+xlabel, y-ylabel else: new_x1, new_y1 = x-xlabel, y-ylabel new_x2, new_y2 = x+xlabel, y+ylabel new_x1d, new_y1d = trans.inverse_xy_tup((new_x1, new_y1)) new_x2d, new_y2d = trans.inverse_xy_tup((new_x2, new_y2)) if rot > 0: if len(lc1) > 0 and (lc1[-1][0] <= new_x1d) and (lc1[-1][1] <= new_y1d): lc1.append((new_x1d, new_y1d)) if len(lc2) > 0 and (lc2[0][0] >= new_x2d) and (lc2[0][1] >= new_y2d): lc2.insert(0, (new_x2d, new_y2d)) else: if len(lc1) > 0 and ((lc1[-1][0] <= new_x1d) and (lc1[-1][1] >= new_y1d)): lc1.append((new_x1d, new_y1d)) if len(lc2) > 0 and ((lc2[0][0] >= new_x2d) and (lc2[0][1] <= new_y2d)): lc2.insert(0, (new_x2d, new_y2d)) return [lc1,lc2]