예제 #1
0
def from_cone(ra, dec, error, dateobs):
    localization_name = "%.5f_%.5f_%.5f" % (ra, dec, error)

    center = SkyCoord(ra * u.deg, dec * u.deg)
    radius = error * u.deg

    # Determine resolution such that there are at least
    # 16 pixels across the error radius.
    hpx = HEALPix(pixel_resolution_to_nside(radius / 16, round='up'),
                  'nested', frame=ICRS())

    # Find all pixels in the 4-sigma error circle.
    ipix = hpx.cone_search_skycoord(center, 4 * radius)

    # Convert to multi-resolution pixel indices and sort.
    uniq = moc.nest2uniq(nside_to_level(hpx.nside), ipix)
    i = np.argsort(uniq)
    ipix = ipix[i]
    uniq = uniq[i]

    # Evaluate Gaussian.
    distance = hpx.healpix_to_skycoord(ipix).separation(center)
    probdensity = np.exp(-0.5 * np.square(distance / radius).to_value(
        u.dimensionless_unscaled))
    probdensity /= probdensity.sum() * hpx.pixel_area.to_value(u.steradian)

    models.db.session.merge(
        models.Localization(
            localization_name=localization_name,
            dateobs=dateobs,
            uniq=uniq.tolist(),
            probdensity=probdensity.tolist()))
    models.db.session.commit()

    return localization_name
예제 #2
0
def from_cone(ra, dec, error):
    localization_name = "%.5f_%.5f_%.5f" % (ra, dec, error)

    center = SkyCoord(ra * u.deg, dec * u.deg)
    radius = error * u.deg

    # Determine resolution such that there are at least
    # 16 pixels across the error radius.
    hpx = HEALPix(pixel_resolution_to_nside(radius / 16, round='up'),
                  'nested',
                  frame=ICRS())

    # Find all pixels in the 4-sigma error circle.
    ipix = hpx.cone_search_skycoord(center, 4 * radius)

    # Convert to multi-resolution pixel indices and sort.
    uniq = ligo.skymap.moc.nest2uniq(nside_to_level(hpx.nside),
                                     ipix.astype(np.int64))
    i = np.argsort(uniq)
    ipix = ipix[i]
    uniq = uniq[i]

    # Evaluate Gaussian.
    distance = hpx.healpix_to_skycoord(ipix).separation(center)
    probdensity = np.exp(
        -0.5 * np.square(distance / radius).to_value(u.dimensionless_unscaled))
    probdensity /= probdensity.sum() * hpx.pixel_area.to_value(u.steradian)

    skymap = table.Table(
        [np.asarray(uniq), np.asarray(probdensity)],
        names=['UNIQ', 'PROBDENSITY'])

    return skymap, uniq
def main(pool, distance=20, filename='output_file.txt', nside=64):

    #calculate pole centers
    hp = HEALPix(nside=nside, order='ring', frame=coord.Galactic())
    centers = hp.healpix_to_skycoord(np.arange(0, hp.npix))
    #only keep poles above equator to not redo calculate with opposite pole
    centers = centers[centers.b >= 0.0 * u.deg]
    #pad centers to match to number of processors
    ncenters = centers.shape[0]
    nprocs = pool.size
    if nprocs == 0.:
        nprocs = 1
    ncenters_per_proc = np.ceil(ncenters / float(nprocs))
    npads = nprocs * ncenters_per_proc - ncenters
    skypad = coord.SkyCoord(np.zeros(int(npads)),
                            np.zeros(int(npads)),
                            frame='galactic',
                            unit=u.deg)
    centers = coord.concatenate((centers, skypad))
    #reshape centers so each worker gets a block of them
    centers = centers.reshape(nprocs, int(ncenters_per_proc))
    print('number of workers: ', nprocs)
    print('number of poles: ', ncenters)
    print('number of poles per worker: ', ncenters_per_proc)
    print('number of poles added as padding: ', npads)
    print('shape of poles array: ', np.shape(centers))
    #instantiate worker with filename results will be saved to
    worker = Worker(filename, args.dist)
    #you better work !
    for r in pool.map(worker, list(centers), callback=worker.callback):
        pass
