예제 #1
0
파일: extended.py 프로젝트: kerrm/pointlike
def make_pictures(config_dir='.', image_folder = 'extended_images'):
    """ make a folder with images for all extended sources """
    from uw.like2 import configuration
    from skymaps import Band
    if not os.path.exists(image_folder):
        os.mkdir(image_folder)
    cf = configuration.Configuration(config_dir, quiet=True, postpone=True)
    class Bandlite(object):
        def __init__(self, roi_dir, event_type=1, energy =133.352):
            self.event_type=event_type
            self.energy=energy
            self.sd=roi_dir
            self.psf=cf.psfman(event_type,energy)
            self.exposure = cf.exposureman(event_type,energy)
            self.radius =5

    ecat = ExtendedCatalog(cf.extended)
    for name in ecat.names:
        print 'processing %s ...' % name ,
        source = ecat.lookup(name)
        b12 = Band(12); roi_index = b12.index(source.skydir); 
        roi_dir = b12.dir(roi_index)
        conv = convolution.ExtendedConvolver(source, Bandlite(roi_dir=roi_dir))
        conv.create_grid()
        fig = conv.show_source()
        fig.savefig('%s/%s_map.png' %(image_folder,name.replace(' ','_')))
        print 
예제 #2
0
class MultiHealpixKDEMap(object):
    def __init__(self, glob_expansion):
        """glob_expansion: an expression that can be expanded by glob into a list of the
                           pickles of HealpixTSMaps that this class will access
                           
                           N.B. it is necessary that these objects all have been constructed
                           with the same settings of base nside and sub-grid factor!
        """

        tsmaps = [HealpixKDEMap(pickle=x) for x in glob(glob_expansion)]
        nside1 = tsmaps[0].band1.nside()

        self.band1 = Band(nside1)
        self.tsmaps = [False] * 12 * nside1**2
        for tsmap in tsmaps:
            self.tsmaps[tsmap.index] = tsmap
        self.scale = 0

    def __call__(self, v, skydir=None):
        sd = skydir or SkyDir(Hep3Vector(v[0], v[1], v[2]))
        id = self.band1.index(sd)
        tsmap = self.tsmaps[id]
        if not tsmap: return np.nan
        return tsmap.multipix_call(sd)

    def make_zea(self, center, size=10, pixelsize=0.02, galactic=False):
        z = ZEA(center, size=size, pixelsize=pixelsize, galactic=galactic)
        z.fill(PySkyFunction(self))
        self.z = z
예제 #3
0
class HealpixMap(object):
    """map from a set of Healpix to values, supporting a SkyFunction interface
       and interpolation.
       
       The implentation here is not really appropriate for a sparse map (much less
       than all-sky if the number of pixels are large, since the storage system is
       a vector with indices==healpix_index.
       
       An alternative (perhaps realizable with a child class) can use a sorted
       lookup and store only populated entries."""
    def __init__(self, nside, inds, vals):
        self.band = Band(nside)
        #s = np.argsort(inds)
        #self.inds = inds[s]
        #self.vals = vals[s]
        self.vals = np.empty(12 * nside**2)
        self.vals[:] = np.nan
        self.vals[inds] = vals

        from libpointlike import IntVector
        self.iv = IntVector()

    def __call__(self, v, skydir=None):
        sd = skydir or SkyDir(Hep3Vector(v[0], v[1], v[2]))
        healpix_index = self.band.index(sd)
        return self.vals[healpix_index]

    def bilinear_interp(self, v, skydir=None):
        b = self.band
        sd = skydir or SkyDir(Hep3Vector(v[0], v[1], v[2]))
        healpix_index = b.index(sd)
        d = b.dir(healpix_index)
        b.findNeighbors(healpix_index, self.iv)
        idx = np.asarray([x for x in iv] + [healpix_index])
        dirs = [b.dir(idx) for idx in self.iv] + [d]
        diffs = np.asarray([sd.difference(di) for di in dirs])

        # use co-ordinate system that puts pixels closest to equator
        use_gal = abs(d.b()) < abs(d.dec())
        if use_gal:
            lons = np.asarray([d.b() for d in dirs])
            lats = np.asarray([d.l() for d in dirs])
            sdlon = sd.b()
            sdlat = sd.l()
        else:
            lons = np.asarray([d.ra() for d in dirs])
            lats = np.asarray([d.dec() for d in dirs])
            sdlon = sd.ra()
            sdlat = sd.dec()

        s = np.argsort(diffs)
        lons = lons[s][:4]
        lats = lats[s][:4]
        vals = np.asarray([self(0, skydir=dirs[x]) for x in s[:4]])
        return (np.abs(lons - sdlon) * np.abs(lats - sdlat) * vals).sum()
