예제 #1
0
def make_regions(file=None, filetype=None, outfile='ds9.reg'):
    '''
    This function will read in the input file of type "filetype" and write out to a DS9 region file. 
    
    Parameters
    ----------
    - file:     filename [string]
    - filetype: type of file, to determine format. supported: 'sextractor', 'scene' [string]
    - outfile:  output filename. default: 'ds9.reg'. [string]
    
    
    '''

    # code to read in the input file

    if (filetype == 'sextractor'):
        reg_list = read_sextractor(infile=file)
        # the list of regions can be written to a DG9 region file:
        write_ds9(reg_list, outfile, coordsys='physical')

    elif (filetype == 'scene'):
        reg_list = read_scene(infile=file)
        # the list of regions can be written to a DG9 region file:
        write_ds9(reg_list, outfile)

    else:
        raise IOError('Input filetype not recognised!')

# adjust coordinates to get pixel (x,y) coordinates

# write out into a region file

    return 0
예제 #2
0
def make_tiles(ra, dec, tile_spacing=0.625, tile_facet_size=0.7):
    ''' Create the tiling for a 0.3'' mosaic of the central 2.5 degree.
    
    Args:
        ra (float): right ascension of the pointing center.
        dec (float): declination of the pointing center.
    Returns:
        facets (ndarray): a 4 x 4 x 2 array with the central RA and DEC of the tiles.
    '''
    spacing = tile_spacing * u.degree
    # Have some overlap
    facet_size = tile_facet_size * u.degree
    facets = np.zeros((4,4,2)) * u.degree#, dtype=(float, 2)) * u.degree
    facetlist = []
    k = 1
    for i in range(4):
        for j in range(4):
            RA = phasecenter.ra + (spacing * (j-1.5) / np.cos((phasecenter.dec + spacing*(i-1.5)).rad))
            DEC = phasecenter.dec + (spacing * (i-1.5))
            facets[i, j, 0] = RA
            facets[i, j, 1] = DEC
            facetlist.append((RA.deg,DEC.deg))
            PARSET = 'msout.storagemanager=dysco\nmsout.storagemanager.databitrate=4\nmsout.storagemanager.weightbitrate=8\nsteps=[shift,avg]\nshift.type = phaseshift\nshift.phasecenter = [{:f}deg, {:f}deg]\navg.type = average\navg.timeresolution = 4\navg.freqresolution = 48.82kHz'.format(RA.deg, DEC.deg)
            with open('shift_to_facet_{:d}.parset'.format(k), 'w') as f:
                f.write(PARSET)
            k += 1
    region_strs = map(lambda pos: 'fk5\nbox({:f},{:f},{:f},{:f},0) # color=green width=4 text=""'.format(*pos, facet_size.value, facet_size.value), facetlist)
    parser = DS9Parser('\n'.join(list(region_strs)))
    regions = parser.shapes.to_regions()
    write_ds9(regions, 'facets.reg')
    return facets
예제 #3
0
    def dagga(field):
        "function to tag sources for dd calibration, very smoky"
        key = 'calibrate_dd'
        #make a skymodel with only dE taggable sources.
        #de_only_model = 'de-only-model.txt'
        de_sources_mode = config[key]['de_sources_mode']
        print("de_sources_mode:", de_sources_mode)
       # if usepb:
       #    model_cube = prefix+"-DD-precal.cube.int.model.fits"
       # else:
       #    model_cube = prefix+"-DD-precal.cube.app.model.fits"
        outdir = field+"_ddcal"
        if de_sources_mode == 'auto':
           print("Carrying out automatic source taggig for direction dependent calibration")
           caracal.log.info('Carrying out automatic dE tagging')

           catdagger_opts = {
            "ds9-reg-file": "de-{0:s}.reg:output".format(field),
            "ds9-tag-reg-file" : "de-clusterleads-{0:s}.reg:output".format(field),
            "noise-map" : prefix+"_"+field+"-DD-precal.app.residual.fits",
            "sigma" : config[key]['sigma'],
            "min-distance-from-tracking-centre" : config[key]['min_dist_from_phcentre'],
           }

           recipe.add('cab/catdagger', 'tag_sources-auto_mode', catdagger_opts,input=INPUT,
              output=OUTPUT+"/"+outdir,label='tag_sources-auto_mode::Tag dE sources with CatDagger',shared_memory=shared_mem)

        if de_sources_mode == 'manual':
           img = prefix+"_"+field+"-DD-precal.app.restored.fits"
           imagefile = os.path.join(pipeline.output,DD_DIR,outdir,img)
           #print("Imagefile",imagefile)
           #print("Pipeline output", pipeline.output)
           w = WCS(imagefile)
           #coords =  config[key]['de_sources_manual']
           print(de_dict)
           sources_to_tag = de_dict[field.replace("_","-")]
           reg = []
           for j in range(len(sources_to_tag.split(";"))):
               coords = sources_to_tag.split(";")[j]
               size = coords.split(",")[2]
               coords_str = coords.split(",")[0]+" "+coords.split(",")[1]
               #print("Coordinate String", coords_str)
               centre = SkyCoord(coords_str, unit='deg')
               separation = int(size) * u.arcsec
               #print("Size",separation)
               xlist = []
               ylist = []
               for i in range(5):
                 ang_sep = (306/5)*i*u.deg
                 p = centre.directional_offset_by(ang_sep,separation)
                 pix = PixCoord.from_sky(p,w)
                 xlist.append(pix.x)
                 ylist.append(pix.y)
               vertices = PixCoord(x=xlist, y=ylist)
               region_dd = PolygonPixelRegion(vertices=vertices)
               reg.append(region_dd)
           regfile = "de-{0:s}.reg".format(field)
           ds9_file = os.path.join(OUTPUT,outdir,regfile)
           write_ds9(reg,ds9_file,coordsys='physical')
예제 #4
0
 def write_region(cls, coords, filename, **kwargs):
     try:
         iter(coords)
     except TypeError as te:
         raise Exception('Coords must be iterable')
     circles = []
     for coord in coords:
         center = utils.get_skycoord(coord)
         rad = utils.get_angle(coord['rad'])
         circles.append(CircleSkyRegion(center=center, radius=rad, visual=kwargs))
     write_ds9(circles, filename)