예제 #4
0
def reg2moc(region, moc_field, wcs, moc_order=15):
    """
    Transform a the intersection of moc_field with a Region object into a MOC.
    """
    list_cells = np.array([c for c in moc_field.flattened()])

    hp = HEALPix(nside=2**moc_order, order='nested', frame=ICRS())
    cells_skycoords = hp.healpix_to_skycoord(list_cells)

    mask = region.contains(cells_skycoords, wcs)
    region_moc = MOC(moc_order, list_cells[mask])

    return region_moc
예제 #5
0
 def coordinates(self):
     if type(self.wcs) is dict:
         hp = HEALPix(nside=self.wcs['nside'],
                      order=self.wcs['order'],
                      frame=Galactic())
         coords = hp.healpix_to_skycoord(np.arange(self.map.shape[0]))
         return coords
     else:
         x, y = np.meshgrid(np.arange(self.map.shape[1]),
                            np.arange(self.map.shape[0]),
                            sparse=True)
         coords = self.wcs.pixel_to_world(x, y)
         return coords
def retrieve_gaia_data_for_map():

    if len(argv) == 1:
        data_dir = input('Please enter the path to the output data directory: ')
    else:
        data_dir = argv[1]

    # Read the Galactic Plane survey priority pointing map, identify those
    # pixels above the given priority threshold, and calculate the spatial
    # coordinates of the corresponding pixels:
    ahp = HEALPix(nside=NSIDE, order='ring', frame=TETE())
    map = hp.read_map(path.join(MAPS_DIR,'GalPlane_priority_map_r.fits'))
    NPIX = hp.nside2npix(NSIDE)
    pixels = np.arange(0,NPIX,1, dtype='int')

    priority_min_threshold = 0.4
    index = (map >= priority_min_threshold,1,0)[0]
    priority_healpixels = np.unique(pixels[index])

    priority_coords = ahp.healpix_to_skycoord(priority_healpixels)
    c = priority_coords[0]

    # For each HEALpix pointing, query the Gaia catalog and retrieve a random
    # sampling of the point source catalog for that sky location:
    tap_service = init_tap_service()

    for i in range(0,len(priority_coords),1):
        coord = priority_coords[i]
        if not check_for_existing_output(data_dir, coord):
            try:
                data = run_async_gaia_tap_query(tap_service, coord)
                output_gaia_to_fits(data_dir,data,coord)
            except requests.exceptions.ConnectionError:
                tap_service = init_tap_service()
                data = run_async_gaia_tap_query(tap_service, coord)
                output_gaia_to_fits(data_dir,data,coord)