예제 #4
0
def make_index_table(nside, subnside, usefile=True):
    filename = 'index_table_%02d_%03d.pickle' % (nside, subnside)
    if os.path.exists(filename) and usefile:
        return pickle.load(open(filename))
    print 'generating index table for nside, subnside= %d %d' % (nside,
                                                                 subnside)
    band, subband = Band(nside), Band(subnside)
    npix, nsubpix = 12 * nside**2, 12 * subnside**2
    t = np.array([band.index(subband.dir(i)) for i in xrange(nsubpix)])
    a = np.arange(nsubpix)
    index_table = [a[t == i] for i in xrange(npix)]
    if usefile:
        pickle.dump(index_table, open(filename, 'w'))
    return index_table
예제 #5
0
    def setup_from_roi(self, hr, factor):

        band1 = hr.band
        band2 = Band(int(round(band1.nside() * factor)))
        rd = band1.dir(hr.index)

        # get pixels within a radius 10% greater than the base Healpix diagonal dimension
        radius = (np.pi / (3 * band1.nside()**2))**0.5 * 2**0.5 * 1.1
        wsdl = WeightedSkyDirList(band2, rd, radius, True)

        # then cut down to just the pixels inside the base Healpixel
        inds = np.asarray([band1.index(x) for x in wsdl])
        mask = inds == hr.index
        dirs = [wsdl[i] for i in xrange(len(mask)) if mask[i]]
        inds = np.asarray([band2.index(x) for x in dirs]).astype(int)

        # sanity check
        if abs(float(mask.sum()) / factor**2 - 1) > 0.01:
            print 'Warning: number of pixels found does not agree with expectations!'

        # calculate TS for each sub-pixel
        tsc = TSCalc(hr.roi)
        if self.bright_sources is not None:
            ts_vals = self.ts_vals = [deque(), deque(), deque()]
            bsm = np.asarray([
                x.source_name in self.bright_sources for x in hr.roi.psm.models
            ])
            for d in dirs:
                ts_vals[0].append(tsc(d))
                ts_vals[1].append(tsc(d, repeat_diffuse=True))
                ts_vals[2].append(
                    tsc(d, repeat_diffuse=True, bright_source_mask=bsm))
        else:
            self.ts_vals = ts_vals = [deque(), deque()]
            for d in dirs:
                ts_vals[0].append(tsc(d))
                ts_vals[1].append(tsc(d, repeat_diffuse=True))

        self.band1 = band1
        self.band2 = band2

        sorting = np.argsort(inds)
        self.inds = inds[sorting]
        for i in range(len(ts_vals)):
            ts_vals[i] = np.asarray(ts_vals[i])[sorting]

        self.previous_index = -1
        self.index = hr.index
        self.mode = 0
        self.ts = self.ts_vals[0]
예제 #6
0
def make_index_table(nside=12, subnside=512, usefile=True):
    """create, and/or use a table to convert between different nside pixelizations
    """
    filename = os.path.expandvars('$FERMI/misc/index_table_%02d_%03d.pickle' % (nside, subnside) )
    if os.path.exists(filename) and usefile:
        return pickle.load(open(filename))
    print 'generating index table for nside, subnside= %d %d' % (nside, subnside)
    band, subband = Band(nside), Band(subnside)
    npix, nsubpix = 12*nside**2, 12*subnside**2
    t=np.array([band.index(subband.dir(i)) for i in xrange(nsubpix)])
    a = np.arange(nsubpix)
    index_table = [a[t==i] for i in xrange(npix)]
    if usefile:
        pickle.dump(index_table, open(filename,'w'))
    return index_table