예제 #5
0
def FindBoxSource(catalog, GorC, srcReg, freeReg, outfile):
    catalog = LoadModel(catalog)
    model = NewModel()
    for srcName in catalog.SrcList:
        skycrd_C = catalog.GetSrcDir(srcName)
        if GorC == 'C':
            xref, yref = skycrd_C
        if GorC == 'G':
            skycrd_G = maptools.skycrdC2G(skycrd_C)[0]
            xref, yref = skycrd_G
        xmin, xmax, ymin, ymax = srcReg
        if xref > xmin and xref < xmax and yref > ymin and yref < ymax:
            print(srcName, xref, yref)
            srcEle = catalog.GetSrcEle(srcName)
            if srcEle.attrib['type'] == 'PointSource':
                model.AddPointSource(srcName)
            if srcEle.attrib['type'] == 'DiffuseSource':
                spatialFile = srcEle.find('spatialModel').attrib['file']
                model.AddDiffuseSource(srcName, SpatialFile=spatialFile)
            model.AddSrcEle(srcName, srcEle)
    model.SaveModel(outfile)

    regionList = []
    model = LoadModel(outfile)
    for srcName in model.SrcList:
        skycrd_C = catalog.GetSrcDir(srcName)
        center = SkyCoord(*skycrd_C, unit='deg')
        region = PointSkyRegion(center)
        regionList.append(region)

        if GorC == 'C':
            xref, yref = skycrd_C
        if GorC == 'G':
            skycrd_G = maptools.skycrdC2G(skycrd_C)[0]
            xref, yref = skycrd_G
        xmin, xmax, ymin, ymax = freeReg
        if xref < xmin or xref > xmax or yref < ymin or yref > ymax:
            print(srcName, xref, yref)
            for parName in model.FreeParDict[srcName]:
                print(parName)
                model.SetParFree(srcName, parName, 0)
    model.SaveModel(outfile)

    regfile = outfile.split('.')[0] + '.reg'
    write_ds9(regionList, regfile)
예제 #6
0
def FindCircleSource(catalog, skycrd0_C, srcRad, freeRad, outfile):
    catalog = LoadModel(catalog)

    model = NewModel()
    for srcName in catalog.SrcList:
        skycrd_C = catalog.GetSrcDir(srcName)
        rad = maptools.Sep(skycrd_C, skycrd0_C)
        if rad < srcRad:
            print(srcName, rad)
            srcEle = catalog.GetSrcEle(srcName)
            if srcEle.attrib['type'] == 'PointSource':
                model.AddPointSource(srcName)
            if srcEle.attrib['type'] == 'DiffuseSource':
                spatialFile = srcEle.find('spatialModel').attrib['file']
                model.AddDiffuseSource(srcName, SpatialFile=spatialFile)
            model.AddSrcEle(srcName, srcEle)
    model.SaveModel(outfile)

    regionList = []
    model = LoadModel(outfile)
    for srcName in model.SrcList:
        skycrd_C = catalog.GetSrcDir(srcName)
        center = SkyCoord(*skycrd_C, unit='deg')
        region = PointSkyRegion(center)
        regionList.append(region)

        rad = maptools.Sep(skycrd_C, skycrd0_C)
        if rad > freeRad:
            print(srcName, rad)
            for parName in model.FreeParDict[srcName]:
                print(parName)
                model.SetParFree(srcName, parName, 0)
    model.SaveModel(outfile)

    regfile = outfile.split('.')[0] + '.reg'
    write_ds9(regionList, regfile)
예제 #7
0
# Python script of generating DS9 region file
# from IRAF output mag.1 file
# written by Duho Kim (1/18/18)        
######################################################
import numpy as np
from astropy.io import ascii
from astropy.table import Table
from regions import DS9Parser, write_ds9

work_dir = '/Users/dhk/work/data/NGC_IC/pilot_script/'

mag1 = ascii.read(work_dir+'ic1065.mag.1')


reg_string = 'galactic\ncircle(42,43,3) # color=green'

parser = DS9Parser(reg_string)
parser.run()


reg = Table(names=('shape','x','y','rad'),dtype=('S6','f8','f8','f8'))

for i in range(len(mag1)):
	write_ds9('image\ncircle('+mag1['XCENTER'][i]+','+mag1['YCENTER'][i]+')')
	reg.add_row( ('circle',mag1['XCENTER'][i],mag1['YCENTER'][i],np.sqrt(mag1['AREA'][i]/np.pi)) )

reg.write(work_dir+'ic1065.reg',format='ascii.commented_header',comment='# Region file format: DS9 version 4.1
global color=green dashlist=8 3 width=1 font="helvetica 10 normal roman" select=1 highlite=1 dash=0 fixed=0 edit=1 move=1 delete=1 include=1 source=1')


예제 #8
0
def main(argv=None):
    """ Main Function """
    # Call initial parser from init_utils
    parser = ap.ArgumentParser(description="""Create Region Files.""",
                               add_help=True)

    parser.add_argument(
        "-s",
        "--shotid",
        help="""Shot identifier, an integer""",
        type=int,
        default=None,
    )

    parser.add_argument(
        "-d",
        "--date",
        help="""Date, e.g., 20170321, YYYYMMDD""",
        type=str,
        default=None,
    )

    parser.add_argument(
        "-o",
        "--observation",
        help='''Observation number, "00000007" or "7"''',
        type=str,
        default=None,
    )

    parser.add_argument(
        "-f",
        "--field",
        help="""Options=""",
        type=str,
        default=None,
    )

    args = parser.parse_args(argv)
    args.log = setup_logging()

    if args.field is not None:

        S = Survey()
        survey_table = S.return_astropy_table()
        sel_field = survey_table["field"] == args.field
        ifuregions = []

        for row in survey_table[sel_field]:
            args.log.info("Working on " + str(row["shotid"]))
            ifuregions.extend(get_regions_from_flim(row["shotid"]))

        outname = args.field

    elif args.shotid:
        ifuregions = get_regions_from_flim(args.shotid)
        outname = str(args.shotid)

    elif args.date is not None:
        if args.observation is not None:
            shotid = int(str(args.date) + str(args.observation).zfill(3))
            ifuregions = get_regions_from_flim(shotid)
            outname = str(shotid)

    region_file = outname + '.reg'
    write_ds9(ifuregions, region_file)
          overwrite=True)

reglist = [
    regions.CircleSkyRegion(
        coordinates.SkyCoord(row['RA'],
                             row['Dec'],
                             frame='fk5',
                             unit=(u.hour, u.deg)),
        radius=(u.Quantity(float(row['robs']) * 1000, u.au) /
                (8.5 * u.kpc)).to(u.arcsec, u.dimensionless_angles()),
        meta={'text': row['ID']},
        visual={'name': row['ID']},
    ) for row in tbl if row['ID']
]