예제 #7
0
파일: skymaps.py 프로젝트: ecm0/pyburst
class Skymap(object):
    """ 
    A skymap object is an HEALPix map equipped with a custom coordinate system -- from LAL.
    """
    
    def __init__(self, nside, coordsystem, order='nested', array=None):
        """
        grid: HEALPix map object
        nside: HEALPix nside parameter (int, power of 2)
        order: pixel ordering scheme of the HEALPix map
        coordsystem: Coordsystem object that describes the coordinate system  
        Note: 
        The HEALPix map used for the grid is initialized with a dummy ICRS 
        coordinate frame, that is not used in practise as healpy nor astropy 
        don't support ECEF/Geographic coordinate systems. 
        Instead the grid coordinates are defined through a coordinate system
        obtained from the LAL library.
        """

        if array is not None:
            assert len(array) == healpy.nside2npix(nside), "Data array has incorrect size"
        
        self.grid = HEALPix(nside=nside, order=order, frame=ICRS()) 
        self.nside = nside
        self.order = order
        self.coordsystem = coordsystem
        self.data = numpy.empty(healpy.nside2npix(nside)) if array is None else array

    @classmethod
    def like(cls, skymap, coordsystem=None, data=None):
        """
        Instantiate a Skymap object with the same feature as the input
        skymap unless otherwise requested.
        
        skymap: reference Skymap object
        coordsystem: Coordsystem object that defines the coordinate system 
                     of the new Skymap object 
        data: data of the new Skymap object 
        """

        if coordsystem is not None:
            assert coordsystem.is_valid(),  "Unsupported coordinate system"
            
        if data is not None:
            assert len(data) == skymap.grid.npix, 'Input data has wrong dimensions'
            
        return cls(skymap.nside, \
                   coordsystem if coordsystem is not None else skymap.coordsystem, \
                   skymap.order, \
                   data if data is not None else skymap.data)
                   
    def is_nested(self):
        return self.order == 'nested'

    def grid_points(self):
        return [Skypoint(math.radians(p.ra.value), math.radians(p.dec.value), self.coordsystem) \
                for p in self.grid.healpix_to_skycoord(range(self.grid.npix))]

    def feed(self, data):
        """
        Update the skymap data with the given array
        """

        assert len(data) == self.grid.npix, 'Input data has wrong dimensions'
        self.data = data

    def value(self, skypoint):
        """
        Returns the skymap value at a skypoint. The skymap and skypoint
        must have the same coordinate system.
        """
        
        assert self.coordsystem.is_same(skypoint.coordsystem), \
            "The skymap and skypoint must have the same coordinate system"
        
        # Get the pixel index that corresponds to the skypoint coordinates  
        idx = healpy.ang2pix(self.nside, \
                                *skypoint.coords(), \
                                nest=self.is_nested())
        return self.data[idx]
    
    def transformed_to(self, coordsystem):
        """
        Transforms the skymap to another coordinate system

        If initial and target coordinate systems have the same type, the reference
        time of the coordinate system is the only parameter that is changed.
        """

        if self.coordsystem.has_same_type_as(coordsystem):
            return Skymap.like(self, coordsystem=coordsystem)
        
        # Get co-latitude and longitude coordinates of the skygrid in the target coord system 
        colat, lon = healpy.pix2ang(self.nside, \
                                    numpy.arange(healpy.nside2npix(self.nside)), \
                                    nest=self.is_nested())
        
        # Map target to original coordinates
        points = [Skypoint(l, math.pi/2-c, coordsystem).transformed_to(self.coordsystem) \
                                  for l, c in zip(lon, colat)]
        
        # Transform the list of coordinate tuples [(lon, lat), ...] into two lists [lons, lats]
        coords_rot = [p.coords() for p in points]
        (colat_rot, lon_rot) = tuple(map(list,zip(*coords_rot)))
 
        # Compute skymap in target coord system: interpolate the skymap at points that map to target coords
        data_rotated = healpy.get_interp_val(self.data, numpy.array(colat_rot), numpy.array(lon_rot), \
                                             nest=self.is_nested())
        
        # Create target skymap and update its data 
        return Skymap.like(self, coordsystem=coordsystem, data=data_rotated)
    
    def argmin(self, label = 'skymap minimum'):
        """
        Returns the location of the skymap minimum
        """
        
        coords = healpy.pix2ang(self.nside,numpy.argmin(self.data), nest=self.is_nested())
        return Skypoint(coords[1], math.pi/2-coords[0], self.coordsystem, \
                             label + " (val={0:.2f})".format(numpy.min(self.data)))
    
    def display(self, title, cmap_name='gray_r'):
        """
        Display the skymap
        """
        
        cmap = plt.get_cmap(cmap_name)
        cmap.set_under('w')
        healpy.mollview(self.data, \
                    nest=self.is_nested(), cmap=cmap, \
                    title=title + " ({})".format(self.coordsystem))
예제 #8
0
cmb_map = hpy.pixelfunc.ud_grade(map1, nside, order_in = 'RING', order_out = 'RING')

##### Convert to Coordinates #####

# initialise and pre allocate arrays for speed
x = np.zeros(len(cmb_map))
y = np.zeros(len(cmb_map))
z = np.zeros(len(cmb_map))
temp = cmb_map
coords = []
xf = np.zeros(len(cmb_map))
yf = np.zeros(len(cmb_map))
zf = np.zeros(len(cmb_map))