예제 #7
0
    def setup_from_roi(self, hr, factor):

        band1 = hr.band
        band2 = Band(int(round(band1.nside() * factor)))
        rd = band1.dir(hr.index)

        # get pixels within a radius 10% greater than the base Healpix diagonal dimension
        radius = (np.pi / (3 * band1.nside()**2))**0.5 * 2**0.5 * 1.1
        wsdl = WeightedSkyDirList(band2, rd, radius, True)

        # then cut down to just the pixels inside the base Healpixel
        inds = np.asarray([band1.index(x) for x in wsdl])
        mask = inds == hr.index
        dirs = [wsdl[i] for i in xrange(len(mask)) if mask[i]]
        inds = np.asarray([band2.index(x) for x in dirs]).astype(int)

        # sanity check
        if abs(float(mask.sum()) / factor**2 - 1) > 0.01:
            print 'Warning: number of pixels found does not agree with expectations!'

        # loop through the bands and image pixels to calculate the KDE
        from libpointlike import DoubleVector
        #dv = DoubleVector()
        rvs = [np.empty(len(band.wsdl), dtype=float) for band in hr.roi.bands]
        img = np.zeros(len(inds))
        weights = [
            np.asarray([x.weight() for x in b.wsdl]).astype(int)
            for b in hr.roi.bands
        ]
        for idir, mydir in enumerate(dirs):
            #print 'Processing pixel %d'%(idir)
            for iband, band in enumerate(hr.roi.bands):
                PythonUtilities.arclength(band.rvals, band.wsdl, mydir)
                img[idir] += (band.psf(rvs[iband], density=True) *
                              weights[iband]).sum()

        self.band1 = band1
        self.band2 = band2
        self.previous_index = -1

        sorting = np.argsort(inds)
        self.inds = inds[sorting]
        self.img = img[sorting]

        self.index = hr.index
예제 #8
0
class Display_map(object):
    """ utility class to handle nice displays of a HParray object
    
    """
    def __init__(self,
                 hptable,
                 outdir,
                 map_dir=None,
                 nside=12,
                 imshow_kw=dict(
                     interpolation='bilinear',
                     vmin=0,
                     vmax=100,
                 ),
                 **kwargs):
        """
        hptable : HParray object
            expect to have vec, nside members
        outdir : string
            folder containing the skymodel
        map_dir : None, string
            folder name to save the images
        
        """
        from .. import skymodel
        self.v = hptable.vec
        self.subband = Band(hptable.nside)
        self.band = Band(nside)
        self.n = 12 * nside**2
        self.imshow_kw = imshow_kw
        self.scale = kwargs.pop('scale', lambda x: x)
        if type(self.scale) == types.StringTypes:
            if self.scale == 'sqrt': self.scale = lambda x: np.sqrt(max(x, 0))
            elif self.scale == 'log':
                self.scale = lambda x: np.log10(max(x, 0.1))
            else:
                raise Exception, 'unrecognized scale function, %s' % self.scale
        print 'Can generate %d map figures' % (self.n)
        self.outdir = outdir
        self.ZEA_kw = kwargs.pop('ZEA_kw', dict())
        if map_dir is not None:
            self.map_path = os.path.join(outdir, map_dir)
            if not os.path.exists(self.map_path):
                os.makedirs(self.map_path)
            print 'will save figures in folder %s' % self.map_path
        else:
            self.map_path = None
        skm = skymodel.SkyModel(outdir)
        self.sources = skm.point_sources + skm.extended_sources
        print 'loaded %d sources from skymodel %s' % (len(
            self.sources), outdir)

    def get_pyskyfun(self):
        return PySkyFunction(self)

    def skyfun(self, v):
        skydir = SkyDir(Hep3Vector(v[0], v[1], v[2]))
        return self.v[self.subband.index(skydir)]

    def __call__(self, v):
        skydir = SkyDir(Hep3Vector(v[0], v[1], v[2]))
        t = self.v[self.subband.index(skydir)]
        #if   self.scale=='sqrt': return np.sqrt(max(t,0))
        #elif self.scale=='log':  return np.log10(max(t, 1e-1))
        return self.scale(t)

    def fill_ait(self, fignum=11, axes=None, show_kw={}, **kwargs):
        if axes is None:
            plt.close(fignum)
            fig = plt.figure(fignum, figsize=(12, 8))
            axes = fig.gca()
        pixelsize = kwargs.pop('pixelsize', 0.25)
        ait = image.AIT(self.get_pyskyfun(),
                        axes=axes,
                        pixelsize=pixelsize,
                        **kwargs)
        self.imgplot = ait.imshow(**show_kw)
        return ait

    def fill_zea(self, index, fignum=12, axes=None, **kwargs):
        """ sources is a recarray with name, ra, dec
        """
        if axes is None:
            plt.close(fignum)
            fig = plt.figure(fignum, figsize=(6, 6))
            axes = fig.gca()
        size = kwargs.pop('size', 10)
        pixelsize = kwargs.pop('pixelsize', 0.1)
        title = kwargs.pop('title', hpname(index))
        label = kwargs.pop('label', '')
        zea = image.ZEA(self.band.dir(index),
                        size=size,
                        pixelsize=pixelsize,
                        **self.ZEA_kw)
        zea.grid()
        zea.fill(self.get_pyskyfun())
        imshow_kw = self.imshow_kw  #
        imshow_kw.update(kwargs)
        zea.imshow(**imshow_kw)
        zea.colorbar(label=label)
        axes.set_title(title)
        if self.sources is not None:
            count = 0
            for s in self.sources:
                sdir = s.skydir
                if not zea.inside(sdir): continue
                count += 1
                inside = self.band.index(sdir) == index
                zea.plot_source(s.name,
                                sdir,
                                symbol='*' if inside else 'd',
                                markersize=14 if inside else 8,
                                color='w')
            print 'found %d sources to plot' % count

        if self.map_path is not None:
            fout = os.path.join(self.map_path, hpname(index) + '.png')
            plt.savefig(fout)
            print 'saved figure to %s' % fout
        plt.draw_if_interactive()