regions.write_ds9(reglist,
                  paths.rpath('Schmiedeke2016_HIIregions_tableB1.reg'))

rslt = requests.get(
    'http://www.aanda.org/articles/aa/full_html/2016/04/aa27311-15/T2.html')
soup = BeautifulSoup(rslt.text, 'html5lib')
htmltable = soup.findAll('table')[-1]

allrows = (htmltable.findAll('tr'))

colnames_part1 = [
    x.text.strip("a0123456789\n \t") for x in allrows[0].findAll('td')
]
units = [x.text.strip() for x in allrows[1].findAll('td')]
colnames_part2 = [
    x.text.strip("0123456789()\n \t") for x in allrows[2].findAll('td')
]
            pixX, pixY = (pngX / (2487 / 2100)) / .5, ((1306 - pngY) /
                                                       (1306 / 1100)) / .5
        else:
            print('what the hell happened!?!')
            break
        xy = np.column_stack((pixX, pixY))
        print(header)
        w = WCS(imgHeader)
        coords = w.wcs_pix2world(xy, 1)
        raDec = SkyCoord(coords[0][0] * u.deg, coords[0][1] * u.deg)
        region = CircleSkyRegion(raDec, regRadius * u.deg)
        region.visual['color'] = 'red'
        region.visual['width'] = '2'
        header = Path(header).stem + '_' + str(imgName)
        print(header)
        regName = regFile.joinpath(header).with_suffix('.reg')
        print(regName)
        write_ds9([region], regName)
    except:
        pass

regfiles = sorted(regFile.glob('*reg'))
for rf, x in zip(regfiles, range(len(regfiles) - 1)):
    if regfiles[x].stem[:regfiles[x].stem.find('_', 8)] != regfiles[
            x + 1].stem[:regfiles[x].stem.find('_', 8)]:
        print('break')
        fp.close(regfiles[x].stem[:regfiles[x].stem.find('_', 8)])
    else:
        print('match')
        fp.open()
예제 #11
0
	region = CircleSkyRegion(center, radius, meta)
	return region

# define path to the main directory
if getpass.getuser() == "luisabuzzo":
    home = "/home/luisabuzzo/Work/Master/SPLUS/"
elif getpass.getuser() == "mlgbuzzo":
    home = "/home/mlgbuzzo/LePhare/"
elif getpass.getuser() == "roderik":
    home = "/Users/roderik/Dropbox/splus/IDR2/"

catfile = os.path.join(home,'Catalogs/STRIPE82_all.fits')
data = fits.open(catfile)
cat = data[1].data

#sel = np.logical_and((cat['FIELD'] == 'STRIPE82-0160'),(cat['r_auto']/cat['er_auto'] < 5))
sel = np.logical_and((cat['FIELD'] == 'STRIPE82-0160'),(cat['r_auto'] < 21))

#sel = (cat['FIELD'] == 'STRIPE82-0160')
cat = cat[sel]

radius_arcsec = 2.0
regions = []
for i in range(0,len(cat)):
	regions.append(make_region(cat['RA'][i],cat['Dec'][i],radius_arcsec/3600.,np.int_(cat['PhotoFlag'][i]))) 
#filename = 'tile0160_sn_lt5.reg'
filename = 'tile0160_r_lt21.reg'

write_ds9(regions, filename)