# get celestial coordinates
coords = hp.healpix_to_skycoord(np.arange(len(cmb_map)))
print coords

# store cartesian coordinates of each data point
# This is for a plain sphere with no height attribute
for i in range(0,len(cmb_map)):
    x[i], y[i], z[i] = hpy.pix2vec(nside, i, nest = False)
    r = 30
    theta = m.acos(z[i]/m.sqrt(m.pow(x[i],2)+m.pow(y[i],2)+m.pow(z[i],2)))
    phi = m.atan2(y[i],x[i])
    xf[i] = (r*m.sin(theta)*m.cos(phi))
    yf[i] = (r*m.sin(theta)*m.sin(phi))
    zf[i] = (r*m.cos(theta))

# open file to write data
file = open('plaindata.txt', 'w')
    unique_pixels = list(np.unique(np.array(pixels)))

    return unique_pixels


NSIDE = 64
footprint_maps_dir = getenv('FOOTPRINT_MAPS_DIR')
map = hp.nside2npix(NSIDE)
priority_map = hp.read_map(
    path.join(footprint_maps_dir, 'GalPlane_priority_map_r.fits'))

ahp = HEALPix(nside=NSIDE, order='ring', frame=TETE())
(high_priority_regions, regions_outside_plane
 ) = science_priority_regions.fetch_priority_region_data(ahp)

unique_pixels = condense_pixel_list(high_priority_regions,
                                    regions_outside_plane)

coords = ahp.healpix_to_skycoord(unique_pixels)

priority_values = priority_map[unique_pixels]

output = open(path.join(footprint_maps_dir, 'GalPlane_pointings_list.txt'),
              'w')
output.write('# Field center RA, Dec [deg]  Priority\n')
for i, c in enumerate(coords):
    output.write(
        str(c.ra.deg) + ' ' + str(c.dec.deg) + ' ' + str(priority_values[i]) +
        '\n')