예제 #9
0
class DisplayMap(object):
    """ display the contents of a HEALpix table as ait or zea
    
    """
    def __init__(self, table,
                sources=None, 
                imshow_kw=dict(interpolation='bilinear',  ),
                **kwargs):
        """table : string or iterable
                If a string, the name of a pickled file
           sources : None or a string 
                if a string, the name of a pickled rec with name, ra, dec fields
        """
        if type(table)==types.StringType:        
            self.v = pickle.load(open(table))
            print 'Loaded HEALpix table from file %s' %table
        else: self.v=table
        self.nside = int(np.sqrt(len(self.v)/12))
        assert len(self.v)==12*self.nside**2, 'size of map not consistent with expected nside %d' % nside 
        self.band = Band(self.nside)
        self.imshow_kw=imshow_kw
        self.scale = kwargs.pop('scale', lambda x: x)
        if type(self.scale) == types.StringTypes:
            if self.scale=='sqrt': self.scale= lambda x: np.sqrt(max(x,0))
            elif self.scale=='log': self.scale=lambda x: np.log10(max(x,0.1))
            else:
                raise Exception, 'unrecognized scale function, %s' %self.scale
        self.ZEA_kw = kwargs.pop('ZEA_kw', dict(galactic=True, size=10, pixelsize=0.1))
        if sources is not None:
            self.sources = pickle.load(open(sources))
            print 'loaded %d sources from %s' % (len(self.sources),sources)
        else:self.sources=None
        
        self.map_path = kwargs.pop('map_path',None)
        
    def get_pyskyfun(self):
        return PySkyFunction(self)

    def skyfun(self, v):
        skydir = SkyDir(Hep3Vector(v[0],v[1],v[2]))
        return self.v[self.band.index(skydir)]
        
    def __call__(self,v):
        skydir = SkyDir(Hep3Vector(v[0],v[1],v[2]))
        t =self.v[self.band.index(skydir)]
        return self.scale(t) 

    def fill_ait(self, fignum=11, axes=None, show_kw={}, source_kw={}, figwidth=12, margin=0.15, **kwargs):
        if axes is None:
            # set up a figure for 2x1 image with equal margins
            plt.close(fignum)
            figheight = figwidth*(1.+2*margin)/(1+margin)/2.
            fig=plt.figure(fignum, figsize=(figwidth, figheight));
            axes=plt.gca()
            plt.subplots_adjust(left=0.05, right=0.95) #gives reasonable equal margins
        pixelsize = kwargs.pop('pixelsize', 0.25)
        ait = image.AIT(self.get_pyskyfun(),axes=axes, pixelsize=pixelsize, **kwargs)
        self.imgplot=ait.imshow(**show_kw)
        ait.axes.set_autoscale_on(False)

        if self.sources is not None:
            sdirs = map(SkyDir, self.sources.ra, self.sources.dec)
            ait.plot(sdirs, **source_kw)
            print 'found %d sources to plot' % len(sdirs) 
        plt.draw_if_interactive()
        return ait

    def fill_zea(self, index, fignum=12, axes=None, show_kw=None, **kwargs):
        """ index: integer, or a SkyDir
                the HP12 index if integer
            figmun: integer
                used if axes is None
            show_kw : dict
                override imshow keywords
            kwargs 
                size
                pixelsize
                galactic
        """
        if axes is None:
            plt.close(fignum)
            fig = plt.figure(fignum,figsize=(6,6)); 
            axes = fig.gca()
        if type(index) == types.IntType:
            sdir = Band(12).dir(index)
            title = 'HP12_%4d'%index
        else:
            sdir = index
            title = 'l = %.1f, b=%.1f' % (sdir.l(), sdir.b())
        title = kwargs.pop('title',title)
        kw = self.ZEA_kw
        kw.update(kwargs)
        zea = image.ZEA(sdir, **kw)
        zea.grid()
        zea.fill(self.get_pyskyfun())
        zea.imshow( **(show_kw if show_kw is not None else self.imshow_kw))
        zea.colorbar()
        if title is not None: axes.set_title(title)
        if self.sources is not None:
            count = 0
            for s in self.sources:
                sdir = SkyDir(s.ra,s.dec)
                if not zea.inside(sdir):continue
                count += 1
                inside =self.band.index(sdir)==index
                zea.plot_source(s.name, sdir, symbol='*' if inside else 'd', 
                    markersize=14 if inside else 8,
                    color='w')
            print 'found %d sources to plot' %count        
        
        if self.map_path is not None:
            fout = os.path.join(self.map_path,hpname(index)+'.png')
            plt.savefig(fout, bbox_inches='tight')
            print 'saved figure to %s' % fout
        plt.draw_if_interactive()
        return zea