예제 #12
0
def make_cosmological_sources(exp_time, fov, sky_center, cat_center=None,
                              absorb_model="wabs", nH=0.05, area=40000.0,
                              output_sources=None, write_regions=None,
                              prng=None):
    r"""
    Make an X-ray source made up of contributions from
    galaxy clusters, galaxy groups, and galaxies. 

    Parameters
    ----------
    exp_time : float, (value, unit) tuple, or :class:`~astropy.units.Quantity`
        The exposure time of the observation in seconds.
    fov : float, (value, unit) tuple, or :class:`~astropy.units.Quantity`
        The field of view in arcminutes.
    sky_center : array-like
        The center RA, Dec of the field of view in degrees.
    cat_center : array-like
        The center of the field in the coordinates of the
        halo catalog, which range from -5.0 to 5.0 in 
        degrees in both directions. If None is given, a 
        center will be randomly chosen.
    absorb_model : string, optional
        The absorption model to use, "wabs" or "tbabs". Default: "wabs"
    nH : float, (value, unit) tuple, or :class:`~astropy.units.Quantity`, optional
        The hydrogen column in units of 10**22 atoms/cm**2. 
        Default: 0.05
    area : float, (value, unit) tuple, or :class:`~astropy.units.Quantity`, optional
        The effective area in cm**2. It must be large enough 
        so that a sufficiently large sample is drawn for the 
        ARF. Default: 40000.
    output_sources : string, optional
        If set to a filename, output the properties of the sources
        within the field of view to a file. Default: None
    write_regions : string, optional
        If set to a filename, output circle ds9 regions corresponding to the
        positions of the halos with radii corresponding to their R500 
        projected on the sky.  Default: None
    prng : :class:`~numpy.random.RandomState` object, integer, or None
        A pseudo-random number generator. Typically will only 
        be specified if you have a reason to generate the same 
        set of random numbers, such as for a test. Default is None, 
        which sets the seed based on the system time.
    """
    exp_time = parse_value(exp_time, "s")
    fov = parse_value(fov, "arcmin")
    if nH is not None:
        nH = parse_value(nH, "1.0e22*cm**-2")
    area = parse_value(area, "cm**2")
    prng = parse_prng(prng)
    cosmo = FlatLambdaCDM(H0=100.0*h0, Om0=omega_m)
    agen = ApecGenerator(0.1, 10.0, 10000, broadening=False)

    mylog.info("Creating photons from cosmological sources.")

    mylog.info("Loading halo data from catalog: %s" % halos_cat_file)
    halo_data = h5py.File(halos_cat_file, "r")

    scale = cosmo.kpc_comoving_per_arcmin(halo_data["redshift"][()]).to("Mpc/arcmin")

    # 600. arcmin = 10 degrees (total FOV of catalog = 100 deg^2)
    fov_cat = 10.0*60.0
    w = construct_wcs(*sky_center)

    cat_min = -0.5*fov_cat
    cat_max = 0.5*fov_cat

    if cat_center is None:
        xc, yc = prng.uniform(low=cat_min+0.5*fov, high=cat_max-0.5*fov, size=2)
    else:
        xc, yc = cat_center
        xc *= 60.0
        yc *= 60.0
        xc, yc = np.clip([xc, yc], cat_min+0.5*fov, cat_max-0.5*fov)

    mylog.info("Coordinates of the FOV within the catalog are (%g, %g) deg." %
               (xc/60.0, yc/60.0))

    xlo = (xc-1.1*0.5*fov)
    xhi = (xc+1.1*0.5*fov)
    ylo = (yc-1.1*0.5*fov)
    yhi = (yc+1.1*0.5*fov)

    mylog.info("Selecting halos in the FOV.")

    halo_x = halo_data["x"][()].astype("float64")/(h0*scale.value)
    halo_y = halo_data["y"][()].astype("float64")/(h0*scale.value)

    fov_idxs = (halo_x >= xlo) & (halo_x <= xhi)
    fov_idxs = (halo_y >= ylo) & (halo_y <= yhi) & fov_idxs

    n_halos = fov_idxs.sum()

    mylog.info("Number of halos in the field of view: %d" % n_halos)

    # Now select the specific halos which are in the FOV
    z = halo_data["redshift"][fov_idxs].astype("float64")
    m = halo_data["M500c"][fov_idxs].astype("float64")/h0
    # We need to compute proper scales here
    s = scale[fov_idxs].to("Mpc/arcsec").value/(1.0+z)
    ra0, dec0 = w.wcs_pix2world((halo_x[fov_idxs]-xc)*60.0,
                                (halo_y[fov_idxs]-yc)*60.0, 1)

    # Close the halo catalog file
    halo_data.close()

    # Some cosmological stuff
    rho_crit = cosmo.critical_density(z).to("Msun/Mpc**3").value

    # halo temperature and k-corrected flux
    kT = Tx(m, z)
    flux_kcorr = 1.0e-14*lum(m, z)/flux2lum(kT, z)

    # halo scale radius
    r500 = (3.0*m/(4.0*np.pi*500*rho_crit))**(1.0/3.0)
    r500_kpc = r500 * 1000.0
    rc_kpc = r500/conc * 1000.0
    rc = r500/conc/s

    # Halo slope parameter
    beta = prng.normal(loc=0.666, scale=0.05, size=n_halos)
    beta[beta < 0.5] = 0.5

    # Halo ellipticity
    ellip = prng.normal(loc=0.85, scale=0.15, size=n_halos)
    ellip[ellip < 0.0] = 1.0e-3

    # Halo orientation
    theta = 360.0*prng.uniform(size=n_halos)

    # If requested, output the source properties to a file
    if output_sources is not None:
        t = Table([ra0, dec0, rc_kpc, beta, ellip, theta, m,
                   r500_kpc, kT, z, flux_kcorr],
                  names=('RA', 'Dec', 'r_c', 'beta', 'ellipticity',
                         'theta', 'M500c', 'r500', 'kT', 'redshift',
                         'flux_0.5_2.0_keV'))
        t["RA"].unit = "deg"
        t["Dec"].unit = "deg"
        t["flux_0.5_2.0_keV"].unit = "erg/(cm**2*s)"
        t["r_c"].unit = "kpc"
        t["theta"].unit = "deg"
        t["M500c"].unit = "solMass"
        t["r500"].unit = "kpc"
        t["kT"].unit = "kT"
        t.write(output_sources, format='ascii.ecsv', overwrite=True)

    if write_regions is not None:
        from regions import CircleSkyRegion, write_ds9
        from astropy.coordinates import Angle, SkyCoord
        regs = []
        for halo in range(n_halos):
            c = SkyCoord(ra0[halo], dec0[halo], unit=("deg", "deg"), frame='fk5')
            scale = cosmo.kpc_proper_per_arcmin(z[halo]).to("kpc/deg")
            r500c = r500_kpc / scale.value
            r = Angle(r500c, 'deg')
            reg = CircleSkyRegion(c, r)
            regs.append(reg)
        write_ds9(regs, write_regions)

    tot_flux = 0.0
    ee = []
    ra = []
    dec = []

    pbar = tqdm(leave=True, total=n_halos, 
                desc="Generating photons from halos ")
    for halo in range(n_halos):
        spec = agen.get_spectrum(kT[halo], abund, z[halo], 1.0)
        spec.rescale_flux(flux_kcorr[halo], emin=emin, emax=emax, 
                          flux_type="energy")
        if nH is not None:
            spec.apply_foreground_absorption(nH, model=absorb_model)
        e = spec.generate_energies(exp_time, area, prng=prng, quiet=True)
        beta_model = BetaModel(ra0[halo], dec0[halo], rc[halo], beta[halo],
                               ellipticity=ellip[halo], theta=theta[halo])
        xsky, ysky = beta_model.generate_coords(e.size, prng=prng)
        tot_flux += e.flux
        ee.append(e.value)
        ra.append(xsky.value)
        dec.append(ysky.value)
        pbar.update()
    pbar.close()

    ra = np.concatenate(ra)
    dec = np.concatenate(dec)
    ee = np.concatenate(ee)

    mylog.info("Created %d photons from cosmological sources." % ee.size)

    output_events = {"ra": ra, "dec": dec, "energy": ee, 
                     "flux": tot_flux.value}

    return output_events
예제 #13
0
 def to_reg(self, filename):
     regions.write_ds9(self.region_list, filename, coordsys="fk5")
