Source code for megabeast.tools.make_naive_maps

import math

import argparse
import numpy as np
import h5py
import itertools as it
from astropy.io import fits
from astropy.table import Table, vstack

from beast.tools.create_background_density_map import (
    calc_nx_ny_from_pixsize,
    make_wcs_for_map,
    get_pix_coords,
)


__all__ = ["create_naive_maps"]


[docs] def create_naive_maps(stats_filename, pix_size=10.0, verbose=False, median=False, chi2mincut=False, weigh_by_av=False): """ Make the naive maps by directly averaging the BEAST results for all the stars in each pixel. Does not account for completeness, hence naive maps! Parameters ---------- stats_filename : string or list of strings name(s) of the catalog(s) of BEAST results pix_size : float (default=10) size of pixels/regions in arcsec median : bool (default=False) calculate the median of the BEAST results (instead of the mean) chi2mincut : int (default=None) place a chi2min cut on the BEAST results. Gives the max threshold. weigh_by_av : bool (default=False) weigh R(V) and f_A by A(V) to determinе R(V) and f_A of the total column of dust in a pixel (as opposed to finding a simple average across a pixel) """ # type of statistic (make a commandline parameter later) # remember to add to output filenames stat_type = "Exp" # read in the full brick catalog if isinstance(stats_filename, str): stats_filename = [stats_filename] cat = Table.read(stats_filename[0]) if len(stats_filename) > 1: for fname in stats_filename[1:]: tcat = Table.read(fname) cat = vstack([cat, tcat]) if chi2mincut: cat = cat[cat['chi2min'] < chi2mincut] # make RA/Dec grid ra = cat["RA"] dec = cat["DEC"] pixsize_degrees = pix_size / 3600 n_x, n_y, ra_delt, dec_delt = calc_nx_ny_from_pixsize(cat, pixsize_degrees) # the ra spacing needs to be larger, as 1 degree of RA == # cos(DEC) degrees on the great circle ra_grid = ra.min() + ra_delt * np.arange(0, n_x + 1, dtype=float) dec_grid = dec.min() + dec_delt * np.arange(0, n_y + 1, dtype=float) # generate the wcs info for the output FITS files w = make_wcs_for_map(ra_grid, dec_grid) # get the pixel coordinates for each source pix_x, pix_y = get_pix_coords(cat, w) # import pdb; pdb.set_trace() # for ease of checking the bin, set x/y coords to integers x = np.floor(pix_x) y = np.floor(pix_y) # setup arrary to store summary stats per pixel sum_stats = ["Av", "Rv", "f_A", "logT", "M_act", "logA"] print("summary stats", sum_stats) n_sum = len(sum_stats) summary_stats = np.zeros((n_y + 1, n_x + 1, n_sum + 1), dtype=float) summary_sigmas = np.zeros((n_y + 1, n_x + 1, n_sum), dtype=float) values_foreach_pixel = { cur_stat: {(i, j): [] for i in range(n_x + 1) for j in range(n_y + 1)} for cur_stat in sum_stats } print('n_x', n_x) print('n_y', n_y) print('len x', np.shape(x)) print('len y', len(y)) # loop through the pixels and generate the summary stats for i in range(n_x + 1): for j in range(n_y + 1): (tindxs,) = np.where((x == i) & (y == j)) if len(tindxs) > 0: summary_stats[j, i, n_sum] = len(tindxs) if verbose: print(i, j, len(tindxs)) for k, cur_stat in enumerate(sum_stats): values = cat[cur_stat + "_" + stat_type][tindxs] # weigh R(V) and f_A by A(V) if weigh_by_av and ("Rv" in cur_stat or "f_A" in cur_stat): # get Av values av_values = cat["Av" + "_" + stat_type][tindxs] values_foreach_pixel[cur_stat][i, j] = values / av_values weights = av_values else: values_foreach_pixel[cur_stat][i, j] = values weights = None if median: summary_stats[j, i, k] = np.median(values) xabs = abs(values - np.median(values)) ** 2. summary_sigmas[j, i, k] = np.sqrt(np.median(xabs)) / math.sqrt(len(values)) else: summary_stats[j, i, k] = np.average(values, weights=weights) summary_sigmas[j, i, k] = np.std(values, ddof=1) / math.sqrt(len(values)) master_header = w.to_header() # Now, write the maps to disk for k, cur_stat in enumerate(sum_stats): map_name = stats_filename[0].replace("stats.fits", "map_" + cur_stat + "_" + str(pix_size) + "arcsec.fits") hdu = fits.PrimaryHDU(summary_stats[:, :, k], header=master_header) hdu.writeto(map_name, overwrite=True) sigma_name = map_name.replace("map", "map_sigma") hdu_sigma = fits.PrimaryHDU(summary_sigmas[:, :, k], header=master_header) hdu_sigma.writeto(sigma_name, overwrite=True) hdu = fits.PrimaryHDU(summary_stats[:, :, n_sum], header=master_header) hdu.writeto(stats_filename[0].replace("stats.fits", "npts.fits"), overwrite=True) # And store all the values in HDF5 format values_name = stats_filename[0].replace("stats.fits", "values_per_pixel.hd5") f = h5py.File(values_name, "w") dt = h5py.special_dtype(vlen=float) for cur_stat in sum_stats: dset = f.create_dataset(cur_stat, (n_x, n_y), dtype=dt) for i, j in it.product(range(n_x), range(n_y)): dset[i, j] = values_foreach_pixel[cur_stat][i, j]
if __name__ == "__main__": # command line params to specify the run directory # and any other needed parameters # commandline parser parser = argparse.ArgumentParser() parser.add_argument( "stats_filename", metavar="fname", type=str, nargs="+", help="Filename(s) of the stats", ) parser.add_argument( "--pix_size", default=10.0, type=float, help="pixel scale [arcsec]" ) parser.add_argument( "--verbose", default=False, type=bool, help="print pixel indices as a check" ) parser.add_argument( "--median", default=False, type=bool, help="find the median of the values" ) parser.add_argument( "--chi2mincut", default=False, type=int, help="max chi2min threshold to place on results" ) parser.add_argument( "--weigh_by_av", default=False, type=bool, help="weigh R(V) or f_A by A(V)" ) args = parser.parse_args() # call the function create_naive_maps(args.stats_filename, pix_size=args.pix_size)