def fillcontinents(self,ax,color=0.8): """ Fill continents. ax - current axis instance. color - color to fill continents (default gray). """ # define corners of map domain. p1 = (self.llcrnrx,self.llcrnry); p2 = (self.urcrnrx,self.urcrnry) p3 = (self.llcrnrx,self.urcrnry); p4 = (self.urcrnrx,self.llcrnry) for x,y in self.coastpolygons: xa = N.array(x,'f') ya = N.array(y,'f') # clip to map domain. xa = N.clip(xa, self.xmin, self.xmax) ya = N.clip(ya, self.ymin, self.ymax) # check to see if all four corners of domain in polygon (if so, # don't draw since it will just fill in the whole map). test1 = N.fabs(xa-self.xmax) < 10. test2 = N.fabs(xa-self.xmin) < 10. test3 = N.fabs(ya-self.ymax) < 10. test4 = N.fabs(ya-self.ymin) < 10. hasp1 = sum(test1*test3) hasp2 = sum(test2*test3) hasp4 = sum(test2*test4) hasp3 = sum(test1*test4) if not hasp1 or not hasp2 or not hasp3 or not hasp4: xy = zip(xa.tolist(),ya.tolist()) poly = Polygon(xy,facecolor=color,edgecolor=color,linewidth=0) ax.add_patch(poly)
def fillcontinents(self, ax, color=0.8): """ Fill continents. ax - current axis instance. color - color to fill continents (default gray). """ # define corners of map domain. p1 = (self.llcrnrx, self.llcrnry) p2 = (self.urcrnrx, self.urcrnry) p3 = (self.llcrnrx, self.urcrnry) p4 = (self.urcrnrx, self.llcrnry) for x, y in self.coastpolygons: xa = N.array(x, 'f') ya = N.array(y, 'f') # clip to map domain. xa = N.clip(xa, self.xmin, self.xmax) ya = N.clip(ya, self.ymin, self.ymax) # check to see if all four corners of domain in polygon (if so, # don't draw since it will just fill in the whole map). test1 = N.fabs(xa - self.xmax) < 10. test2 = N.fabs(xa - self.xmin) < 10. test3 = N.fabs(ya - self.ymax) < 10. test4 = N.fabs(ya - self.ymin) < 10. hasp1 = sum(test1 * test3) hasp2 = sum(test2 * test3) hasp4 = sum(test2 * test4) hasp3 = sum(test1 * test4) if not hasp1 or not hasp2 or not hasp3 or not hasp4: xy = zip(xa.tolist(), ya.tolist()) poly = Polygon(xy, facecolor=color, edgecolor=color, linewidth=0) ax.add_patch(poly)
def _mad2(data, included): # adapted from NR function moment # same as mad3 but ignores zero values n = len(data[:,0,0]) s = num.zeros(data[0,:,:].shape, num.Float32) # First pass to get the mean. for j in range(n): s += data[j,:,:] ave = s/included adev = num.zeros(s.shape, num.Float32) for j in range(n): d = where(num.fabs(data[j]) > tiny, num.fabs(data[j] - ave), 0.0) num.add(adev, d, adev) return adev / included
def _simple_logistic_regression(x,y,beta_start=None,verbose=False, CONV_THRESH=1.e-3,MAXIT=500): """ Faster than logistic_regression when there is only one predictor. """ if len(x) != len(y): raise ValueError, "x and y should be the same length!" if beta_start is None: beta_start = NA.zeros(2,x.typecode()) iter = 0; diff = 1.; beta = beta_start # initial values if verbose: print 'iteration beta log-likliehood |beta-beta_old|' while iter < MAXIT: beta_old = beta p = NA.exp(beta[0]+beta[1]*x)/(1.+NA.exp(beta[0]+beta[1]*x)) l = NA.sum(y*NA.log(p) + (1.-y)*NA.log(1.-p)) # log-likliehood s = NA.array([NA.sum(y-p), NA.sum((y-p)*x)]) # scoring function # information matrix J_bar = NA.array([[NA.sum(p*(1-p)),NA.sum(p*(1-p)*x)], [NA.sum(p*(1-p)*x),NA.sum(p*(1-p)*x*x)]]) beta = beta_old + NA.dot(LA.inverse(J_bar),s) # new value of beta diff = NA.sum(NA.fabs(beta-beta_old)) # sum of absolute differences if verbose: print iter+1, beta, l, diff if diff <= CONV_THRESH: break iter = iter + 1 return beta, J_bar, l
def _simple_logistic_regression(x,y,beta_start=None,verbose=False, CONV_THRESH=1.e-3,MAXIT=500): """ Faster than logistic_regression when there is only one predictor. """ if len(x) != len(y): raise ValueError, "x and y should be the same length!" if beta_start is None: beta_start = NA.zeros(2,x.dtype.char) iter = 0; diff = 1.; beta = beta_start # initial values if verbose: print 'iteration beta log-likliehood |beta-beta_old|' while iter < MAXIT: beta_old = beta p = NA.exp(beta[0]+beta[1]*x)/(1.+NA.exp(beta[0]+beta[1]*x)) l = NA.sum(y*NA.log(p) + (1.-y)*NA.log(1.-p)) # log-likliehood s = NA.array([NA.sum(y-p), NA.sum((y-p)*x)]) # scoring function # information matrix J_bar = NA.array([[NA.sum(p*(1-p)),NA.sum(p*(1-p)*x)], [NA.sum(p*(1-p)*x),NA.sum(p*(1-p)*x*x)]]) beta = beta_old + NA.dot(LA.inverse(J_bar),s) # new value of beta diff = NA.sum(NA.fabs(beta-beta_old)) # sum of absolute differences if verbose: print iter+1, beta, l, diff if diff <= CONV_THRESH: break iter = iter + 1 return beta, J_bar, l
def _mad3(data): # adapted from NR function moment n = len(data[:,0,0]) s = num.zeros(data[0,:,:].shape, num.Float32) # First pass to get the mean. for j in range(n): s += data[j,:,:] ave = s/n adev = num.zeros(s.shape, num.Float32) for j in range(n): num.add(adev, num.fabs(data[j] - ave), adev) return adev / n
def logistic_regression(x, y, beta_start=None, verbose=False, CONV_THRESH=1.e-3, MAXIT=500): """ Uses the Newton-Raphson algorithm to calculate a maximum likelihood estimate logistic regression. The algorithm is known as 'iteratively re-weighted least squares', or IRLS. x - rank-1 or rank-2 array of predictors. If x is rank-2, the number of predictors = x.shape[0] = N. If x is rank-1, it is assumed N=1. y - binary outcomes (if N>1 len(y) = x.shape[1], if N=1 len(y) = len(x)) beta_start - initial beta vector (default zeros(N+1,x.dtype.char)) if verbose=True, diagnostics printed for each iteration (default False). MAXIT - max number of iterations (default 500) CONV_THRESH - convergence threshold (sum of absolute differences of beta-beta_old, default 0.001) returns beta (the logistic regression coefficients, an N+1 element vector), J_bar (the (N+1)x(N+1) information matrix), and l (the log-likeliehood). J_bar can be used to estimate the covariance matrix and the standard error for beta. l can be used for a chi-squared significance test. covmat = inverse(J_bar) --> covariance matrix of coefficents (beta) stderr = sqrt(diag(covmat)) --> standard errors for beta deviance = -2l --> scaled deviance statistic chi-squared value for -2l is the model chi-squared test. """ if x.shape[-1] != len(y): raise ValueError, "x.shape[-1] and y should be the same length!" try: N, npreds = x.shape[1], x.shape[0] except: # single predictor, use simple logistic regression routine. return _simple_logistic_regression(x, y, beta_start=beta_start, CONV_THRESH=CONV_THRESH, MAXIT=MAXIT, verbose=verbose) if beta_start is None: beta_start = NA.zeros(npreds + 1, x.dtype.char) X = NA.ones((npreds + 1, N), x.dtype.char) X[1:, :] = x Xt = NA.transpose(X) iter = 0 diff = 1. beta = beta_start # initial values if verbose: print 'iteration beta log-likliehood |beta-beta_old|' while iter < MAXIT: beta_old = beta ebx = NA.exp(NA.dot(beta, X)) p = ebx / (1. + ebx) l = NA.sum(y * NA.log(p) + (1. - y) * NA.log(1. - p)) # log-likeliehood s = NA.dot(X, y - p) # scoring function J_bar = NA.dot(X * p, Xt) # information matrix beta = beta_old + NA.dot(LA.inverse(J_bar), s) # new value of beta diff = NA.sum(NA.fabs(beta - beta_old)) # sum of absolute differences if verbose: print iter + 1, beta, l, diff if diff <= CONV_THRESH: break iter = iter + 1 if iter == MAXIT and diff > CONV_THRESH: print 'warning: convergence not achieved with threshold of %s in %s iterations' % ( CONV_THRESH, MAXIT) return beta, J_bar, l
def drawmeridians(self,ax,meridians,color='k',linewidth=1., \ linestyle='--',dashes=[1,1],labels=[0,0,0,0],\ font='rm',fontsize=12): """ draw meridians (longitude lines). ax - current axis instance. meridians - list containing longitude values to draw (in degrees). color - color to draw meridians (default black). linewidth - line width for meridians (default 1.) linestyle - line style for meridians (default '--', i.e. dashed). dashes - dash pattern for meridians (default [1,1], i.e. 1 pixel on, 1 pixel off). labels - list of 4 values (default [0,0,0,0]) that control whether meridians are labelled where they intersect the left, right, top or bottom of the plot. For example labels=[1,0,0,1] will cause meridians to be labelled where they intersect the left and bottom of the plot, but not the right and top. Labels are located with a precision of 0.1 degrees and are drawn using mathtext. font - mathtext font used for labels ('rm','tt','it' or 'cal', default 'rm'. fontsize - font size in points for labels (default 12). """ # don't draw meridians past latmax, always draw parallel at latmax. latmax = 80. # not used for cyl, merc projections. # offset for labels. yoffset = (self.urcrnry-self.llcrnry)/100./self.aspect xoffset = (self.urcrnrx-self.llcrnrx)/100. if self.projection not in ['merc','cyl']: lats = N.arange(-latmax,latmax+1).astype('f') else: lats = N.arange(-90,91).astype('f') xdelta = 0.1*(self.xmax-self.xmin) ydelta = 0.1*(self.ymax-self.ymin) for merid in meridians: lons = merid*N.ones(len(lats),'f') x,y = self(lons,lats) # remove points outside domain. testx = N.logical_and(x>=self.xmin-xdelta,x<=self.xmax+xdelta) x = N.compress(testx, x) y = N.compress(testx, y) testy = N.logical_and(y>=self.ymin-ydelta,y<=self.ymax+ydelta) x = N.compress(testy, x) y = N.compress(testy, y) if len(x) > 1 and len(y) > 1: # split into separate line segments if necessary. # (not necessary for mercator or cylindrical). xd = (x[1:]-x[0:-1])**2 yd = (y[1:]-y[0:-1])**2 dist = N.sqrt(xd+yd) split = dist > 500000. if N.sum(split) and self.projection not in ['merc','cyl']: ind = (N.compress(split,pylab.squeeze(split*N.indices(xd.shape)))+1).tolist() xl = [] yl = [] iprev = 0 ind.append(len(xd)) for i in ind: xl.append(x[iprev:i]) yl.append(y[iprev:i]) iprev = i else: xl = [x] yl = [y] # draw each line segment. for x,y in zip(xl,yl): # skip if only a point. if len(x) > 1 and len(y) > 1: l = Line2D(x,y,linewidth=linewidth,linestyle=linestyle) l.set_color(color) l.set_dashes(dashes) ax.add_line(l) # draw labels for meridians. # search along edges of map to see if parallels intersect. # if so, find x,y location of intersection and draw a label there. if self.projection == 'cyl': dx = 0.01; dy = 0.01 elif self.projection == 'merc': dx = 0.01; dy = 1000 else: dx = 1000; dy = 1000 for dolab,side in zip(labels,['l','r','t','b']): if not dolab: continue # for cyl or merc, don't draw meridians on left or right. if self.projection in ['cyl','merc'] and side in ['l','r']: continue if side in ['l','r']: nmax = int((self.ymax-self.ymin)/dy+1) if self.urcrnry < self.llcrnry: yy = self.llcrnry-dy*N.arange(nmax) else: yy = self.llcrnry+dy*N.arange(nmax) if side == 'l': lons,lats = self(self.llcrnrx*N.ones(yy.shape,'f'),yy,inverse=True) else: lons,lats = self(self.urcrnrx*N.ones(yy.shape,'f'),yy,inverse=True) lons = N.where(lons < 0, lons+360, lons) lons = [int(lon*10) for lon in lons.tolist()] lats = [int(lat*10) for lat in lats.tolist()] else: nmax = int((self.xmax-self.xmin)/dx+1) if self.urcrnrx < self.llcrnrx: xx = self.llcrnrx-dx*N.arange(nmax) else: xx = self.llcrnrx+dx*N.arange(nmax) if side == 'b': lons,lats = self(xx,self.llcrnry*N.ones(xx.shape,'f'),inverse=True) else: lons,lats = self(xx,self.urcrnry*N.ones(xx.shape,'f'),inverse=True) lons = N.where(lons < 0, lons+360, lons) lons = [int(lon*10) for lon in lons.tolist()] lats = [int(lat*10) for lat in lats.tolist()] for lon in meridians: if lon<0: lon=lon+360. # find index of meridian (there may be two, so # search from left and right). try: nl = lons.index(int(lon*10)) except: nl = -1 try: nr = len(lons)-lons[::-1].index(int(lon*10))-1 except: nr = -1 if lon>180: lonlab = r'$\%s{%g\/^{\circ}\/W}$'%(font,N.fabs(lon-360)) elif lon<180 and lon != 0: lonlab = r'$\%s{%g\/^{\circ}\/E}$'%(font,lon) else: lonlab = r'$\%s{%g\/^{\circ}}$'%(font,lon) # meridians can intersect each map edge twice. for i,n in enumerate([nl,nr]): lat = lats[n]/10. # no meridians > latmax for projections other than merc,cyl. if self.projection not in ['merc','cyl'] and lat > latmax: continue # don't bother if close to the first label. if i and abs(nr-nl) < 100: continue if n > 0: if side == 'l': pylab.text(self.llcrnrx-xoffset,yy[n],lonlab,horizontalalignment='right',verticalalignment='center',fontsize=fontsize) elif side == 'r': pylab.text(self.urcrnrx+xoffset,yy[n],lonlab,horizontalalignment='left',verticalalignment='center',fontsize=fontsize) elif side == 'b': pylab.text(xx[n],self.llcrnry-yoffset,lonlab,horizontalalignment='center',verticalalignment='top',fontsize=fontsize) else: pylab.text(xx[n],self.urcrnry+yoffset,lonlab,horizontalalignment='center',verticalalignment='bottom',fontsize=fontsize) # make sure axis ticks are turned off ax.set_xticks([]) ax.set_yticks([])
def drawmeridians(self,ax,meridians,color='k',linewidth=1., \ linestyle='--',dashes=[1,1],labels=[0,0,0,0],\ font='rm',fontsize=12): """ draw meridians (longitude lines). ax - current axis instance. meridians - list containing longitude values to draw (in degrees). color - color to draw meridians (default black). linewidth - line width for meridians (default 1.) linestyle - line style for meridians (default '--', i.e. dashed). dashes - dash pattern for meridians (default [1,1], i.e. 1 pixel on, 1 pixel off). labels - list of 4 values (default [0,0,0,0]) that control whether meridians are labelled where they intersect the left, right, top or bottom of the plot. For example labels=[1,0,0,1] will cause meridians to be labelled where they intersect the left and bottom of the plot, but not the right and top. Labels are located with a precision of 0.1 degrees and are drawn using mathtext. font - mathtext font used for labels ('rm','tt','it' or 'cal', default 'rm'. fontsize - font size in points for labels (default 12). """ # don't draw meridians past latmax, always draw parallel at latmax. latmax = 80. # not used for cyl, merc projections. # offset for labels. yoffset = (self.urcrnry - self.llcrnry) / 100. / self.aspect xoffset = (self.urcrnrx - self.llcrnrx) / 100. if self.projection not in ['merc', 'cyl']: lats = N.arange(-latmax, latmax + 1).astype('f') else: lats = N.arange(-90, 91).astype('f') xdelta = 0.1 * (self.xmax - self.xmin) ydelta = 0.1 * (self.ymax - self.ymin) for merid in meridians: lons = merid * N.ones(len(lats), 'f') x, y = self(lons, lats) # remove points outside domain. testx = N.logical_and(x >= self.xmin - xdelta, x <= self.xmax + xdelta) x = N.compress(testx, x) y = N.compress(testx, y) testy = N.logical_and(y >= self.ymin - ydelta, y <= self.ymax + ydelta) x = N.compress(testy, x) y = N.compress(testy, y) if len(x) > 1 and len(y) > 1: # split into separate line segments if necessary. # (not necessary for mercator or cylindrical). xd = (x[1:] - x[0:-1])**2 yd = (y[1:] - y[0:-1])**2 dist = N.sqrt(xd + yd) split = dist > 500000. if N.sum(split) and self.projection not in ['merc', 'cyl']: ind = (N.compress( split, pylab.squeeze(split * N.indices(xd.shape))) + 1).tolist() xl = [] yl = [] iprev = 0 ind.append(len(xd)) for i in ind: xl.append(x[iprev:i]) yl.append(y[iprev:i]) iprev = i else: xl = [x] yl = [y] # draw each line segment. for x, y in zip(xl, yl): # skip if only a point. if len(x) > 1 and len(y) > 1: l = Line2D(x, y, linewidth=linewidth, linestyle=linestyle) l.set_color(color) l.set_dashes(dashes) ax.add_line(l) # draw labels for meridians. # search along edges of map to see if parallels intersect. # if so, find x,y location of intersection and draw a label there. if self.projection == 'cyl': dx = 0.01 dy = 0.01 elif self.projection == 'merc': dx = 0.01 dy = 1000 else: dx = 1000 dy = 1000 for dolab, side in zip(labels, ['l', 'r', 't', 'b']): if not dolab: continue # for cyl or merc, don't draw meridians on left or right. if self.projection in ['cyl', 'merc'] and side in ['l', 'r']: continue if side in ['l', 'r']: nmax = int((self.ymax - self.ymin) / dy + 1) if self.urcrnry < self.llcrnry: yy = self.llcrnry - dy * N.arange(nmax) else: yy = self.llcrnry + dy * N.arange(nmax) if side == 'l': lons, lats = self(self.llcrnrx * N.ones(yy.shape, 'f'), yy, inverse=True) else: lons, lats = self(self.urcrnrx * N.ones(yy.shape, 'f'), yy, inverse=True) lons = N.where(lons < 0, lons + 360, lons) lons = [int(lon * 10) for lon in lons.tolist()] lats = [int(lat * 10) for lat in lats.tolist()] else: nmax = int((self.xmax - self.xmin) / dx + 1) if self.urcrnrx < self.llcrnrx: xx = self.llcrnrx - dx * N.arange(nmax) else: xx = self.llcrnrx + dx * N.arange(nmax) if side == 'b': lons, lats = self(xx, self.llcrnry * N.ones(xx.shape, 'f'), inverse=True) else: lons, lats = self(xx, self.urcrnry * N.ones(xx.shape, 'f'), inverse=True) lons = N.where(lons < 0, lons + 360, lons) lons = [int(lon * 10) for lon in lons.tolist()] lats = [int(lat * 10) for lat in lats.tolist()] for lon in meridians: if lon < 0: lon = lon + 360. # find index of meridian (there may be two, so # search from left and right). try: nl = lons.index(int(lon * 10)) except: nl = -1 try: nr = len(lons) - lons[::-1].index(int(lon * 10)) - 1 except: nr = -1 if lon > 180: lonlab = r'$\%s{%g\/^{\circ}\/W}$' % (font, N.fabs(lon - 360)) elif lon < 180 and lon != 0: lonlab = r'$\%s{%g\/^{\circ}\/E}$' % (font, lon) else: lonlab = r'$\%s{%g\/^{\circ}}$' % (font, lon) # meridians can intersect each map edge twice. for i, n in enumerate([nl, nr]): lat = lats[n] / 10. # no meridians > latmax for projections other than merc,cyl. if self.projection not in ['merc', 'cyl'] and lat > latmax: continue # don't bother if close to the first label. if i and abs(nr - nl) < 100: continue if n > 0: if side == 'l': pylab.text(self.llcrnrx - xoffset, yy[n], lonlab, horizontalalignment='right', verticalalignment='center', fontsize=fontsize) elif side == 'r': pylab.text(self.urcrnrx + xoffset, yy[n], lonlab, horizontalalignment='left', verticalalignment='center', fontsize=fontsize) elif side == 'b': pylab.text(xx[n], self.llcrnry - yoffset, lonlab, horizontalalignment='center', verticalalignment='top', fontsize=fontsize) else: pylab.text(xx[n], self.urcrnry + yoffset, lonlab, horizontalalignment='center', verticalalignment='bottom', fontsize=fontsize) # make sure axis ticks are turned off ax.set_xticks([]) ax.set_yticks([])
def logistic_regression(x,y,beta_start=None,verbose=False,CONV_THRESH=1.e-3, MAXIT=500): """ Uses the Newton-Raphson algorithm to calculate a maximum likelihood estimate logistic regression. The algorithm is known as 'iteratively re-weighted least squares', or IRLS. x - rank-1 or rank-2 array of predictors. If x is rank-2, the number of predictors = x.shape[0] = N. If x is rank-1, it is assumed N=1. y - binary outcomes (if N>1 len(y) = x.shape[1], if N=1 len(y) = len(x)) beta_start - initial beta vector (default zeros(N+1,x.dtype.char)) if verbose=True, diagnostics printed for each iteration (default False). MAXIT - max number of iterations (default 500) CONV_THRESH - convergence threshold (sum of absolute differences of beta-beta_old, default 0.001) returns beta (the logistic regression coefficients, an N+1 element vector), J_bar (the (N+1)x(N+1) information matrix), and l (the log-likeliehood). J_bar can be used to estimate the covariance matrix and the standard error for beta. l can be used for a chi-squared significance test. covmat = inverse(J_bar) --> covariance matrix of coefficents (beta) stderr = sqrt(diag(covmat)) --> standard errors for beta deviance = -2l --> scaled deviance statistic chi-squared value for -2l is the model chi-squared test. """ if x.shape[-1] != len(y): raise ValueError, "x.shape[-1] and y should be the same length!" try: N, npreds = x.shape[1], x.shape[0] except: # single predictor, use simple logistic regression routine. return _simple_logistic_regression(x,y,beta_start=beta_start, CONV_THRESH=CONV_THRESH,MAXIT=MAXIT,verbose=verbose) if beta_start is None: beta_start = NA.zeros(npreds+1,x.dtype.char) X = NA.ones((npreds+1,N), x.dtype.char) X[1:, :] = x Xt = NA.transpose(X) iter = 0; diff = 1.; beta = beta_start # initial values if verbose: print 'iteration beta log-likliehood |beta-beta_old|' while iter < MAXIT: beta_old = beta ebx = NA.exp(NA.dot(beta, X)) p = ebx/(1.+ebx) l = NA.sum(y*NA.log(p) + (1.-y)*NA.log(1.-p)) # log-likeliehood s = NA.dot(X, y-p) # scoring function J_bar = NA.dot(X*p,Xt) # information matrix beta = beta_old + NA.dot(LA.inverse(J_bar),s) # new value of beta diff = NA.sum(NA.fabs(beta-beta_old)) # sum of absolute differences if verbose: print iter+1, beta, l, diff if diff <= CONV_THRESH: break iter = iter + 1 if iter == MAXIT and diff > CONV_THRESH: print 'warning: convergence not achieved with threshold of %s in %s iterations' % (CONV_THRESH,MAXIT) return beta, J_bar, l