예제 #14
0
def make_master_catalog(dat,outfolder,remake_catalog=False,norates=True,maximum_ap=np.inf):
    """makes master catalog for selecting objects

    CATALOG 1 (FOR ME): Objname, RA, DEC, PA, box dimensions, expected Br gamma flux + EW, recessional velocity, RGB,
    nearby OH lines + strengths, sSFR, metallicity, Herschel photometry flag
    CATALOG 2 (CSV): Objname, RA, DEC, equinox (fk5), non-sidereal tracking rate
        -- this is 2' per 10 minutes in direction perpendicular to PA, in [d(RA), d(DEC)]
    CATALOG 3 (CSV): (nearby bright stars)?

    order by brightness, for galaxies with no strong OH lines
    """

    # input catalog DAT has mass, SFR, sSFR, (Br gamma / Pa alpha / H-alpha) (EW/flux/luminosity)

    # additional inputs
    # dictionary of RA, DEC, recessional velocity
    pdat = load_positional_data()
    # list of objects with Herschel information
    hnames = load_herschel_data()
    # PA, box dimensions
    box_data = load_slit_box()

    # remove unobservable galaxies
    lowest_allowed_airmass = 1.6
    min_airmass = is_observable(pdat)
    obs_idx = np.isfinite(min_airmass) & (min_airmass < lowest_allowed_airmass)
    names, min_airmass = pdat['Name'][obs_idx], min_airmass[obs_idx]

    # important observing quantities
    # need exposure time to calculate tracking rate
    slitlength = (30*u.arcsec).to(u.degree)
    exposure_time = 5*u.minute

    # sort by (line flux / photometric area) (surface brightness?)
    # also remove unobservable galaxies here!
    brg_flux = [np.median(dat['Br gamma 21657']['flux'][dat['names'].index(name),:]) for name in names]
    area = []
    for name in names:
        p1, p2 = box_data['phot_size'][box_data['Name']==name.replace(' ','_')][0].split('_')
        longax = np.clip(np.max([int(p1),int(p2)]),-np.inf,maximum_ap)
        area += [30*longax]
    sb = brg_flux/np.array(area)
    nidx = sb.argsort()[::-1]
    names, min_airmass = names[nidx], min_airmass[nidx]

    # Part 1: Rogue's gallery.
    # figure info
    if remake_catalog:
        figsize =  (20,20)
        fs = 10
        dx_txt, dy_txt = 0.1, 0.008
        xs_start, ys_start = 0.01,0.98
        xbox_size, ybox_size = 0.24, 0.11
        dx_box = 0.005

        # already observed
        obsed = ['NGC 3690','NGC 3310', 'NGC 4194', 'NGC 4536', 'Mrk 33', 'NGC 6090', 'Mrk 1490', 'UGCA 166',
                 'NGC_2388','NGC_2798','Mrk_1450','NGC_5194','NGC_5055','NGC_5256','UGC_08696','NGC_4088','IC_4553',
                 'NGC_6052']

        # initialize and start
        xs, ys = xs_start, ys_start
        catnum = 1
        fig = plt.figure(figsize = figsize)
        for i, name in enumerate(names):

            if name in obsed:
                continue

            # RA, dec, cz, hflag
            pidx = pdat['Name'] == name
            ra = str(pdat['RAh'][pidx][0])+'h '+str(pdat['RAm'][pidx][0])+'m '+str(pdat['RAs'][pidx][0])+'s'
            dec = str(pdat['DE-'][pidx][0])+str(pdat['DEd'][pidx][0])+'d '+str(pdat['DEm'][pidx][0])+'m '+str(pdat['DEs'][pidx][0])+'s'
            cz_str = str(pdat['cz'][pidx][0])+ ' km/s'
            hflag = 'has Herschel photometry'
            if name not in hnames:
                hflag = ''

            # PA, box dimensions
            bidx = box_data['Name'] == name.replace(' ','_')
            phot_pa = box_data['phot_pa'][bidx][0]
            aperture = box_data['phot_size'][bidx][0].replace('_',"'x")+"''"

            # physical properties
            didx = np.array(dat['names']) == name
            brg_flux = np.median(dat['Br gamma 21657']['flux'][didx])
            brg_ew = np.median(dat['Br gamma 21657']['ew'][didx])
            mass = np.median(dat['stellar_mass'][didx])
            ssfr = np.log10(np.median(dat['ssfr'][didx]))

            # OH lines
            cz = pdat['cz'][pidx][0]
            lam_cent = 21657*(1+(cz/(3e5)))
            lamlist, strlist = oh_lines(lam_cent,cz)
            lamlist = ", ".join([str(int(lam-lam_cent)) for lam in lamlist])
            strlist = ", ".join([str(int(stren)) for stren in strlist])

            # put it all together
            xt = xs + dx_txt + 0.005
            fig.text(xt,ys+0.001,name,fontsize=fs+2,weight='bold')
            strs = ['RA='+ra,
                    'DEC='+dec,
                    r'log(f$_{\mathrm{Br}\gamma}$)='+'{:.1e}'.format(brg_flux)+r' erg/s/cm$^{2}$',
                    r' EW$_{\mathrm{Br}\gamma}$='+'{:.1f}'.format(brg_ew)+r' $\AA$',
                    r'log(M/M$_{\odot}$)='+'{:.1f}'.format(mass),
                    r' log(sSFR/yr$^{-1}$)='+'{:.2f}'.format(ssfr),
                    r'$\lambda_{\mathrm{Br}\gamma}$='+str(int(lam_cent))+r' $\AA$',
                    r'OH $\Delta \lambda$: '+lamlist+r'$\AA$',
                    'OH strength: '+strlist,
                    'aperture: '+phot_pa+r'$^{\circ}$ PA'+', '+aperture,
                    'min(airmass): '+'{:.2f}'.format(min_airmass[i]),
                    hflag
                    ]
            for i, s in enumerate(strs): fig.text(xt,ys-dy_txt*(i+1),s,fontsize=fs)

            # RGB
            rgb = load_rgb_png(name).swapaxes(0,1)
            ax = fig.add_axes([xs,ys-dx_txt,dx_txt,dx_txt])
            ax.imshow(rgb)
            ax.set_facecolor('white')
            ax.set_axis_off()

            # increment
            xs += xbox_size+dx_box

            # check for right edge of page
            if (xs + xbox_size) > 1:
                ys = ys - ybox_size-dx_box
                xs = xs_start

            # check for off-page
            if (ys-ybox_size) < 0:
                plt.savefig(outfolder+'catalog'+str(catnum)+'.png',dpi=150)
                plt.close()
                fig = plt.figure(figsize = figsize)
                catnum += 1
                xs, ys = xs_start, ys_start

    # Part 2: target list
    # Objname, RA, DEC, equinox (fk5), non-sidereal tracking rate
    # RA: Specified in sexagesimal hours, minutes and seconds.  Internal fields are separated by spaces.
    # DEC:   Specified in sexagesimal degrees, minutes and seconds.
    # equinox: J2000
    # RA_track: arcseconds / second
    # DEC_track: arcseconds / second
    objname_list, ra_list, dec_list, ra_track_list, dec_track_list, slit_pa_list = [[] for i in range(6)]
    for i, name in enumerate(names):
        
        # create coord.SkyCoord object
        # this represents the center of the box
        pidx = pdat['Name'] == name
        ra = str(pdat['RAh'][pidx][0])+'h '+str(pdat['RAm'][pidx][0])+'m '+str(pdat['RAs'][pidx][0])+'s'
        dec = str(pdat['DE-'][pidx][0])+str(pdat['DEd'][pidx][0])+'d '+str(pdat['DEm'][pidx][0])+'m '+str(pdat['DEs'][pidx][0])+'s'
        galcoords = coord.SkyCoord(ra, dec, frame='fk5')

        # grab PA
        bidx = box_data['Name'] == name.replace(' ','_')
        phot_pa = float(box_data['phot_pa'][bidx][0])

        # grab aperture, translate to sky box sizes
        # the given PA describes the position of the FIRST axis
        # if this is not the LONGEST axis, redefine by adding 90 to PA
        # this means we'll need to output a list of PAs (put it in the tracking output)
        aperture = box_data['phot_size'][bidx][0]
        ap1, ap2 = aperture.split('_')
        aps = np.array([float(ap1),float(ap2)])/3600.*u.deg # from arcsec to degrees
        if aps[0] < aps[1]:
            phot_pa -= 90
            if (phot_pa < 0):
                phot_pa += 360
            print name
        shortax, longax = aps.min(), aps.max() 
        longax = np.clip(longax,-np.inf,maximum_ap*u.arcsec)
        shortax = 30*u.arcsecond
        phot_pa_rad = np.pi/180. * phot_pa * u.radian

        # generate starting position
        # check that it has proper distance and PA
        bot_mid = calc_new_position(galcoords, phot_pa_rad, longax.to(u.radian)/2.)
        np.testing.assert_almost_equal(galcoords.separation(bot_mid).to(u.arcsec).value,longax.to(u.arcsec).value/2,decimal=0)
        np.testing.assert_almost_equal(galcoords.position_angle(bot_mid).to(u.degree).value,phot_pa,decimal=1)

        # non sidereal tracking rate, must be output in RA and DEC (arcseconds/hour)
        # we travel LONGAX in EXPOSURE_TIME, in the -PA_CAT_PARALLEL direction
        pa_cat_parallel = np.array([np.sin(phot_pa_rad),np.cos(phot_pa_rad)])
        dist = (-1)*pa_cat_parallel*longax
        rate = dist/exposure_time
        rate = [x.to(u.arcsecond/u.hour) for x in rate]

        # create .region file with proper scan positions
        # for testing purposes
        pclose = [calc_new_position(bot_mid, phot_pa_rad+np.pi/2.*u.radian,slitlength.to(u.radian)/2.),
                  calc_new_position(bot_mid, phot_pa_rad-np.pi/2.*u.radian,slitlength.to(u.radian)/2.)]
        pfar = [coord.SkyCoord(pclose[1].ra+dist[0]/np.cos(pclose[0].dec.to(u.rad)),pclose[1].dec+dist[1]),
                coord.SkyCoord(pclose[0].ra+dist[0]/np.cos(pclose[0].dec.to(u.rad)),pclose[0].dec+dist[1])]
        points = [pfar+pclose]
        sregions = [poly_region(point) for point in points]
        write_ds9(sregions, region_files+name.replace(' ','_')+'.reg')

        # slit pa
        # we need this
        slit_pa = phot_pa - 90
        if (slit_pa < 0):
            slit_pa += 360

        # add to lists for output
        objname_list += [name.replace(' ','_')]
        ra,dec = bot_mid.to_string('hmsdms').split(' ')
        ra_list += [ra.split('h')[0]  + ' ' + ra.split('m')[0].split('h')[-1] + ' ' + ra.split('m')[-1][:-1]]
        dec_list += [dec.split('d')[0]  + ' ' + dec.split('m')[0].split('d')[-1] + ' ' + dec.split('m')[-1][:-1]]
        ra_track_list += [rate[0].value]
        dec_track_list += [rate[1].value]
        slit_pa_list += [slit_pa]

    # sky
    sky_objname, sky_ra, sky_dec = sky_lists()

    # write to CSV
    if norates:
        outloc = outfolder+'target_list_norates.csv'
        with open(outloc, 'w') as f:
                for i in range(len(objname_list)):
                    f.write(objname_list[i]+','+ra_list[i]+','+dec_list[i]+',J2000')#,{:.2f},{:.2f}'.format(
                            #ra_track_list[i],dec_track_list[i]))
                    f.write('\n')

                # write marla objects
                mnames = ['2M00444105+8351358','2M14390944+4953029']
                mcoords = [coord.SkyCoord(11.171077*u.degree, 83.859955*u.degree, frame='fk5'),
                           coord.SkyCoord(219.789356*u.degree, 49.884155*u.degree, frame='fk5')]
                for i in range(2):
                    ra, dec = mcoords[i].to_string('hmsdms').split(' ')
                    ra_str = ra.split('h')[0]  + ' ' + ra.split('m')[0].split('h')[-1] + ' ' + ra.split('m')[-1][:-1]
                    dec_str = dec.split('d')[0]  + ' ' + dec.split('m')[0].split('d')[-1] + ' ' + dec.split('m')[-1][:-1]
                    f.write(mnames[i]+','+ra_str+','+dec_str+',J2000')#,0.0,0.0')
                    f.write('\n')    
                
                for i in range(len(sky_objname)):
                    f.write(sky_objname[i].replace(' ','_')+'_sky,'+sky_ra[i]+','+sky_dec[i]+',J2000')
                    f.write('\n')

    else:
        outloc = outfolder+'target_list.csv'
        with open(outloc, 'w') as f:
            for i in range(len(objname_list)):
                f.write(objname_list[i]+','+ra_list[i]+','+dec_list[i]+',J2000,{:.2f},{:.2f},{:.1f}'.format(
                        ra_track_list[i],dec_track_list[i],slit_pa_list[i]))
                f.write('\n')

            # write marla objects
            mnames = ['2M00444105+8351358','2M14390944+4953029']
            mcoords = [coord.SkyCoord(11.171077*u.degree, 83.859955*u.degree, frame='fk5'),
                       coord.SkyCoord(219.789356*u.degree, 49.884155*u.degree, frame='fk5')]
            for i in range(2):
                ra, dec = mcoords[i].to_string('hmsdms').split(' ')
                ra_str = ra.split('h')[0]  + ' ' + ra.split('m')[0].split('h')[-1] + ' ' + ra.split('m')[-1][:-1]
                dec_str = dec.split('d')[0]  + ' ' + dec.split('m')[0].split('d')[-1] + ' ' + dec.split('m')[-1][:-1]
                f.write(mnames[i]+','+ra_str+','+dec_str+',J2000,0.0,0.0,0.0')
                f.write('\n')    
                   
            for i in range(len(sky_objname)):
                f.write(sky_objname[i].replace(' ','_')+'_sky,'+sky_ra[i]+','+sky_dec[i]+',J2000,0,0,0')
                f.write('\n')
