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 __init__(self, cmds, opt_train=None, inst_filter=None, star_filter=None, mmin=18, mmax=28, n_stars=100, grid_spacing=100, snr_fitting_limits=[10, 200]): self.image = None self.hdu = None self.cmds = cmds self.snr_fitting_limits = snr_fitting_limits self.mag_min = np.min((mmin, mmax)) self.mag_max = np.max((mmin, mmax)) # self.spec_type = spec_type self.n_stars = n_stars self.pixel_sep = grid_spacing self.star_filter = self.cmds[ "INST_FILTER_TC"] if star_filter is None else star_filter self.star_sep = self.pixel_sep * self.cmds["SIM_DETECTOR_PIX_SCALE"] self.star_grid = simcado.source.star_grid(n=self.n_stars, mag_min=self.mag_min, mag_max=self.mag_max, filter_name=self.star_filter, separation=self.star_sep) self.mags = np.linspace(self.mag_min, self.mag_max, self.n_stars) if inst_filter is not None: self.cmds["INST_FILTER_TC"] = inst_filter self.inst_filter = self.cmds["INST_FILTER_TC"] self.optical_train = simcado.OpticalTrain( cmds=self.cmds) if opt_train is None else opt_train cmds["OBS_NDIT"] = 1 cmds["FPA_LINEARITY_CURVE"] = "none" cmds["FPA_CHIP_LAYOUT"] = "small" self.detector = simcado.Detector(cmds=self.cmds) self.star_grid.apply_optical_train(self.optical_train, self.detector) self.x = self.star_grid.x_pix self.y = self.star_grid.y_pix
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 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")
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 for kk in range(1, ndit): hdu = fpa.read_out() im += hdu[0].data.T ################################################################### results, new_im = imf.iter_psf_photometry(im, psf,
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