예제 #10
0
class ROIWrapper(object):
    """Wrap up an ROI as if it were a HealpixROI, for testing."""
    def __init__(self, roi, nside=6):
        self.roi = roi
        self.band = Band(nside)
        self.index = self.band.index(roi.roi_dir)
예제 #11
0
class HealpixKDEMap(object):

    defaults = dict(
        factor=100,
        emin=[500, 1000],
    )

    def __init__(self, hr=None, pickle=None, do_healpix=False, **kwargs):
        """hr     :   an instance of HealpixROI
           pickle :   a pickle saved from a previous HealpixTSMap
           factor :   number of intervals to divide base Healpixel side into"""

        self.__dict__.update(HealpixKDEMap.defaults)
        self.__dict__.update(kwargs)
        if hr is not None:
            if do_healpix:
                self.__call__ = self.call
                self.setup_from_roi(hr, self.factor)
            else:
                self.__call__ = self.call2
                self.setup_from_roi2(hr)
        elif pickle is not None:
            self.load(pickle)
        else:
            print 'Must provide either a HealpixROI instance or a pickle file!'
            raise Exception

    def setup_from_roi2(self, hr):
        self.bands = []
        for iband, band in enumerate(hr.roi.bands):
            if band.emin < self.emin[band.ct]:
                continue
            else:
                self.bands += [band]
            band.rvals = np.empty(len(band.wsdl), dtype=float)
            band.r99 = np.radians(band.psf.inverse_integral_on_axis(0.95))

    def call2(self, v, skydir=None):
        sd = skydir or SkyDir(Hep3Vector(v[0], v[1], v[2]))
        rval = 0
        for band in self.bands:
            if band.photons == 0: continue
            band.rvals = np.empty(len(band.wsdl), dtype=float)
            PythonUtilities.arclength(band.rvals, band.wsdl, sd)
            mask = band.rvals < band.r99
            rval += (band.psf(band.rvals[mask], density=True) *
                     band.pix_counts[mask]).sum()
        return rval

    def setup_from_roi(self, hr, factor):

        band1 = hr.band
        band2 = Band(int(round(band1.nside() * factor)))
        rd = band1.dir(hr.index)

        # get pixels within a radius 10% greater than the base Healpix diagonal dimension
        radius = (np.pi / (3 * band1.nside()**2))**0.5 * 2**0.5 * 1.1
        wsdl = WeightedSkyDirList(band2, rd, radius, True)

        # then cut down to just the pixels inside the base Healpixel
        inds = np.asarray([band1.index(x) for x in wsdl])
        mask = inds == hr.index
        dirs = [wsdl[i] for i in xrange(len(mask)) if mask[i]]
        inds = np.asarray([band2.index(x) for x in dirs]).astype(int)

        # sanity check
        if abs(float(mask.sum()) / factor**2 - 1) > 0.01:
            print 'Warning: number of pixels found does not agree with expectations!'

        # loop through the bands and image pixels to calculate the KDE
        from libpointlike import DoubleVector
        #dv = DoubleVector()
        rvs = [np.empty(len(band.wsdl), dtype=float) for band in hr.roi.bands]
        img = np.zeros(len(inds))
        weights = [
            np.asarray([x.weight() for x in b.wsdl]).astype(int)
            for b in hr.roi.bands
        ]
        for idir, mydir in enumerate(dirs):
            #print 'Processing pixel %d'%(idir)
            for iband, band in enumerate(hr.roi.bands):
                PythonUtilities.arclength(band.rvals, band.wsdl, mydir)
                img[idir] += (band.psf(rvs[iband], density=True) *
                              weights[iband]).sum()

        self.band1 = band1
        self.band2 = band2
        self.previous_index = -1

        sorting = np.argsort(inds)
        self.inds = inds[sorting]
        self.img = img[sorting]

        self.index = hr.index

    def dump(self, filename):
        d = dict()
        d['inds'] = self.inds
        d['img'] = self.img
        d['nside1'] = self.band1.nside()
        d['nside2'] = self.band2.nside()
        d['index'] = self.index
        dump(d, file(filename, 'w'))

    def load(self, filename):
        d = load(file(filename))
        self.inds = d['inds']
        self.band1 = Band(d['nside1'])
        self.band2 = Band(d['nside2'])
        self.img = d['img']
        self.index = d['index']
        self.previous_index = -1

    def pyskyfun(self):
        return PySkyFunction(self)

    def __call__(self, v, skydir=None):
        sd = skydir or SkyDir(Hep3Vector(v[0], v[1], v[2]))
        if self.band1.index(sd) != self.index: return np.nan
        id = self.band2.index(sd)
        if id != self.previous_index:
            self.previous_value = self.img[np.searchsorted(self.inds, id)]
            self.previous_index = id
        return self.previous_value

    def multipix_call(self, sd):
        """A faster version of the skydir lookup where it assumed that the argument
           lies within the boundaries of this Healpixel."""
        id = self.band2.index(sd)
        if id != self.previous_index:
            self.previous_value = self.img[np.searchsorted(self.inds, id)]
            self.previous_index = id
        return self.previous_value