예제 #15
0
        filename = Path(input("Enter path to file: "))
    except (KeyError, TypeError, FileNotFoundError):
        filename = Path(input("perhaps a typo, try again"))
    names = input('image name? ')
    images = sorted(filename.glob(names))
    for names in images:
        image = fits.open(names)
        data = image[0].data
        wcs = WCS(image[0].header)

        # try:
        #     threshold = image[0].header['SATURATE']
        # except (KeyError, TypeError):
        #     threshold = 40000
        threshold = 55000
        tbl = find_peaks(data, threshold, box_size=10, wcs=wcs)
        regions = []

        center = tbl['skycoord_peak']
        for i in range(len(tbl)):
            region = CircleSkyRegion(center[i], radius)
            region.visual['color'] = 'cyan'
            region.visual['width'] = '3'
            regions.append(region)
        write_ds9(regions,
                  names.parent.joinpath('saturated' + names.stem + '.reg'))
        print(names)
        image.close()
    test = input(
        "If there is another image, enter 0. If done, enter any key. ")
예제 #16
0
def dendrocatify(regname,
                 fn,
                 threshold=4,
                 min_npix=100,
                 min_delta=1,
                 cutout=None,
                 cutout_header=None,
                 snr_threshold=5,
                 noiselevel_table='noise_levels.json'):

    noisefilepath = f"{catalog_path}/{noiselevel_table}"
    if os.path.exists(noisefilepath):
        with open(noisefilepath, 'r') as fh:
            noiselevel_table = json.load(fh)
    else:
        noiselevel_table = {}

    print(f"Starting region {regname}: {fn}")
    if cutout_header is None or cutout is None:
        fh = fits.open(fn)
        data = fh[0].data
        header = fh[0].header
        # LONPOLE isn't very relevant and LATPOLE is not part of the coordinate
        # systems we're interested in.  From Calabretta 2002: "LATPOLEa is never
        # required for zenithal projections"
        try:
            del header['LONPOLE']
            del header['LATPOLE']
        except KeyError:
            pass
        ww = wcs.WCS(header)
        pixscale = wcs.utils.proj_plane_pixel_area(ww)**0.5 * u.deg
        reg = cutout_regions[regname].to_pixel(ww)
        mask = reg.to_mask()
        data_sm = convolve_fft(data,
                               Gaussian2DKernel(
                                   (45 * u.arcsec / pixscale).decompose()),
                               allow_huge=True)
        data_filtered = data - data_sm
        err = mad_std(data_filtered)
        cutout = mask.multiply(data_filtered)
        frame = wcs.utils.wcs_to_celestial_frame(ww)

        # TODO: check that this is working - the regions output seem to be offset?
        ww_cutout = ww[mask.bbox.iymin:mask.bbox.iymax,
                       mask.bbox.ixmin:mask.bbox.ixmax]

        # add beam parameters to header
        cutout_header = ww_cutout.to_header()
        cutout_header['BMAJ'] = mustang_beam_fwhm.to(u.deg).value
        cutout_header['BMIN'] = mustang_beam_fwhm.to(u.deg).value
        cutout_header['BUNIT'] = 'Jy/beam'
        cutout_header['TELESCOP'] = 'GBT'
        cutout_header['FREQ'] = mustang_central_frequency.to(u.Hz).value

        avg_noise = mad_std(data, ignore_nan=True)
        filt_avg_noise = mad_std(cutout, ignore_nan=True)
        noiselevel_table[regname] = {
            'noise': avg_noise,
            'filtered_noise': filt_avg_noise
        }
        with open(noisefilepath, 'w') as fh:
            json.dump(noiselevel_table, fh)

    print(
        f"Beginning cataloging.  Noise is {avg_noise:0.4f} before and {filt_avg_noise:0.4f} after filtering"
    )
    radiosource = dendrocat.RadioSource(
        [fits.PrimaryHDU(data=cutout, header=cutout_header)])
    radiosource.nu = mustang_central_frequency
    radiosource.freq_id = 'MUSTANG'
    radiosource.set_metadata()
    print("Running to_dendrogram")
    radiosource.to_dendrogram(
        min_value=err * threshold,
        min_delta=err * min_delta,
        min_npix=min_npix,
    )
    print("Making plot grid")
    radiosource.plot_grid(
        skip_rejects=False,
        outfile=
        f'{catalog_figure_path}/{regname}_dendrocat_thr{threshold}_minn{min_npix}_mind{min_delta}_prerejection.png',
        figurekwargs={'num': 1},
    )
    pl.figure(1).clf()
    #radiosource.autoreject(threshold=5.0)
    rejected = radiosource.catalog[
        'MUSTANG_dend_flux'] / filt_avg_noise < snr_threshold
    #radiosource.catalog.add_column(Column(rejected, name='rejected'))
    radiosource.catalog['rejected'] = rejected.astype('int')
    print("Rejected {0}, kept {1}, of {2} total sources".format(
        radiosource.catalog['rejected'].sum(),
        (1 - radiosource.catalog['rejected']).sum(), len(radiosource.catalog)))
    radiosource.plot_grid(
        skip_rejects=False,
        outfile=
        f'{catalog_figure_path}/{regname}_dendrocat_thr{threshold}_minn{min_npix}_mind{min_delta}_postrejection.png',
        figurekwargs={'num': 1},
    )
    pl.figure(1).clf()
    #dend = astrodendro.Dendrogram.compute(cutout,
    #                                      min_value=err*threshold,
    #                                      min_delta=err*min_delta,
    #                                      verbose=True, min_npix=min_npix,
    #                                      wcs=ww_cutout)
    dend = radiosource.dendrogram

    pl.figure(2).clf()
    ax = pl.gca()
    ax.cla()
    pl.imshow(cutout,
              cmap='gray_r',
              interpolation='none',
              origin='lower',
              vmax=0.01,
              vmin=-0.001)
    pltr = dend.plotter()
    print("Contouring dendrogram leaves")
    for struct in ProgressBar(dend.leaves):
        pltr.plot_contour(ax,
                          structure=struct,
                          colors=['r'],
                          linewidths=[0.9],
                          zorder=5)
        if struct.parent:
            while struct.parent:
                struct = struct.parent
            pltr.plot_contour(ax,
                              structure=struct,
                              colors=[(0, 1, 0, 1)],
                              linewidths=[0.5])

    cntr = pl.gca().collections

    pl.setp([x for x in cntr if x.get_color()[0, 0] == 1], linewidth=0.25)
    pl.setp([x for x in cntr if x.get_color()[0, 1] == 1], linewidth=0.25)
    pl.savefig(
        f'{catalog_figure_path}/{regname}_dend_contour_thr{threshold}_minn{min_npix}_mind{min_delta}.pdf'
    )

    # zoom only for G31
    if regname == 'G31':
        pl.axis((1125.4006254228616, 1670.3650637799306, 1291.6829155596627,
                 1871.8063499397681))
        pl.setp([x for x in cntr if x.get_color()[0, 0] == 1],
                linewidth=0.75)  # Red
        pl.setp([x for x in cntr if x.get_color()[0, 1] == 1],
                linewidth=0.5)  # Green
        pl.savefig(
            f'{catalog_figure_path}/{regname}_dend_contour_thr{threshold}_minn{min_npix}_mind{min_delta}_zoom.pdf'
        )

    #metadata = {'data_unit': u.Jy / u.beam,
    #            'beam_major': 8*u.arcsec,
    #            'beam_minor': 8*u.arcsec,
    #            'wcs': ww_cutout,
    #            'spatial_scale': wcs.utils.proj_plane_pixel_scales(ww_cutout).mean()*u.deg,
    #           }
    #ppcat = astrodendro.pp_catalog(dend, metadata)

    ppcat = radiosource.catalog

    mastercatalog = dendrocat.MasterCatalog(radiosource, catalog=ppcat)
    aperture1 = Circle([0, 0], 10 * u.arcsec, name='10as', frame=frame.name)
    aperture2 = Circle([0, 0], 15 * u.arcsec, name='15as', frame=frame.name)
    background = Annulus([0, 0],
                         inner=15 * u.arcsec,
                         outer=20 * u.arcsec,
                         name='background',
                         frame=frame.name)
    print("Beginning photometry ...")
    mastercatalog.photometer(aperture1, aperture2, background)
    print()

    source_center = coordinates.SkyCoord(mastercatalog.catalog['x_cen'],
                                         mastercatalog.catalog['y_cen'],
                                         unit=(u.deg, u.deg),
                                         frame=frame.name)
    source_name = [
        "G{0:0.3f}{1:+0.3f}".format(sc.galactic.l.deg, sc.galactic.b.deg)
        for sc in source_center
    ]
    mastercatalog.catalog.add_column(
        Column(name='SourceName', data=source_name))

    mastercatalog.catalog.write(
        f'{catalog_path}/{regname}_dend_contour_thr{threshold}_minn{min_npix}_mind{min_delta}.ipac',
        format='ascii.ipac')

    regs = ppcat_to_regions(ppcat, frame.name)
    regions.write_ds9(
        regions=regs,
        filename=
        f'{catalog_path}/{regname}_dend_contour_thr{threshold}_minn{min_npix}_mind{min_delta}.reg'
    )

    return radiosource, dend, mastercatalog, ppcat
