Source code for maps

"""Planetary mapping routines.

phi = 0 faces toward the observer
phi = pi thus faces away from the observer
theta=pi/2 is the z-axis or 'north pole'
theta=-pi/2 is the 'south pole'




"""
# 2010-01-15 20:31 IJC: Started                   .               .            .

from numpy import pi


[docs]def makegrid(nphi,ntheta): """Make grids of phi and theta values with the specified number of points in each direction. Phi ranges from 0 to 2pi, and theta ranges from -pi/2 to pi/2. Returns (phi, theta)""" # 2010-01-15 20:29 IJC: Created from numpy import meshgrid, linspace phi,theta = meshgrid(linspace(0,2*pi,nphi),linspace(-pi/2,pi/2,ntheta)) return phi,theta
[docs]def rotcoord(phi,theta,iangle,rangle): """rotate coordinate system from local (planetary) coordinates into observer-oriented coordinages. rangle and iangle are the rotation and inclination angles of the planet in radians. returns (phi2,theta2) phi2 will be in the range (0,2pi) and theta2 will be in the range (-pi/2,pi/2) """ # 2010-01-15 21:09 IJC: Created from numpy import array,cos,sin,vstack,dot,arctan2,sqrt,pi nphi,ntheta = phi.shape phir = phi+rangle costheta = cos(theta) x = cos(phir)*costheta y = sin(phir)*costheta z = sin(theta) xyz = vstack((x.ravel(),y.ravel(),z.ravel())) beta = pi/2.-iangle sinbeta = sin(beta) cosbeta = cos(beta) rotmat = array([[cosbeta,0,-sinbeta],[0,1,0],[sinbeta,0,cosbeta]]) xyz2 = dot(rotmat,xyz) x2,y2,z2 = xyz2[0].reshape(nphi,ntheta),xyz2[1].reshape(nphi,ntheta),xyz2[2].reshape(nphi,ntheta) phi2 = arctan2(y2,x2) % (2*pi) theta2 = arctan2(z2,sqrt(x2**2+y2**2)) return phi2,theta2
[docs]def visiblemap(phi,theta,iangle,rangle): """Return a 2D boolean map that's True for the planetary latitude, longitude values visible from an observer. For rangle (rotation angle) zero and iangle (inclination angle) equal to pi/2, phi=pi is toward the observer. """ # 2010-01-18 08:13 IJC: Created nphi,ntheta = phi.shape phi2,theta2 = rotcoord(phi,theta,iangle,rangle) vismap = (phi2<pi/2)+(phi2>1.5*pi) return vismap
[docs]def wedgemap(phi,theta,phi0,phi1): """Return a 2D boolean map that's True for the latitude, longitude values in a given longitudinal planet 'wedge'. phi0,phi1 should be in the range (0,2*pi) """ # 2010-01-18 08:13 IJC: Created phi0 = phi0 % (2*pi) phi1 = phi1 % (2*pi) if phi1>=phi0: wedge = (phi<phi1)*(phi>=phi0) elif phi1<phi0: wedge = (phi>=phi0)+(phi<phi1) return wedge
[docs]def wedgestack(phi,theta,nwedge,phi0): """Return a stack of 2D boolean maps via wedgemap. phi0 defines the center of wedge zero. """ # 2010-01-18 08:13 IJC: Created from numpy import zeros,arange dphi = 2*pi/nwedge pp0=arange(-.5,nwedge-.5,dtype=float)*dphi+phi0 pp1=arange(.5,nwedge+.5,dtype=float)*dphi+phi0 wedges = zeros((nwedge,)+phi.shape,float) for ii in range(nwedge): wedges[ii,:,:]= wedgemap(phi,theta,pp0[ii],pp1[ii]) return wedges
[docs]def projarea(phi,theta): """Return a 2D map of the projected area. Note that you need to determine for yourself which parts of the areal map are actually visible to the observer. Assumes dA = cos(t) dt df (theta=t, phi=f) and thus da = cos(f) cos(t)**2 dt df EXAMPLE: import maps, pylab phi, theta = maps.makegrid(300,240) vis = maps.visiblemap(phi,theta,pi/2,0) da = maps.projarea(phi,theta) pylab.imshow(da*vis) pylab.title('visible projected area sums to: %f (pi)' % (da*vis).sum()) """ # 2010-01-18 09:23 IJC: Created from numpy import cos df = phi[0,1]-phi[0,0] dt = theta[1,0]-theta[0,0] da = (cos(theta)**2) * cos(phi) * dt * df return da
[docs]def wedgebasis(phi,theta,iangle,rangle,nwedge,phi0, fwedge=None): """Return a set of basis functions for the flux from each wedge. phi,theta are the observer-centered grids from MAPS.MAKEGRID iangle is the inclination of the system (0 = pole-on) rangle (seq.) is a sequence of (0,2pi) rotation values at which the wedge-based flux is evaluated. nwedge is the number of wedges phi0 defines the center of wedge zero. fwedge -- an optional sequence to set individual flux values for each wedge. """ # 2010-01-18 08:13 IJC: Created from numpy import array,arange,zeros,tile rangle = array(rangle,copy=True) nrot = len(rangle) bases = zeros((nrot,nwedge),float) da = projarea(phi,theta) vis = (phi<=0.5*pi) + (phi>1.5*pi) phi2,theta2 = rotcoord(phi,theta,iangle,rangle[0]) for ii in range(nrot): # Faster to shift reference point than entire phi2 grid: wedges = wedgestack(phi2,theta2,nwedge,phi0-rangle[ii]+rangle[0]) bases[ii,:] = (wedges*da*vis).sum(2).sum(1) if fwedge<>None: fwedge = tile(fwedge,(nrot,1)) bases = bases * fwedge return bases
[docs]def errseries(param,phi,theta,rangle,meas,err): """Give the chi-squared to an input timeseries to get the wedge coefficients and inclination angle. param -- [inclination, phi0, wedge coefficients] phi,theta -- from MAKEGRID rangle -- rotation angles at which flux was measured meas -- measured flux err -- error on measurement (one-sigma) Usage: from scipy import optimize optimize.fmin(maps.errseries, guess, args=(...)) """ # 2010-01-18 14:04 IJC: Created iangle = param[0] phi0 = param[1] fcoef = param[2::] nwedge = len(fcoef) model = wedgebasis(phi,theta,iangle,rangle,nwedge,phi0,fwedge=fcoef).sum(1) chisq = (((model-meas)/err)**2).sum() print "param, chisq>>" +str(param)+', '+str(chisq) return chisq
[docs]def makespot(phi, theta, da=None, vmap=None, inc=None, rot=None, long=0, lat=0, siz=pi/4, plotalot=False): """Make a spot-map. EXAMPLE: import maps inc, rot = pi/2., 0. phi, theta = maps.makecoord(120,60) phi2, theta2 = maps.rotcoord(phi,theta,inc,rot) vmap = maps.visiblemap(phi,theta,inc,rot) maps.makespot(phi,theta,inc=pi/2,rot=0.,lat=pi/4,long=1.*pi) maps.makespot(phi2,theta2,vmap=vmap,lat=pi/4,long=1.*pi) """ if plotalot: from pylab import * from tools import nextfig figure(nextfig(), [15,15]); clf() if da is None: da = projarea(phi,theta) if plotalot: subplot(3,3,1) imshow(phi); colorbar(); title('phi') subplot(3,3,2) imshow(theta); colorbar(); title('theta') subplot(3,3,3) imshow(da); colorbar(); title('d_area') if inc is not None and rot is not None: phi, theta = rotcoord(phi,theta,inc,rot) if vmap is None: vmap = visiblemap(phi,theta,inc,rot) if plotalot: subplot(3,3,4) imshow(phi); colorbar(); title('phi') subplot(3,3,5) imshow(theta); colorbar(); title('theta') subplot(3,3,6) imshow(vmap); title('vmap: inc=%s, rot=%s'%(inc,rot)); colorbar() if long is not None and lat is not None: phi, theta, = rotcoord(phi,theta,-lat, -long) spot = vmap*da*((theta-theta.max())>-siz) if plotalot: subplot(3,3,7) imshow(phi); colorbar(); title('phi') subplot(3,3,8) imshow(theta); colorbar(); title('theta') subplot(3,3,9) imshow(spot); title('spot: lat=%s, long=%s'%(lat,long)); colorbar() return phi, theta, da, vmap, spot, (inc, rot, long, lat, siz)