output.close()
예제 #10
0
파일: skymaps.py 프로젝트: canocy/pyburst
class Skymap(object):
    """ 
    A skymap object is an HEALPix map equipped with a custom coordinate system -- from LAL.
    """
    def __init__(self, nside, coordsystem, order='nested', array=None):
        """
        grid: HEALPix map object
        nside: HEALPix nside parameter (int, power of 2)
        order: pixel ordering scheme of the HEALPix map
        coordsystem: Coordsystem object that describes the coordinate system  
        Note: 
        The HEALPix map used for the grid is initialized with a dummy ICRS 
        coordinate frame, that is not used in practise as healpy nor astropy 
        don't support ECEF/Geographic coordinate systems. 
        Instead the grid coordinates are defined through a coordinate system
        obtained from the LAL library.
        """

        if array is not None:
            assert len(array) == healpy.nside2npix(
                nside), "Data array has incorrect size"

        self.grid = HEALPix(nside=nside, order=order, frame=ICRS())
        self.nside = nside
        self.order = order
        self.coordsystem = coordsystem
        self.data = numpy.empty(
            healpy.nside2npix(nside)) if array is None else array

    @classmethod
    def like(cls, skymap, coordsystem=None, data=None):
        """
        Instantiate a Skymap object with the same feature as the input
        skymap unless otherwise requested.
        
        skymap: reference Skymap object
        coordsystem: Coordsystem object that defines the coordinate system 
                     of the new Skymap object 
        data: data of the new Skymap object 
        """

        if coordsystem is not None:
            assert coordsystem.is_valid(), "Unsupported coordinate system"

        if data is not None:
            assert len(
                data) == skymap.grid.npix, 'Input data has wrong dimensions'

        return cls(skymap.nside, \
                   coordsystem if coordsystem is not None else skymap.coordsystem, \
                   skymap.order, \
                   data if data is not None else skymap.data)

    def is_nested(self):
        return self.order == 'nested'

    def grid_points(self):
        return [Skypoint(math.radians(p.ra.value), math.radians(p.dec.value), self.coordsystem) \
                for p in self.grid.healpix_to_skycoord(range(self.grid.npix))]

    def feed(self, data):
        """
        Update the skymap data with the given array
        """

        assert len(data) == self.grid.npix, 'Input data has wrong dimensions'
        self.data = data

    def value(self, skypoint):
        """
        Returns the skymap value at a skypoint. The skymap and skypoint
        must have the same coordinate system.
        """

        assert self.coordsystem.is_same(skypoint.coordsystem), \
            "The skymap and skypoint must have the same coordinate system"

        # Get the pixel index that corresponds to the skypoint coordinates
        idx = healpy.ang2pix(self.nside, \
                                *skypoint.coords(), \
                                nest=self.is_nested())
        return self.data[idx]

    def transformed_to(self, coordsystem):
        """
        Transforms the skymap to another coordinate system

        If initial and target coordinate systems have the same type, the reference
        time of the coordinate system is the only parameter that is changed.
        """

        if self.coordsystem.has_same_type_as(coordsystem):
            return Skymap.like(self, coordsystem=coordsystem)

        # Get co-latitude and longitude coordinates of the skygrid in the target coord system
        colat, lon = healpy.pix2ang(self.nside, \
                                    numpy.arange(healpy.nside2npix(self.nside)), \
                                    nest=self.is_nested())

        # Map target to original coordinates
        points = [Skypoint(l, math.pi/2-c, coordsystem).transformed_to(self.coordsystem) \
                                  for l, c in zip(lon, colat)]

        # Transform the list of coordinate tuples [(lon, lat), ...] into two lists [lons, lats]
        coords_rot = [p.coords() for p in points]
        (colat_rot, lon_rot) = tuple(map(list, zip(*coords_rot)))

        # Compute skymap in target coord system: interpolate the skymap at points that map to target coords
        data_rotated = healpy.get_interp_val(self.data, numpy.array(colat_rot), numpy.array(lon_rot), \
                                             nest=self.is_nested())

        # Create target skymap and update its data
        return Skymap.like(self, coordsystem=coordsystem, data=data_rotated)

    def argmin(self, label='skymap minimum'):
        """
        Returns the location of the skymap minimum
        """

        coords = healpy.pix2ang(self.nside,
                                numpy.argmin(self.data),
                                nest=self.is_nested())
        return Skypoint(coords[1], math.pi/2-coords[0], self.coordsystem, \
                             label + " (val={0:.2f})".format(numpy.min(self.data)))

    def argmax(self, label='skymap maximum'):
        """
        Returns the location of the skymap maximum
        """

        coords = healpy.pix2ang(self.nside,
                                numpy.argmax(self.data),
                                nest=self.is_nested())
        return Skypoint(coords[1], math.pi/2-coords[0], self.coordsystem, \
                             label + " (val={0:.2f})".format(numpy.max(self.data)))

    def nearest_pixel(
            self,
            skypoint):  ## Modify to accept several points instead of just one
        """
        Returns the nearest pixel's indice of skypoint
        """
        colat, lon = skypoint.coords()
        return healpy.ang2pix(self.nside, colat, lon, nest=self.is_nested())

    def find_greedy_credible_levels(self):
        """Find the greedy credible levels of a (possibly multi-dimensional) array.
        from : https://lscsoft.docs.ligo.org/ligo.skymap/_modules/ligo/skymap/postprocess/util.html#find_greedy_credible_levels

        Returns
        -------
        cls : np.ndarray
            An array with the same shape as slef.data, with values ranging from `0`
            to `self.data.sum()`, representing the greedy credible level to which each
            entry in the array belongs.
        """
        i = numpy.flipud(numpy.argsort(self.data))
        cs = numpy.cumsum(self.data[i])
        cls = numpy.empty_like(self.data)
        cls[i] = cs
        return cls

    def test_skypoint_credible_level(self, skypoint, level=0.9, verbose=False):
        ipix = self.nearest_pixel(skypoint)
        credible_levels = self.find_greedy_credible_levels()
        if np.min(credible_levels) > level:
            if verbose:
                print('No region with this low credible level.')
            if credible_levels[ipix] == np.min(credible_levels):
                if verbose:
                    print(
                        'This skypoint alone have a credible level of {:.3}.'.
                        format(credible_levels[ipix]))
                return True
            else:
                return False
        else:
            return credible_levels[ipix] <= level

    def display(self, title, cmap_name='gray_r'):
        """
        Display the skymap
        """

        cmap = plt.get_cmap(cmap_name)
        cmap.set_under('w')
        healpy.mollview(self.data, \
                    nest=self.is_nested(), cmap=cmap, \
                    title=title + " ({})".format(self.coordsystem))