import astropy.units as u

imgHeaderPath = Path('headers')
regFile = Path('pixCoords/xyreg.lis')
regDirec = Path('regionFiles/xyregs')
finalReg = Path('regionFiles/skyregs')

arcsec2deg = 1 / 3600
regRadius = 20. * arcsec2deg

fp = open(regFile, 'r')
ll = fp.readlines()
fp.close()

for name in range(len(ll)):
    #     print(regName)
    regName = Path(ll[name])
    print(regName)
    imgName = regName.with_suffix('')
    print(imgName)
    imgName = imgName.with_suffix('')
    print(imgName)
    reg = read_ds9(regDirec.joinpath(regName).with_suffix('.reg'))
    hdr = Header.fromtextfile(
        str(imgHeaderPath.joinpath(imgName).with_suffix('.head')))
    w = WCS(hdr)
    for rr in range(len(reg)):
        reg[rr] = reg[rr].to_sky(wcs=w)

    write_ds9(reg, finalReg.joinpath(imgName).with_suffix('.sky.reg'))
예제 #18
0
    msnamelist = list(map(lambda s: 'P{:d}.ms'.format(int(s)), positions_25mJy['Source_id']))
    print('msout.name=[' + ','.join(msnamelist) + ']')
    msposlist = list(map(lambda x: '[{:f}deg,{:f}deg]'.format(x[0], x[1]), positions_25mJy['RA', 'DEC']))
    print('phasecenter=[' + ','.join(msposlist) + ']')
    region_strs = map(lambda pos: 'fk5\ncircle({:f},{:f},{:f}) # color=red width=2 text="{:s}"'.format(*pos['RA','DEC'], 30. / 3600, str(pos['Source_id'])), positions_25mJy)
    for i in range(len(msnamelist)//10):
        with open('split_25mJy_{:02d}.parset'.format(i), 'w') as f:
            output = PARSET + '\nmsout.name=[' + ','.join(msnamelist[10*i:10*(i+1)]) + ']\n' +\
                     'shift.phasecenter=[' + ','.join(msposlist[10*i:10*(i+1)]) + ']\n'
            f.write(output)

    from regions import DS9Parser, write_ds9
    parser = DS9Parser('\n'.join(list(region_strs)))
    regions = parser.shapes.to_regions()

    write_ds9(regions, 'pointings_25mJy.reg')

def make_tiles(ra, dec, tile_spacing=0.625, tile_facet_size=0.7):
    ''' Create the tiling for a 0.3'' mosaic of the central 2.5 degree.
    
    Args:
        ra (float): right ascension of the pointing center.
        dec (float): declination of the pointing center.
    Returns:
        facets (ndarray): a 4 x 4 x 2 array with the central RA and DEC of the tiles.
    '''
    spacing = tile_spacing * u.degree
    # Have some overlap
    facet_size = tile_facet_size * u.degree
    facets = np.zeros((4,4,2)) * u.degree#, dtype=(float, 2)) * u.degree
    facetlist = []