def test_update(): import simcado as sim cmd = sim.UserCommands() cmd.update({'OBS_EXPTIME': 30}) assert cmd.cmds['OBS_EXPTIME'] == 30 with pytest.raises(KeyError): cmd.update({'NO_EXISTE': 30})
def main(): '''Main function Define source components, commands, psf, detector, etc. here ''' ## Commands to control the simulation #cmds = sim.UserCommands('spectro_HK.config') cmds = sim.UserCommands('spectro_IJ.config') # Optionally set some parameters explicitely. cmds['SPEC_ORDER_LAYOUT'] = "specorders-160904.fits" cmds['OBS_EXPTIME'] = 60 cmds['FPA_LINEARITY_CURVE'] = 'none' cmds['SPEC_INTERPOLATION'] = 'spline' #cmds['SPEC_INTERPOLATION'] = 'nearest' ## Define the source(s) -- Only point sources for the moment specfiles = ['GW_Ori+9mag.fits', 'GW_Ori+9mag.fits'] sourcepos = [[-1, 0], [1, 0]] ## Background spectra - these fill the slit bgfiles = ['atmo_emission.fits'] ## Create source object. The units of the spectra are ## - ph / um for source spectra ## - erg / (um arcsec2) for background spectra srcobj = sc.SpectralSource(cmds, specfiles, sourcepos, bgfiles) ## Load the psf psfobj = sc.prepare_psf("PSF_SCAO_120.fits") # Create detector detector = sim.Detector(cmds, small_fov=False) # Create transmission curve. # Here we take the transmission from the simcado optical train, # this includes atmospheric, telescope and instrumental # transmissivities. # You can create your own transmission by suitably defining # tc_lam (in microns) and tc_val (as numpy arrays). opttrain = sim.OpticalTrain(cmds) tc_lam = opttrain.tc_mirror.lam_orig tc_val = opttrain.tc_mirror.val_orig transmission = interp1d(tc_lam, tc_val, kind='linear', bounds_error=False, fill_value=0.) ## Prepare the order descriptions tracelist = sc.layout.read_spec_order(cmds['SPEC_ORDER_LAYOUT']) # tracelist = list() #for lfile in layoutlist: # tracelist.append(sc.SpectralTrace(lfile)) #sc.do_one_chip(detector.chips[3], srcobj, psfobj, tracelist, cmds, # transmission) sc.do_all_chips(detector, srcobj, psfobj, tracelist, cmds, transmission)
def test_full_sim_with_single_star_double_corr_readout(): cmd = sim.UserCommands() opt = sim.OpticalTrain(cmd) fpa = sim.Detector(cmd) src = sim.source.star(mag=20, filter_name="Ks") src.apply_optical_train(opt, fpa) hdu = fpa.read_out(read_out_type="non_destructive") # "It’s over nine thousand!" - Vegeta Breigh assert np.max(hdu[0].data) > 9000
def make_cluster_hdus(mass=2E4, half_light_radius=1, exptime=3600, show=False): cmd = sim.UserCommands() cmd["OBS_EXPTIME"] = exptime # cmd["SCOPE_PSF_FILE"] = "PSF_MAORY_SCAO_Ks_2.fits" cmd["SCOPE_PSF_FILE"] = "Default_PSF_SCAO.fits" cmd["INST_FILTER_TC"] = "Ks" cmd["FPA_LINEARITY_CURVE"] = "none" cmd["FPA_USE_NOISE"] = "no" cmd["FPA_CHIP_LAYOUT"] = "FPA_chip_layout_centre.dat" opt = sim.OpticalTrain(cmd) fpa = sim.Detector(cmd, small_fov=False) dist_orig = 1E3 cluster = sim.source.cluster(mass=mass, distance=dist_orig, half_light_radius=half_light_radius) x_orig = deepcopy(cluster.x) y_orig = deepcopy(cluster.y) f_orig = deepcopy(cluster.weight) d = np.array([8.5E3, 20E3, 50E3, 200E3, 800E3]) dist_mods = 5 * np.log10(d) - 5 if show: plt.figure(figsize=(15, 5)) for ii, dist_mod in enumerate( dist_mods): # GC=14.5, LMC=18.5, Leo I=21.5, M31=24.5 dist = 10**(1 + dist_mod / 5) cluster.x = x_orig * dist_orig / dist cluster.y = y_orig * dist_orig / dist scale = f_orig * (dist_orig / dist)**2 threshold = 0.000003 scale[scale > threshold] = threshold cluster.weight = scale cluster.apply_optical_train(opt, fpa) hdu = fpa.read_out(OBS_EXPTIME=exptime, filename=f"{int(dist)}kpc_{int(mass)}Msun.fits") if show: plt.subplot(1, 5, ii + 1) plt.imshow(hdu[0].data, norm=LogNorm(), vmin=1.61E5, vmax=1.8E5) if show: plt.show()
def test_flux_from_non_destructive_is_same_as_superfast(): cmd = sim.UserCommands() cmd["FPA_READ_OUT_SCHEME"] = "double_corr" opt = sim.OpticalTrain(cmd) fpa = sim.Detector(cmd) src = sim.source.star(mag=20, filter_name="Ks") src.apply_optical_train(opt, fpa) hdu_nd = fpa.read_out(read_out_type="non_destructive") hdu_sf = fpa.read_out(read_out_type="superfast") sig_nd = np.max(hdu_nd[0].data) - np.min(hdu_nd[0].data) sig_sf = np.max(hdu_sf[0].data) - np.min(hdu_sf[0].data) # is the difference between the signal part fo the two read-outs < 10%? assert sig_nd - sig_sf < 0.1 * sig_sf
def simulate_m4_raw_data(show_plots=False): random_extinction_factor = 0.9 k = simcado.optics.get_filter_curve("Ks") * random_extinction_factor cmd = simcado.UserCommands("HAWK-I_config/hawki.config") cmd["INST_FILTER_TC"] = k cmd["ATMO_BG_MAGNITUDE"] = 13.6 cmd["OBS_EXPTIME"] = 10 cmd["FPA_CHIP_LAYOUT"] = "HAWK-I_config/FPA_hawki_layout_cen.dat" cmd["FPA_LINEARITY_CURVE"] = "HAWK-I_config/FPA_hawki_linearity_ext.dat" opt = simcado.OpticalTrain(cmd) fpa = simcado.Detector(cmd, small_fov=False) if show_plots: plt.plot(opt.tc_source) plt.show() hdu_tbls = [] for i in range(4): hdu_tbls += [ascii.read("M4/M4_chip" + str(i) + "table.dat")] gain = np.array([1.87, 1.735, 1.705, 2.11]) hdus = [] for i in range(4): x = (hdu_tbls[i]["x_corr"] - 1024) * 0.106 y = (hdu_tbls[i]["y_corr"] - 1024) * 0.106 k_m = hdu_tbls[i]["k_m"] src = simcado.source.stars(mags=k_m, x=x, y=y) fpa.chips[0].gain = gain[i] src.apply_optical_train(opt, fpa) hdus += fpa.read_out() for i in range(1, 4): hdus[i] = fits.ImageHDU(data=hdus[i].data, header=hdus[i].header) hdus = fits.HDUList(hdus) hdus.writeto("M4/hawkado_test10.fits", clobber=True)
def show_limiting_mags_micado(): filter_names = ["J", "H", "Ks", "Br-gamma"] bg_mags = [16.5, 14.4, 13.6, 13.6] exptimes = np.array([2.6, 10, 60, 600, 3600, 18000, 36000]) mmins = [19, 19, 18, 16] etcs = [] for i in range(4): cmd = simcado.UserCommands() cmd["FPA_LINEARITY_CURVE"] = None cmd["ATMO_BG_MAGNITUDE"] = bg_mags[i] cmd["INST_FILTER_TC"] = filter_names[i] opt = simcado.OpticalTrain(cmd) etcs += [ETC(cmds=cmd, opt_train=opt, mmin=mmins[i], mmax=30)] plt.figure(figsize=(15, 15)) my_lim_mags = [] for i in range(4): plt.subplot(2, 2, i + 1) my_snr = etcs[i] lim_mags = my_snr.limiting_magnitudes(exptimes=exptimes, plot=True, limiting_sigmas=[5, 10, 250]) # lim_mags = np.array(lim_mags).T my_lim_mags += [lim_mags] for lm, sig in zip(lim_mags, [5, 10, 250]): print( str(filter_names[i]) + " & " + str(sig) + r"\sig & " + str([str(np.round(m, 1))[:4] + r"\m & " for m in lm])[1:-1].replace(",", "").replace("'", "") + r"\\") plt.savefig("images/MICADO_limiting_mags_JHKBrG.png", format="png") plt.savefig("images/MICADO_limiting_mags_JHKBrG.pdf", format="pdf") return my_lim_mags
def run_simcado(): import simcado as sim import os cmd = sim.UserCommands() cmd["OBS_EXPTIME"] = 3600 cmd["OBS_NDIT"] = 1 cmd["INST_FILTER_TC"] = "J" src = sim.source.source_1E4_Msun_cluster() opt = sim.OpticalTrain(cmd) fpa = sim.Detector(cmd) src.apply_optical_train(opt, fpa) fpa.read_out("my_output.fits") is_there = os.path.exists("my_output.fits") os.remove("my_output.fits") return is_there
def background_increases_consistently_with_exptime(): """ Run an empty source for exposure time: (1,2,4,8,16,32,64) mins If true the background level increases linearly and the stdev increases as sqrt(exptime) """ import numpy as np import simcado as sim cmd = sim.UserCommands() cmd["OBS_REMOVE_CONST_BG"] = "no" opt = sim.OpticalTrain(cmd) fpa = sim.Detector(cmd) stats = [] for t in [2**i for i in range(7)]: src = sim.source.empty_sky() src.apply_optical_train(opt, fpa) hdu = fpa.read_out(OBS_EXPTIME=60 * t, FPA_LINEARITY_CURVE=None) im = hdu[0].data stats += [[t, np.sum(im), np.median(im), np.std(im)]] stats = np.array(stats) factors = stats / stats[0, :] bg_stats = [ i == np.round(l**2) == np.round(j) == np.round(k) for i, j, k, l in factors ] return_val = np.all(bg_stats) if not return_val: print(factors) return return_val
def snr_curve(exptimes, mmin=20, mmax=30, filter_name="Ks", aperture_radius=4, cmds=None, **kwargs): """ Get the signal to noise ratios for a series of magnitudes and exposure times This function "observes" a grid of 100 stars equally spaced in the range [``mmin``, ``mmax``] The stars are observed for all times given in ``exptime`` and the SNR for each star is returned for each exposure time. Parameters ---------- exptimes : float, list [s] exposure times for the stars mmin, mmax [mag] minimum and maximum magnitudes tor the SNR curve filter_name : str The name of a filter installed in SimCADO - see ``:func:~simcado.optics.get_filter_set()`` aperture_radius : int [pixels] The radius of the aperture places around each star cmds : UserCommands object Used to control the observation fo the grid of stars Optional Parameters ------------------- **kwargs : Anything that you want to pass to a ``UserCommands`` object Returns ------- snr_array : list of arrays The best fit to the Magnitude-SNR curve for each entry in ``exptimes`` mags : np.ndarray [mag] The magnitudes that the SNR values correspond to. Generally 100 values in a np.linspace range between ``mmin`` and ``mmax`` See Also -------- ``:func:~simcado.optics.get_filter_set()`` """ if isinstance(exptimes, (float, int)): exptimes = [exptimes] paranal_bg = {"J": 16.5, "H": 14.4, "Ks": 13.6} default_cmds = sim.UserCommands() default_cmds["ATMO_EC"] = "none" default_cmds["FPA_USE_NOISE"] = "no" if filter_name in paranal_bg.keys(): default_cmds["ATMO_BG_MAGNITUDE"] = paranal_bg[filter_name] if cmds is not None: default_cmds.update(cmds) default_cmds.update(kwargs) q = sim.simulation._make_snr_grid_fpas(filter_names=[filter_name], mmin=mmin, mmax=mmax, cmds=default_cmds) fpa, src = q[0][0], q[1] mags = np.linspace(mmin, mmax, 100) r = aperture_radius r_out = 48 r_width = 5 snr_array = [] for exptime in exptimes: hdu = fpa.read_out(OBS_EXPTIME=exptime) data = hdu[0].data sq_aps = [] bg_stats = [] for i in range(len(src.x_pix)): x, y = int(src.x_pix[i]), int(src.y_pix[i]) sq_ap = np.copy(data[y - r:y + r + 1, x - r:x + r + 1]) sq_aps += [sq_ap] bg_ap = np.copy(data[y - r_out:y + r_out + 1, x - r_out:x + r_out + 1]) bg_ap[r_width:-r_width, r_width:-r_width] = 0 av, med, std = sigma_clipped_stats(bg_ap[bg_ap != 0]) bg_stats += [[av, med, std]] RON = default_cmds["FPA_READOUT_MEDIAN"] bg_med = np.array([s[1] for s in bg_stats]) bg_std = np.array([s[0] for s in bg_stats]) n_pix = (r * 2 + 1)**2 raw = np.array([np.sum(s) for s in sq_aps]) sig = raw - bg_med * n_pix sig_shot = np.sqrt(sig) bg_shot = np.sqrt(bg_med * n_pix) bg_shot_std = np.sqrt(n_pix) * bg_std e_shot = np.sqrt(n_pix * RON**2) tot_err = np.sqrt(sig_shot**2 + bg_shot**2 + e_shot**2) snr_val = sig / tot_err mask = snr > 10 log_snr = np.log10(snr_val[mask]) p = np.polyfit(mags[mask], log_snr, 2) snr_fit = 10**np.polyval(p, mags) snr_array += [snr_fit] return snr_array, mags
def _make_snr_grid_fpas(filter_names=["J", "H", "Ks"], mmin=22, mmax=32, cmds=None, **kwargs): """ Makes a series of :class:`.Detector` objects containing a grid of stars Parameters ---------- filter_names : list Which filters to use for the images. See ``simcado.optices.get_filter_set()`` mmin, mmax : float [mag] Minimum and maximum magnitudes to use for the grid of stars cmds : simcado.UserCommands A custom set of commands for building the optical train Optional Parameters ------------------- Any Keyword-Value pairs accepted by a :class:`~simcado.commands.UserCommands` object Returns ------- fpas : list A list of :class:`Detector` objects with the grid of stars for each filter len(fpas) == len(filter_names) grid : simcado.Source A :class:`Source` object containing the grids of stars See Also -------- :class:`~simcado.commands.UserCommands` """ if isinstance(filter_names, str): filter_names = [filter_names] if not isinstance(cmds, list): cmds = [cmds] * len(filter_names) fpas = [] grids = [] for filt, cmd in zip(filter_names, cmds): if cmd is None: cmd = sim.UserCommands() #cmd["FPA_USE_NOISE"] = "no" cmd["OBS_NDIT"] = 1 cmd["FPA_LINEARITY_CURVE"] = "none" cmd["FPA_CHIP_LAYOUT"] = "small" cmd.update(kwargs) star_sep = cmd["SIM_DETECTOR_PIX_SCALE"] * 100 grid = sim.source.star_grid(100, mmin, mmax, filter_name=filt, separation=star_sep) grids += [grid] hdus, (cmd, opt, fpa) = sim.run(grid, filter_name=filt, cmds=cmd, return_internals=True) fpas += [fpa] return fpas, grid
def run(src, mode="wide", cmds=None, opt_train=None, fpa=None, detector_layout="small", filename=None, return_internals=False, filter_name=None, exptime=None, sub_pixel=False, **kwargs): """ Run a MICADO simulation with default parameters Parameters ---------- src : simcado.Source The object of interest mode : str, optional ["wide", "zoom"] Default is "wide", for a 4mas FoV. "Zoom" -> 1.5mas cmds : simcado.UserCommands, optional A custom set of commands for the simulation. Default is None opt_train : simcado.OpticalTrain, optional A custom optical train for the simulation. Default is None fpa : simcado.Detector, optional A custom detector layout for the simulation. Default is None detector_layout : str, optional ["small", "centre", "full", "tiny"] Default is "small". "small" - 1x 1k-detector centred in the FoV "tiny" - 128 x 128 pixels centred in the FoV "centre" - 1x 4k-detector centred in the FoV "full" - 9x 4k-detectors filename : str, optional The filepath for where the FITS images should be saved. Default is None. If None, the output images are returned to the user as FITS format astropy.io.HDUList objects. return_internals : bool [False, True] Default is False. If True, the ``UserCommands``, ``OpticalTrain`` and ``Detector`` objects used in the simulation are returned in a tuple: ``return hdu, (cmds, opt_train, fpa)`` filter_name : str, TransmissionCurve Analogous to passing INST_FILTER_TC as a keyword argument exptime : int, float [s] Analogous to passing OBS_EXPTIME as a keyword argument """ if cmds is None: cmds = sim.UserCommands() cmds["INST_FILTER_TC"] = "Ks" if detector_layout.lower() in ("tiny", "small", "centre", "center"): cmds["FPA_CHIP_LAYOUT"] = detector_layout else: cmds["FPA_CHIP_LAYOUT"] = 'full' if mode == "wide": cmds["SIM_DETECTOR_PIX_SCALE"] = 0.004 cmds["INST_NUM_MIRRORS"] = 11 elif mode == "zoom": cmds["SIM_DETECTOR_PIX_SCALE"] = 0.0015 cmds["INST_NUM_MIRRORS"] = 13 else: raise ValueError("'mode' must be either 'wide' or ' zoom', not " + mode) if filter_name is not None: cmds["INST_FILTER_TC"] = filter_name if exptime is not None: cmds["OBS_EXPTIME"] = exptime # update any remaining keywords cmds.update(kwargs) if opt_train is None: opt_train = sim.OpticalTrain(cmds) if fpa is None: fpa = sim.Detector(cmds, small_fov=False) print("Detector layout") print(fpa.layout) print("Creating", len(cmds.lam_bin_centers), "layer(s) per chip") print(len(fpa.chips), "chip(s) will be simulated") src.apply_optical_train(opt_train, fpa, sub_pixel=sub_pixel) if filename is not None: if cmds["OBS_SAVE_ALL_FRAMES"] == "yes": for n in cmds["OBS_NDIT"]: fname = filename.replace(".", str(n) + ".") hdu = fpa.read_out(filename=fname, to_disk=True, OBS_NDIT=1) else: hdu = fpa.read_out(filename=filename, to_disk=True) else: hdu = fpa.read_out() if return_internals: return hdu, (cmds, opt_train, fpa) else: return hdu
def plot_micado_rainbow(ab_mags=False): axs = [[0.1, 0.5, 0.4, 0.4], [0.5, 0.5, 0.4, 0.4], [0.1, 0.1, 0.4, 0.4], [0.5, 0.1, 0.4, 0.4], [0.1, 0.9, 0.8, 0.03]] text_heights = [ np.array([28.3, 27.2, 25.7, 24.6, 22.9, 21.4]) + 1.6, np.array([28.2, 27.2, 25.7, 24.6, 22.9, 21.3]) + 1, np.array([28.3, 27.2, 25.7, 24.6, 22.9, 21.4]) + 0.3, np.array([28.3, 27.2, 25.7, 24.6, 22.9, 21.3]) - 0.9 ] mmins = [19, 19, 18, 16] filter_names = ["J", "H", "Ks", "Br-gamma"] label_names = ["J", "H", "K$_S$", "Br$\gamma$"] ab = [0.9, 1.4, 1.85, 1.85] if ab_mags else [0] * 4 bg_mags = [16.5, 14.4, 13.6, 13.6] exptimes = np.logspace(np.log10(60), np.log10(10 * 3600), 10) plt.figure(figsize=(12, 8)) for i in range(4): filt_name = filter_names[i] cmd = simcado.UserCommands() cmd["FPA_LINEARITY_CURVE"] = None cmd["ATMO_BG_MAGNITUDE"] = 16.5 cmd["INST_FILTER_TC"] = filt_name opt = simcado.OpticalTrain(cmd) micado_etc = ETC(cmds=cmd, opt_train=opt, mmin=mmins[i], mmax=32) map_ax = plt.axes(axs[i]) snrs = micado_etc.snr(exptimes=exptimes, fitted=True) micado_etc.plot_snr_rainbow(exptimes / 3600, snrs, snr_levels=[1, 5, 10, 50, 250, 1000], text_heights=text_heights[i] + ab[i], text_center=5, use_colorbar=False) plt.ylim(18, 31.9) plt.xlim(0, 9.9) plt.ylabel(label_names[i], fontsize=14) if i in [1, 3]: plt.gca().yaxis.tick_right() plt.gca().yaxis.set_label_position("right") if i in [0, 1]: plt.gca().set_xticklabels("") plt.axes(axs[4]) cb = plt.colorbar(cax=plt.gca(), orientation="horizontal") plt.gca().xaxis.tick_top() plt.text(0, 48, "Signal to Noise Ratio ($\sigma$)", horizontalalignment="center", fontsize=14) plt.text(0, 16, "Exposure time [hours]", horizontalalignment="center", fontsize=14) if ab_mags: plt.text(-11.5, 32, "AB magnitudes", rotation=90, verticalalignment="center", fontsize=14) else: plt.text(-11.5, 32, "Vega magnitudes", rotation=90, verticalalignment="center", fontsize=14) plt.savefig("images/MICADO_SNR_Rainbow_JHKBrG_ab.png", format="png") plt.savefig("images/MICADO_SNR_Rainbow_JHKBrG_ab.pdf", format="pdf")
mags = imf.abs_mag_from_mass(masses) + dist_mod radius = 4 n = len(lums) a = px_fov im = np.zeros((a, a)) x, y = np.random.randint(radius, a - radius, (2, n)) xs = 0.004 * (x - a // 2) ys = 0.004 * (y - a // 2) dist = 10**(1 + dist_mod / 5) dist = round(dist) star_density = round(mass) print("star_density", star_density, "dist", dist, "mass", mass) cmd = sim.UserCommands() cmd["OBS_EXPTIME"] = exptime cmd["SCOPE_PSF_FILE"] = psf_name cmd["INST_FILTER_TC"] = "Ks" cmd["FPA_LINEARITY_CURVE"] = "none" cmd["FPA_USE_NOISE"] = "no" cmd["FPA_CHIP_LAYOUT"] = "FPA_chip_layout_2as.dat" opt = sim.OpticalTrain(cmd) fpa = sim.Detector(cmd, small_fov=False) src = sim.source.stars(mags=mags, x=xs, y=ys) src.apply_optical_train(opt, fpa) hdu = fpa.read_out() im = hdu[0].data.T
import numpy as np from matplotlib import pyplot as plt from matplotlib.colors import LogNorm import simcado from project.etc import ETC filt_name = "J" cmd = simcado.UserCommands("HAWK-I_config/hawki.config") cmd["FPA_LINEARITY_CURVE"] = None cmd["ATMO_BG_MAGNITUDE"] = 16.5 cmd["INST_FILTER_TC"] = filt_name opt = simcado.OpticalTrain(cmd) hawki_etc = ETC(cmds=cmd, opt_train=opt, mmin=16, mmax=26) exptimes = np.logspace(0.3, 3.55, 10) snrs = hawki_etc.snr(exptimes=exptimes, fitted=True) hawki_etc.plot_snr_rainbow( exptimes / 60, snrs, snr_levels=[1, 5, 10, 50, 250, 1000], text_heights=np.array([21.3, 20, 18.8, 17.5, 15.8, 14.3]) + 3.5, text_center=30) plt.savefig("images/HAWKI_rainbow_J.png", format="png") plt.savefig("images/HAWKI_rainbow_J.pdf", format="pdf")
def plot_background_flux(): #K band 44 photons cm-2 s-1 A-1 - average BG is 13.6 #H band 93 photons cm-2 s-1 A-1 - average BG is 14.4 #J band 193 photons cm-2 s-1 A-1 - average BG is 16.5 # This works out to ~ 1700 ph/pix/dit for J-band and ~12500 ph/pix/dit in K-band # Old calculation was with 4500 and 15000, but this was based on filter widths of 0.26 and 0.4um. # The HAWKI filters are more like 0.15 and 0.35um for J and Ks # Depending on which images we use, J BG flux ranges from 700 to 4000 and K from 12000 to 15000 # This is exactly what we see in the images f0 = np.array([193, 93, 44]) * 1E4 * u.Unit("m-2 s-1 AA-1") area = (4.1**2 - 0.6**2) * np.pi * u.m**2 dlam = np.array([1500, 2900, 3400]) * u.AA exptime = 10 * u.s mag = np.array([16.5, 14.4, 13.6]) mag_corr = 10**(-0.4 * mag) / (u.arcsec**2) pix_size = 0.106**2 * u.arcsec**2 inst_eff = 0.5 gain = 1.7 bg_ph_hawki = f0 * dlam * mag_corr * area * exptime * pix_size * inst_eff * gain print("HAWKI JHK Sky BG: [ADU/pix/dit]", bg_ph_hawki) ### Test the SimCADO background levels for HAWKI - rough calcluation sim_f0 = np.array([ simcado.source.zero_magnitude_photon_flux(i) for i in ["J", "H", "Ks"] ]) * u.Unit("ph/m2/s") print("BG flux JHK [ph/arcsec2/m2/s]", sim_f0 * mag_corr) print("BG flux JHK [ADU/pix/dit]", sim_f0 * mag_corr * area * exptime * pix_size * inst_eff * gain) print("Scale factor for system", area * exptime * pix_size * inst_eff * gain) # ## Create an optical train for the system # Use just the K=13.6 and J=16.5 and scaling a blank spectrum # # For K we get a background flux of ~18000 ph/pix/dit and J ~2500 ph/pix/dit. This is consistent with the upper and lower bounds set by the standard flux values given by theoretical values based on the ESO sky background values and empirical values from the HAWK-I ETC. # # The limits are 15000 < K < 28000 and 2000 < J < 2800 ph/pix/dit # This equates to 10000 < K < 16000 and 1200 < J < 1600 ADU/pix/dit cmd = simcado.UserCommands("HAWK-I_config/hawki.config") cmd["OBS_EXPTIME"] = 10 cmd["INST_FILTER_TC"] = "J" cmd["ATMO_USE_ATMO_BG"] = "yes" cmd["ATMO_BG_MAGNITUDE"] = 16.5 #cmd["ATMO_EC"] = None #cmd["SCOPE_USE_MIRROR_BG"] = "no" #cmd["FPA_USE_NOISE"] = "no" #cmd["FPA_LINEARITY_CURVE"] = None opt = simcado.OpticalTrain(cmd) fpa = simcado.Detector(cmd, small_fov=False) empty_sky = simcado.source.empty_sky() empty_sky.apply_optical_train(opt, fpa) myfits = fpa.read_out(OBS_EXPTIME=10) plt.imshow(myfits[0].data) plt.colorbar() plt.show()
def mimic_image(hdu, catalogue, cmds=None, hdu_ext=0, sim_chip_n=0, return_stamps=False, cat_ra_name="RA", cat_dec_name="DE", cat_filter_name="J", **kwargs): """ Create a SimCADO image to mimic a real FITS file Parameters ---------- hdu : str, astropy.HDUList The original FITS object- either a filename or an astropy.HDUList object catalogue : str, astropy.Table A catalogue of stars - either a filename or an astropy.Table object cmds : str, simcado.UserCommands Commands by which to simulate the image - a filename to a .config file or a UserCommands object hdu_ext : int The extension in the original FITS file which should be simulated sim_chip_n : int Which chip in the FPA_LAYOUT to simulate. Passed to apply_optical_train() and read_out() return_stamps : bool If True, returns two PostageStamps object for the original HDU and the generated HDU cat_ra_name, cat_dec_name, cat_filter_name : str The names of the column in catalogue which point to the RA, Dec and filter magnitudes for the stars Optional Parameters ------------------- As passed to a PostageStamps object "dx" : 0, "dy " : 0, "bg_tile_size" : 24, "stamp_width" : 24, "hot_pixel_threshold" : 3000 Returns ------- hdu_sim, src [, post_real, post_sim] If return_stamps is True, post_real and post_sim are returned Examples -------- :: >>> hdu_real = fits.open("HAWKI.2008-11-05T04_08_55.552.fits") >>> cat = ascii.read("ngc362_cohen.dat") >>> >>> dx, dy = -5, 15 >>> >>> cmd = sim.UserCommands("hawki_ngc362.config") >>> cmd["INST_FILTER_TC"] = "J" >>> cmd["OBS_EXPTIME"] = 10 >>> >>> out = mimic_image(hdu=hdu_real, catalogue=cat, cmds=cmd, hdu_ext=3, ... sim_chip_n=3, return_stamps=True, ... dx=dx, dy=dy) >>> hdu_sim, src, post_real, post_sim = out >>> len(out) 4 """ if isinstance(hdu, str) and os.path.exists(hdu): hdu = fits.open(hdu)[hdu_ext] elif isinstance(hdu, fits.HDUList): hdu = hdu[hdu_ext] else: raise ValueError("hdu must be a filename or an astropy HDU object: " + type(hdu)) if isinstance(catalogue, str) and os.path.exists(catalogue): cat = ascii.read(catalogue) elif isinstance(catalogue, Table): cat = catalogue else: raise ValueError( "catalogue must be a filename or an astropy.Table object: " + type(catalogue)) if isinstance(cmds, str) and os.path.exists(cmds): cmds = sim.UserCommands(cmds) elif isinstance(cmds, sim.UserCommands): pass else: raise ValueError( "cmds must be a filename or an simcado.UserCommands object: " + type(cmds)) fig = plt.figure(figsize=(0.1, 0.1)) apl_fig = aplpy.FITSFigure(hdu, figure=fig) # get the RA DEC position of the centre of the HAWKI FoV xc, yc = hdu.header["CRPIX1"], hdu.header["CRPIX2"] ra_cen, dec_cen = apl_fig.pixel2world(xc, yc) # get the x,y positions in arcsec from the HAWKI FoV centre y = (cat[cat_dec_name] - dec_cen) * 3600 x = -(cat[cat_ra_name] - ra_cen) * 3600 * np.cos(cat[cat_dec_name] / 57.3) mag = cat[cat_filter_name] # make a Source object with the x,y positions in arcsec from the HAWKI FoV centre src = sim.source.stars(mags=mag, filter_name=cat_filter_name, x=x, y=y) opt = sim.OpticalTrain(cmds) fpa = sim.Detector(cmds, small_fov=False) print(sim_chip_n) src.apply_optical_train(opt, fpa, chips=sim_chip_n) hdu_sim = fpa.read_out(chips=sim_chip_n) ## Get the Postage Stamps if return_stamps: params = { "dx": 0, "dy ": 0, "bg_tile_size": 24, "stamp_width": 24, "hot_pixel_threshold": 3000 } params.update(**kwargs) w, h = hdu_sim[0].data.shape mask = (src.x_pix > 0) * (src.x_pix < w) * (src.y_pix > 0) * (src.y_pix < h) xw = cat[cat_ra_name][mask] yw = cat[cat_dec_name][mask] mag = cat[cat_filter_name][mask] # get the x,y pixel positions of the stars in the simulated image xps = src.x_pix[mask] yps = src.y_pix[mask] # get the x,y pixel positions of the stars in the real image, include offset if needed xpr, ypr = apl_fig.world2pixel(xw, yw) xpr += params["dx"] ypr += params["dy"] # get the images from the FITS objects im_sim = np.copy(hdu_sim[0].data) im_sim -= np.median(im_sim) post_sim = PostageStamps(im_sim, x=xps, y=yps, **params) im_real = np.copy(hdu.data) im_real -= np.median(im_real) post_real = PostageStamps(im_real, x=xpr, y=ypr, **params) return hdu_sim, src, post_real, post_sim else: return hdu_sim, src
def test_load_UserCommands(): import simcado as sim cmd = sim.UserCommands() assert type(cmd) == sim.commands.UserCommands