예제 #12
0
class MultiHealpixTSMap(object):
    def __init__(self, glob_expansion):
        """glob_expansion: an expression that can be expanded by glob into a list of the
                           pickles of HealpixTSMaps that this class will access
                           
                           N.B. it is necessary that these objects all have been constructed
                           with the same settings of base nside and sub-grid factor!
        """

        tsmaps = [HealpixTSMap(pickle=x) for x in glob(glob_expansion)]
        nside1 = tsmaps[0].band1.nside()

        self.band1 = Band(nside1)
        self.tsmaps = [False] * 12 * nside1**2
        for tsmap in tsmaps:
            self.tsmaps[tsmap.index] = tsmap
        self.scale = 0

    def __call__(self, v, skydir=None):
        sd = skydir or SkyDir(Hep3Vector(v[0], v[1], v[2]))
        id = self.band1.index(sd)
        tsmap = self.tsmaps[id]
        if not tsmap: return np.nan
        return tsmap.multipix_call(sd)

    def set_mode(self, mode=1):
        """Change display mode.
           1 == TS map with all known point sources included in models
           2 == TS map using only diffuse models for background
        """
        if mode not in [0, 1, 2]:
            print 'Error!  Not a valid mode.  Please use 1 or 2.'
            return
        for tsmap in self.tsmaps:
            if tsmap: tsmap.set_mode(mode)

    def make_zea(self, center, size=10, pixelsize=0.02, galactic=False):
        from uw.utilities.image import ZEA
        z = ZEA(center, size=size, pixelsize=pixelsize, galactic=galactic)
        z.fill(PySkyFunction(self))
        self.z = z

    def get_1FGL_sources(self, z):
        """z == ZEA object"""
        fgl = get_latalog()
        sd_ul = z.skydir(0, 0)  # upper left corner
        sd_lr = z.skydir(z.nx, z.ny)  # lower right corner
        if z.galactic:
            az_max, po_min = sd_ul.l(), sd_ul.b()
            az_min, po_max = sd_lr.l(), sd_lr.b()
        else:
            az_max, po_min = sd_ul.ra(), sd_ul.dec()
            az_min, po_max = sd_lr.ra(), sd_lr.dec()

        # since longitude runs backward, this condition means we looped over 0
        az_zero_cross = az_min > az_max

        az_key, po_key = ['GLON', 'GLAT'] if z.galactic else ['RA', 'DEC']
        az = fgl.get(az_key).astype(float)
        po = fgl.get(po_key).astype(float)
        na = fgl.get('Source_Name')
        print po_min, po_max, az_min, az_max

        mask = (po > po_min) & (po < po_max)
        if az_zero_cross:
            mask = mask & ((az < az_max) | (az > az_min))
        else:
            mask = mask & (az > az_min) & (az < az_max)
        sds = [
            SkyDir(a, p, SkyDir.GALACTIC if z.galactic else SkyDir.EQUATORIAL)
            for a, p in zip(az[mask], po[mask])
        ]
        return na[mask], sds

    def make_map(self,
                 center,
                 size=10,
                 pixelsize=0.02,
                 galactic=False,
                 axes=None,
                 scale=1,
                 thresh_low=0,
                 thresh_high=np.inf,
                 label_1FGL=True,
                 mode=1,
                 cmap=None,
                 log_transform=False,
                 labels=None):
        """
            scale : 0 == linear, 1 == sqrt
        """
        import pylab as P
        from uw.utilities.image import ZEA
        from matplotlib.colorbar import ColorbarBase
        from matplotlib.colors import Normalize

        self.set_mode(mode)

        if axes is None: axes = P.gca()
        cmap = cmap or P.cm.jet
        cmap.set_bad('white')
        z = ZEA(center,
                size=size,
                pixelsize=pixelsize,
                galactic=galactic,
                axes=axes)
        z.fill(PySkyFunction(self))
        im = z.image.copy()
        print 'Max Value: %.2f' % (im.max())
        im[im < thresh_low] = np.nan
        im[im > thresh_high] = thresh_high
        z.grid()
        im = im**(0.5 if scale else 1)
        if log_transform:
            im[im < 1] = 1
            im = np.log10(im)
        P.imshow(im, cmap=cmap)
        #P.colorbar(ax=axes,cmap=cmap,orientation='horizontal')
        #P.contour(im,np.asarray([9,16,25,50,100,1000])**(0.5 if scale else 1))
        #P.contour(im,10)
        #contours = np.asarray([9,16,25,36,49,64,81,100,225,400,625,900,1225,1600])**(0.5 if scale else 1)
        #if log_transform: contours = np.log10(contours)
        #P.contour(im,contours)
        if label_1FGL:
            names, skydirs = self.get_1FGL_sources(z)
            for na, sd in zip(names, skydirs):
                z.plot_source(na,
                              sd,
                              color='gray' if thresh_low > 0 else 'white')
        if labels is not None:
            try:
                names, skydirs = labels
            except:
                skydirs = labels
                names = ['S%d' % (i) for i in xrange(len(labels))]
            for na, sd in zip(names, skydirs):
                z.plot_source(na,
                              sd,
                              color='gray' if thresh_low > 0 else 'white')
        return z
        #colorbar = ColorbarBase(axes,orientation='vertical',cmap=cmap)

    def make_3panel(self,
                    center,
                    size=10,
                    pixelsize=0.02,
                    galactic=False,
                    scale=1,
                    label_1FGL=True,
                    labels=None,
                    separate_figures=False,
                    fignum_base=10):

        import pylab as P
        from matplotlib.colorbar import ColorbarBase
        from matplotlib.colors import Normalize
        from uw.utilities.image import ZEA

        cmap = P.cm.jet
        cmap.set_bad('white')

        if separate_figures:
            axes = []
            for i in xrange(1, 4):
                P.figure(i + fignum_base)
                axes += [P.gca()]
        else:
            axes = [P.subplot(1, 3, i) for i in xrange(1, 4)]
        zeas = [
            ZEA(center,
                size=size,
                pixelsize=pixelsize,
                galactic=galactic,
                axes=ax) for ax in axes
        ]
        mods = [1, 2, 0]
        for i in xrange(0, 3):
            self.set_mode(mods[i])
            zeas[i].fill(PySkyFunction(self))
            zeas[i].grid()
            axes[i].imshow(zeas[i].image**(0.5 if scale else 1), cmap=cmap)
        if label_1FGL:
            names, skydirs = self.get_1FGL_sources(zeas[0])
            for na, sd in zip(names, skydirs):
                for z in zeas:
                    z.plot_source(na, sd, color='white')
        if labels is not None:
            names, skydirs = labels
            for na, sd in zip(names, skydirs):
                for z in zeas:
                    z.plot_source(na, sd, color='white')
        if separate_figures:
            # basically a "show"
            for i in xrange(1, 4):
                P.figure(i + fignum_base)
                axes[i - 1].set_autoscale_on(True)
                cb = ColorbarBase(axes[i - 1],
                                  orientation='vertical',
                                  cmap=cmap)
                #P.colorbar()
        return axes, zeas
