Research Blog
Welcome to my Research Blog.
This is mostly meant to document what I am working on for myself, and to communicate with my colleagues. It is likely filled with errors!
This project is maintained by ndrakos
To make simulated images of the Miri observations, I am using MIRISim, as outlined here.
One component needed to make these observations is a “scene”, which you can either create in MIRISim from a list of objects, or can input as a FITS file. As detailed in this previous post, I was having trouble creating a scene using the first method (there seemed to be memory issues). Therefore I decided to create a FITS file with all the sources, and input this. Vasily kindly shared his code with me, and I have altered it to create a scene, which I’ll detail in this post.
Here is my code to create the scene. Right now it has no sources, and is just all zeros
######################
# Function
######################
def create_hdul(bounds, pixscale, rota=0):
# Creates an hdul with RA and Dec between the specified bounds. Data is all zeros.
# bounds: [RAmin, RAmax, Decmin, Decmax], degrees
# pixscale: degrees/pixel
# mydata: array to store
ra_length = int( (bounds[1]-bounds[0])/pixscale) #In pixels
dec_length = int((bounds[3]-bounds[2])/pixscale) #In pixels
crval = [bounds[1]-(bounds[1]-bounds[0])/2,bounds[3]-(bounds[3]-bounds[2])/2] #centre
crpix = np.array([ [0,ra_length/2,ra_length-1] , [0,dec_length/2,dec_length-1] ])
world_coord = SkyCoord(ra=[bounds[1],crval[0],bounds[0]],dec=[bounds[2],crval[1],bounds[3]],frame='fk5', unit='deg')
w = fit_wcs_from_points(xy = crpix, world_coords = world_coord,projection="TAN")
#Make hdul
myhdul = fits.HDUList()
myhdul.append(fits.ImageHDU())
#Add header
myhdul[0].header.update(w.to_header())
myhdul[0].header['PC1_1']=-np.cos(rota)
myhdul[0].header['PC1_2']=np.sin(rota)
myhdul[0].header['PC2_1']=np.sin(rota)
myhdul[0].header['PC2_2']=np.cos(rota)#(bounds[3]-bounds[2])/dec_length #.11/3600
myhdul[0].header['CDELT1'] = (bounds[1]-bounds[0])/ra_length
myhdul[0].header['CDELT2'] = (bounds[3]-bounds[2])/dec_length
#Add data
myhdul[0].data = np.zeros((ra_length,dec_length)).T
return myhdul
##########################################
# Create Empty Image
#########################################
print('Set-up')
sources_hdul = create_hdul(bounds, pixscale/3600)
#sources_hdul.writeto('testblank.fits', overwrite=True)
I can generate a stamp of each galaxy using make_model_sources_image
from photutils
and inputting a Sersic model (models.Sersic2D()
from astropy
).
I also need to specify a stamp size. I did a stampsize of:
stamp_size = int(np.ceil(radius[i]*5)*oversample) #pixels
stamp_size = max(stamp_size,5)
This should go out to 5 times the half light radius, and have oversample=10 pixels per arcsecond.
This function takes in the normal Sersic parameters (effective half-light radius, sersic index, ellipticity, position angle and amplitude). These are all included in the DREaM catalog, but most need to be converted.
A special note on the amplitude. I have the flux within the MIRI band, but the code takes in the surface brightness at the half-light radius.
To calculate this, I use the fact that the total luminosity in a sersic profile is given by:
\[L = I_e R_e^2 2 \pi n \dfrac{e^{b_n}}{b_n^{2n}} \Gamma (2n)\]where \(I_e\) is the intensity at the effective radius $R_e$ that enclses half the total light from the model (see these notes).
and then solve for the surface brightness at \(R_e\) by dividing the total flux by \(R_e^2 2 \pi n \dfrac{e^{b_n}}{b_n^{2n}} \Gamma (2n)\).
Now that I have the machinery in place to make stamps of each galaxy, I add them to the scene as follows.
1) Create an HDUList from Stamp
First, I give a wcs to the stamp, and store it as an HDUList.
#Make hdul
myra = ra_list[i]; mydec = dec_list[i]
size_arcsec = stamp_size/oversample # size of stamp in arcsec
mybounds = [myra - size_arcsec/3600/2, myra+ size_arcsec/3600/2, mydec-size_arcsec/3600/2, mydec+size_arcsec/3600/2]
stamp_hdul = create_hdul(mybounds, size_arcsec/stamp_size/3600 )
stamp_hdul[0].data = sersic_stamp.T
stamp_hdul.writeto('teststamp.fits', overwrite=True)
2) Get cut-out of big image
The goal is to map the stamp to the big image. However this is really slow to do on the full image, so instead I use a cutout of the big image. This cutout can be obtained by the function “Coutout2D”. I take the size to be 1.1 times the size of the stamp, just in case there is some pixel rounding error (it would probably be fine really, but this doesn’t slow things down much).
Here is my code for cutting out the desired region “cut_im”, and then creating an HDUList of it.
#Get cut-out
cut_im = Cutout2D(sources_hdul[0].data,wcs=WCS((sources_hdul[0].header)),position=pos,size=(1.1*size_arcsec/3600*u.deg),mode="trim",copy=False)
cut_hdul = create_hdul(bounds, pixscale)
cut_hdul[0].header.update(cut_im.wcs.to_header())
cut_hdul[0].data = cut_im.data
3) Add the stamp to the cutout
Now that I have my cutout region, I want to map the stamp to this cutout.
#Add stamp to cutout
cut_data, footprint = mosaicking.reproject_and_coadd([cut_hdul[0],stamp_hdul[0]],cut_hdul[0].header,reproject_function=reproject_interp,combine_function='sum')
cut_hdul[0].data = cut_data; cut_hdul.writeto('testcut.fits', overwrite=True)
Now this cutout region should have the galaxy added to it, and be in the same WCS as the big scene image!
Example:
This is one galaxy with the stamp on the left, and the cutout on the right. I matched the WCS on these two images in DS9 (Frame > Lock > Frame < WCS), so you can see the cutout is slightly bigger.
4) Store Information
Finally, I want to store this cut-out in my total data:
xmin = cut_im.ymin_original; xmax = cut_im.ymax_original+1
ymin = cut_im.xmin_original; ymax = cut_im.xmax_original+1
sources_hdul[0].data[xmin:xmax,ymin:ymax]=cut_data
Basically I loop through all the galaxies and add them each to the full image.
Here is my full code:
And here is what the data looks like
The galaxies look distributed right, but they appear very small. This is possibly just an issue with how I am displaying the data, but I suspect something is wrong with the units.
I need to double check the positions are correct (at first glance this is okay).
I also want to visually inspect the sizes, fluxes, ect. and see why it looks a little strange
Right now I just have my test catalog in this scene. I need to add the fainter galaxies too. If this is too slow to do on my laptop, it should be quite easy to parallelize: I can just run this code for a subset of galaxies, and then add all the data together.
The current plan is to include the Background and Stars using MIRISim’s functionality. But I may decide to add them directly to this image later. Note that including stars will require a bit of work to determine their brightness in the F770W band.
I already tested I have MiriSim working for FITS images (using Jed’s example). I need to run this on my scene (at a fixed pointing), and then pass it along to e.g. Santosh, Daizhong, and make sure we have things working for the pipeline (and iterate over any problems in my simulation!)
As detailed in the previous post, inputting a pointing and dither pattern might not be the most straight-forward in MIRISim. Daizhong has done a bit of work looking into this, so I can hopefully see what he’s done and adjust the code accordingly.