예제 #11
0
def _npixels_to_coords(npixels, level):
    hp = HEALPix(nside=2**level, order="nested", frame=ICRS())
    return hp.healpix_to_skycoord(npixels)
예제 #12
0
def create_external_skymap(ra, dec, error, pipeline, notice_type=111):
    """Create a sky map, either a gaussian or a single
    pixel sky map, given an RA, dec, and error radius.

    If from Fermi, convolves the sky map with both a core and
    tail Gaussian and then sums these to account for systematic
    effects as measured in :doi:`10.1088/0067-0049/216/2/32`

    If from Swift, converts the error radius from that containing 90% of the
    credible region to ~68% (see description of Swift error
    here:`https://gcn.gsfc.nasa.gov/swift.html#tc7`)

    Parameters
    ----------
    ra : float
        right ascension in deg
    dec: float
        declination in deg
    error: float
        error radius in deg

    Returns
    -------
    skymap : numpy array
        sky map array

    """
    max_nside = 2048
    if error:
        # Correct 90% containment to 1-sigma for Swift
        if pipeline == 'Swift':
            error /= np.sqrt(-2 * np.log1p(-.9))
        error_radius = error * u.deg
        nside = pixel_resolution_to_nside(error_radius, round='up')
    else:
        nside = np.inf
    if nside >= max_nside:
        nside = max_nside

        #  Find the one pixel the event can localized to
        hpx = HEALPix(nside, 'ring', frame=ICRS())
        skymap = np.zeros(hpx.npix)
        ind = hpx.lonlat_to_healpix(ra * u.deg, dec * u.deg)
        skymap[ind] = 1.
    else:
        #  If larger error, create gaussian sky map
        hpx = HEALPix(nside, 'ring', frame=ICRS())
        ipix = np.arange(hpx.npix)

        #  Evaluate Gaussian.
        center = SkyCoord(ra * u.deg, dec * u.deg)
        distance = hpx.healpix_to_skycoord(ipix).separation(center)
        skymap = np.exp(-0.5 * np.square(distance / error_radius).to_value(
            u.dimensionless_unscaled))
        skymap /= skymap.sum()
    if pipeline == 'Fermi':
        # Correct for Fermi systematics based on recommendations from GBM team
        # Convolve with both a narrow core and wide tail Gaussian with error
        # radius determined by the scales respectively, each comprising a
        # fraction determined by the weights respectively
        if notice_type == gcn.NoticeType.FERMI_GBM_FLT_POS:
            # Flight notice
            # Values from first row of Table 7
            weights = [0.897, 0.103]
            scales = [7.52, 55.6]
        elif notice_type == gcn.NoticeType.FERMI_GBM_GND_POS:
            # Ground notice
            # Values from first row of Table 3
            weights = [0.804, 0.196]
            scales = [3.72, 13.7]
        elif notice_type == gcn.NoticeType.FERMI_GBM_FIN_POS:
            # Final notice
            # Values from second row of Table 3
            weights = [0.900, 0.100]
            scales = [3.71, 14.3]
        else:
            raise AssertionError(
                'Need to provide a supported Fermi notice type')
        skymap = sum(weight *
                     hp.sphtfunc.smoothing(skymap, sigma=np.radians(scale))
                     for weight, scale in zip(weights, scales))

    # Renormalize due to possible lack of precision
    return skymap / skymap.sum()