예제 #13
0
class HealpixTSMap(object):
    def __init__(self, hr=None, pickle=None, factor=100, bright_sources=None):
        """hr     :   an instance of HealpixROI
           pickle :   a pickle saved from a previous HealpixTSMap
           factor :   number of intervals to divide base Healpixel side into"""

        self.bright_sources = bright_sources
        if hr is not None: self.setup_from_roi(hr, factor)
        elif pickle is not None: self.load(pickle)
        else:
            print 'Must provide either a HealpixROI instance or a pickle file!'
            raise Exception

    def setup_from_roi(self, hr, factor):

        band1 = hr.band
        band2 = Band(int(round(band1.nside() * factor)))
        rd = band1.dir(hr.index)

        # get pixels within a radius 10% greater than the base Healpix diagonal dimension
        radius = (np.pi / (3 * band1.nside()**2))**0.5 * 2**0.5 * 1.1
        wsdl = WeightedSkyDirList(band2, rd, radius, True)

        # then cut down to just the pixels inside the base Healpixel
        inds = np.asarray([band1.index(x) for x in wsdl])
        mask = inds == hr.index
        dirs = [wsdl[i] for i in xrange(len(mask)) if mask[i]]
        inds = np.asarray([band2.index(x) for x in dirs]).astype(int)

        # sanity check
        if abs(float(mask.sum()) / factor**2 - 1) > 0.01:
            print 'Warning: number of pixels found does not agree with expectations!'

        # calculate TS for each sub-pixel
        tsc = TSCalc(hr.roi)
        if self.bright_sources is not None:
            ts_vals = self.ts_vals = [deque(), deque(), deque()]
            bsm = np.asarray([
                x.source_name in self.bright_sources for x in hr.roi.psm.models
            ])
            for d in dirs:
                ts_vals[0].append(tsc(d))
                ts_vals[1].append(tsc(d, repeat_diffuse=True))
                ts_vals[2].append(
                    tsc(d, repeat_diffuse=True, bright_source_mask=bsm))
        else:
            self.ts_vals = ts_vals = [deque(), deque()]
            for d in dirs:
                ts_vals[0].append(tsc(d))
                ts_vals[1].append(tsc(d, repeat_diffuse=True))

        self.band1 = band1
        self.band2 = band2

        sorting = np.argsort(inds)
        self.inds = inds[sorting]
        for i in range(len(ts_vals)):
            ts_vals[i] = np.asarray(ts_vals[i])[sorting]

        self.previous_index = -1
        self.index = hr.index
        self.mode = 0
        self.ts = self.ts_vals[0]

    def dump(self, filename):
        d = dict()
        d['inds'] = self.inds
        d['ts_vals'] = self.ts_vals
        d['nside1'] = self.band1.nside()
        d['nside2'] = self.band2.nside()
        d['index'] = self.index
        dump(d, file(filename, 'w'))

    def load(self, filename):
        d = load(file(filename))
        self.inds = d['inds']
        self.band1 = Band(d['nside1'])
        self.band2 = Band(d['nside2'])
        if 'ts_vals' in d.keys():
            self.ts_vals = d['ts_vals']
        else:
            dim = (self.band2.nside() / self.band1.nside())**2
            self.ts_vals = np.empty([3, dim])
            self.ts_vals[:] = np.nan
        self.index = d['index']
        self.ts = self.ts_vals[0]
        self.previous_index = -1
        self.mode = 0

    def pyskyfun(self):
        return PySkyFunction(self)

    def __call__(self, v, skydir=None):
        sd = skydir or SkyDir(Hep3Vector(v[0], v[1], v[2]))
        if self.band1.index(sd) != self.index: return np.nan
        id = self.band2.index(sd)
        if id != self.previous_index:
            self.previous_value = self.ts[np.searchsorted(self.inds, id)]
            self.previous_index = id
        return self.previous_value

    def multipix_call(self, sd):
        """A faster version of the skydir lookup where it assumed that the argument
           lies within the boundaries of this Healpixel."""
        id = self.band2.index(sd)
        if id != self.previous_index:
            self.previous_value = self.ts[np.searchsorted(self.inds, id)]
            self.previous_index = id
        return self.previous_value

    def set_mode(self, mode=1):
        if mode not in [0, 1, 2]:
            print 'Not a valid mode... taking no action.'
            return
        self.ts = self.ts_vals[mode]
        self.mode = mode