예제 #13
0
def make_plot(args):
    """
    Take the steps to make the plot.

    Parameters
    ----------

    args: array-like
        Command line arguments

    Returns
    -------

    Nothing
    """
    basename = 'PMmap-qso-galactic-aberration'

    gx = 5.04
    gy = -0.10
    gz = -0.29

    if args['quiver']:
        hplevel = 3
    else:
        hplevel = 5
    nside = hp.order2nside(hplevel)
    npix = hp.nside2npix(nside)
    ahp = HEALPix(nside=nside, order='nested', frame=Galactic())

    hpindices = np.arange(npix)
    skycoords = ahp.healpix_to_skycoord(hpindices)

    pm_l_cosb = -gx * np.sin(skycoords.l.to(u.rad)) + gy * np.cos(
        skycoords.l.to(u.rad))
    pm_b = -gx * np.sin(skycoords.b.to(u.rad)) * np.cos(skycoords.l.to(u.rad)) \
           - gy * np.sin(skycoords.b.to(u.rad)) * np.sin(skycoords.l.to(u.rad)) \
           + gz * np.cos(skycoords.b.to(u.rad))
    pmtot = np.sqrt(pm_l_cosb**2 + pm_b**2)

    backgr = plt.imread(
        '../star-trail-animation/sky-images/GaiaSky-colour-2k.png')

    default_proj = ccrs.PlateCarree()
    sky_proj = ccrs.Mollweide()

    fig = plt.figure(figsize=(16, 9),
                     dpi=120,
                     frameon=False,
                     tight_layout={'pad': 0.01})
    gs = GridSpec(1, 1, figure=fig)
    ax = fig.add_subplot(gs[0, 0], projection=sky_proj)
    ax.imshow(np.fliplr(backgr),
              transform=default_proj,
              zorder=-1,
              origin='upper')
    veccolor = plt.cm.get_cmap('tab10').colors[9]
    linecolor = plt.cm.get_cmap('tab10').colors[9]

    if args['quiver']:
        vscale = np.median(pmtot) / 50
        ax.quiver(skycoords.l.value,
                  skycoords.b.value,
                  pm_l_cosb,
                  pm_b,
                  transform=default_proj,
                  angles='xy',
                  scale=vscale,
                  scale_units='dots',
                  color=veccolor,
                  headwidth=4,
                  headlength=4,
                  headaxislength=3.5)
    else:
        if args['colourstreams']:
            ax.streamplot(skycoords.l.value,
                          skycoords.b.value,
                          pm_l_cosb,
                          pm_b,
                          transform=default_proj,
                          linewidth=2.0,
                          density=2,
                          color=pmtot,
                          cmap='viridis',
                          maxlength=0.5,
                          arrowsize=1,
                          arrowstyle=ArrowStyle.Fancy(head_length=1.0,
                                                      head_width=.4,
                                                      tail_width=.4))
        elif args['lwcode'] > 0:
            ax.streamplot(skycoords.l.value,
                          skycoords.b.value,
                          pm_l_cosb,
                          pm_b,
                          transform=default_proj,
                          linewidth=args['lwcode'] * pmtot / np.median(pmtot),
                          density=2,
                          color=linecolor,
                          maxlength=0.5,
                          arrowsize=1,
                          arrowstyle=ArrowStyle.Fancy(head_length=1.0,
                                                      head_width=.4,
                                                      tail_width=.4))
        else:
            ax.streamplot(skycoords.l.value,
                          skycoords.b.value,
                          pm_l_cosb,
                          pm_b,
                          transform=default_proj,
                          linewidth=1.5,
                          density=2.5,
                          color=linecolor,
                          maxlength=0.5,
                          arrowsize=1,
                          arrowstyle=ArrowStyle.Fancy(head_length=1.0,
                                                      head_width=.4,
                                                      tail_width=.4))
    # ax.gridlines()
    ax.invert_xaxis()

    if args['pdfOutput']:
        plt.savefig(basename + '.pdf')
    elif args['pngOutput']:
        plt.savefig(basename + '.png')
    else:
        plt.show()