This notebook measures the 1-D flatfield curve of the red detector. Link to Figure 14.
(The internal hyperlink only works on GitHub Pages or nbviewer. Do not click when viewing the notebook on GitHub.)
import matplotlib.pyplot as plt
import numpy as np
from astropy.io import fits
from astropy.nddata import CCDData
from glob import glob
import os
from astropy.visualization import ZScaleInterval, ImageNormalize
from astropy.convolution import Gaussian2DKernel,Gaussian1DKernel, convolve, convolve_fft
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
from ccdproc import ImageFileCollection
import cmcrameri.cm as cmcm
import h5py
import copy
from scipy import ndimage
import juanfit
from matplotlib import patches
with h5py.File("../../sav/Eclipse/Bias/master_bias_dc_red_1s_proto.h5", 'r') as hf:
bias_dc_red_1s = hf['image'][:]
with h5py.File("../../sav/Eclipse/Bias/master_bias_dc_red_5s_proto.h5", 'r') as hf:
bias_dc_red_5s = hf['image'][:]
red_path = "/Users/yjzhu/Desktop/Solar/Eclipse2017/src/EclipseSpectra2017/MikesData/VaderEclipseDayRed2017aug21/"
fname_skyflat_red_5s = ["SkyRed5s_6227.fit","SkyRed5s_6228.fit","SkyRed5s_6229.fit","SkyRed5s_6230.fit",
"SkyRed5s_6231.fit","SkyRed5s_6232.fit","SkyRed5s_6233.fit","SkyRed5s_6234.fit",
"SkyRed5s_6235.fit","SkyRed5s_6236.fit","SkyRed5s_6237.fit","SkyRed5s_6238.fit",
"SkyRed5s_6239.fit","SkyRed5s_6240.fit","SkyRed5s_6241.fit"]
flat_im_collection = ImageFileCollection(red_path,filenames=fname_skyflat_red_5s)
flat_im_df = flat_im_collection.summary.to_pandas()
flat_im_df
file | simple | bitpix | naxis | naxis1 | naxis2 | bzero | bscale | datamin | datamax | ... | ypixsz | xbinning | ybinning | xorgsubf | yorgsubf | xpossubf | ypossubf | cblack | cwhite | swcreate | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | SkyRed5s_6227.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 938 | 20108 | Artemis Capture |
1 | SkyRed5s_6228.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 939 | 20038 | Artemis Capture |
2 | SkyRed5s_6229.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 940 | 20050 | Artemis Capture |
3 | SkyRed5s_6230.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 940 | 20034 | Artemis Capture |
4 | SkyRed5s_6231.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 938 | 19979 | Artemis Capture |
5 | SkyRed5s_6232.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 938 | 20009 | Artemis Capture |
6 | SkyRed5s_6233.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 938 | 19907 | Artemis Capture |
7 | SkyRed5s_6234.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 939 | 19898 | Artemis Capture |
8 | SkyRed5s_6235.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 938 | 19908 | Artemis Capture |
9 | SkyRed5s_6236.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 940 | 19987 | Artemis Capture |
10 | SkyRed5s_6237.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 939 | 19999 | Artemis Capture |
11 | SkyRed5s_6238.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 939 | 19988 | Artemis Capture |
12 | SkyRed5s_6239.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 939 | 20024 | Artemis Capture |
13 | SkyRed5s_6240.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 939 | 20060 | Artemis Capture |
14 | SkyRed5s_6241.fit | True | 16 | 2 | 1392 | 1040 | 32768.0 | 1.0 | 0.0 | 65535.0 | ... | 6.45 | 1 | 1 | 0 | 0 | 0 | 0 | 940 | 20051 | Artemis Capture |
15 rows × 24 columns
flat_image_cube = np.zeros((1040,1392,15))
for ii, row_ in flat_im_df.iterrows():
flat_image_cube[:,:,ii] = CCDData.read(os.path.join(red_path,row_["file"]),unit="adu").data - bias_dc_red_5s
flat_im_aver = np.mean(flat_image_cube,axis=2)
WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642211 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642211 from DATE-OBS'. WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642269 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642269 from DATE-OBS'. WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642338 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642338 from DATE-OBS'. WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642396 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642396 from DATE-OBS'. WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642454 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642454 from DATE-OBS'. WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642523 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642523 from DATE-OBS'. WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642581 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642581 from DATE-OBS'. WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642650 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642650 from DATE-OBS'. WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642708 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642708 from DATE-OBS'. WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642778 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642778 from DATE-OBS'. WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642836 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642836 from DATE-OBS'. WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642905 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642905 from DATE-OBS'. WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642963 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.642963 from DATE-OBS'. WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.643032 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.643032 from DATE-OBS'. WARNING: FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.643090 from DATE-OBS'. [astropy.wcs.wcs] WARNING:astropy:FITSFixedWarning: 'datfix' made the change 'Set MJD-OBS to 57986.643090 from DATE-OBS'.
fig, ax = plt.subplots(figsize=(10,8),constrained_layout=True)
im = ax.pcolormesh(np.arange(1392),np.arange(1040),flat_im_aver,cmap=cmcm.lajolla_r, rasterized=True,vmax=2e4)
#plt.colorbar(im)
ax.axis("scaled")
clb_ax = inset_axes(ax,width="2%",height= "100%",loc='lower left',
bbox_to_anchor=(1.02, 0., 1, 1),
bbox_transform=ax.transAxes,
borderpad=0)
clb = plt.colorbar(im,pad = 0.05,orientation='vertical',ax=ax,cax=clb_ax)
clb_ax.tick_params(labelsize=12)
clb_ax.yaxis.get_offset_text().set_fontsize(16)
clb_ax.set_ylabel('',fontsize=16)
Text(0, 0.5, '')
with h5py.File("../../sav/Eclipse/Curvature/master_curvature_red.h5", 'r') as hf:
xpos_map_coordinate = hf['xpos_map_coordinate'][:]
xstart_pixel = hf['xpos_map_coordinate'].attrs['xstart_pixel']
xend_pixel = hf['xpos_map_coordinate'].attrs['xend_pixel']
ypos_map_coordinate = hf['ypos_map_coordinate'][:]
ystart_pixel = hf['ypos_map_coordinate'].attrs['ystart_pixel']
yend_pixel = hf['ypos_map_coordinate'].attrs['yend_pixel']
testx_slice_mapcoor = slice(xstart_pixel,xend_pixel)
testy_slice_mapcoor = slice(ystart_pixel,yend_pixel)
flat_trans_mapcoor = ndimage.map_coordinates(flat_im_aver[testy_slice_mapcoor, testx_slice_mapcoor],(ypos_map_coordinate, xpos_map_coordinate),
order=1)
fig, ax = plt.subplots(figsize=(16,8),constrained_layout=True)
im = ax.pcolormesh(np.arange(testx_slice_mapcoor.start,testx_slice_mapcoor.stop),np.arange(testy_slice_mapcoor.start,testy_slice_mapcoor.stop),
flat_trans_mapcoor,vmax=2e4,cmap=cmcm.lajolla_r,rasterized=True)
ax.tick_params(labelsize=16)
ax.axis("scaled")
clb_ax = inset_axes(ax,width="5%",height= "100%",loc='lower left',
bbox_to_anchor=(1.02, 0., 1, 1),
bbox_transform=ax.transAxes,
borderpad=0)
clb = plt.colorbar(im,pad = 0.05,orientation='vertical',ax=ax,cax=clb_ax)
clb_ax.tick_params(labelsize=16)
clb_ax.yaxis.get_offset_text().set_fontsize(16)
clb_ax.set_ylabel('',fontsize=16)
Text(0, 0.5, '')
fig, ax = plt.subplots(figsize=(6,8),constrained_layout=True)
im = ax.pcolormesh(np.arange(605,655),np.arange(testy_slice_mapcoor.start,testy_slice_mapcoor.stop),
flat_trans_mapcoor[:,605:655],vmax=2e4,cmap=cmcm.lajolla_r,rasterized=True)
ax.tick_params(labelsize=16)
# ax.axis("scaled")
clb_ax = inset_axes(ax,width="10%",height= "100%",loc='lower left',
bbox_to_anchor=(1.05, 0., 1, 1),
bbox_transform=ax.transAxes,
borderpad=0)
clb = plt.colorbar(im,pad = 0.05,orientation='vertical',ax=ax,cax=clb_ax)
clb_ax.tick_params(labelsize=16)
clb_ax.yaxis.get_offset_text().set_fontsize(16)
clb_ax.set_ylabel('',fontsize=16)
Text(0, 0.5, '')
flatfield_slicex_1 = slice(628,637)
sample_flatfield_y = np.average(flat_trans_mapcoor[:,flatfield_slicex_1],axis=1)
sample_flatfield_y = sample_flatfield_y/sample_flatfield_y.max()
fig, ax = plt.subplots(figsize=(10,6),constrained_layout=True)
ax.plot(np.arange(testy_slice_mapcoor.start,testy_slice_mapcoor.stop), sample_flatfield_y)
[<matplotlib.lines.Line2D at 0x18e9d9350>]
with h5py.File("../../sav/Eclipse/FlatField/skyflat_red_1d_FeX_52nd.h5", 'w') as hf:
df_flatfield_1d = hf.create_dataset("flatfield_1d", data=sample_flatfield_y)
df_flatfield_1d.attrs["ystart_pixel"] = ystart_pixel
df_flatfield_1d.attrs["yend_pixel"] = yend_pixel
fig, ax = plt.subplots(figsize=(6,8),constrained_layout=True)
im = ax.pcolormesh(np.arange(1025,1075),np.arange(testy_slice_mapcoor.start,testy_slice_mapcoor.stop),
flat_trans_mapcoor[:,1025:1075],vmax=2e4,cmap=cmcm.lajolla_r,rasterized=True)
ax.tick_params(labelsize=16)
# ax.axis("scaled")
clb_ax = inset_axes(ax,width="10%",height= "100%",loc='lower left',
bbox_to_anchor=(1.05, 0., 1, 1),
bbox_transform=ax.transAxes,
borderpad=0)
clb = plt.colorbar(im,pad = 0.05,orientation='vertical',ax=ax,cax=clb_ax)
clb_ax.tick_params(labelsize=16)
clb_ax.yaxis.get_offset_text().set_fontsize(16)
clb_ax.set_ylabel('',fontsize=16)
Text(0, 0.5, '')
flatfield_slicex_53 = slice(1048, 1054)
sample_flatfield_y_53 = np.average(flat_trans_mapcoor[:,flatfield_slicex_53],axis=1)
sample_flatfield_y_53 = sample_flatfield_y_53/sample_flatfield_y_53.max()
fig, ax = plt.subplots(figsize=(10,6),constrained_layout=True)
ax.plot(np.arange(testy_slice_mapcoor.start,testy_slice_mapcoor.stop), sample_flatfield_y_53)
[<matplotlib.lines.Line2D at 0x18f531890>]
with h5py.File("../../sav/Eclipse/FlatField/skyflat_red_1d_FeX_53rd.h5", 'w') as hf:
df_flatfield_1d = hf.create_dataset("flatfield_1d", data=sample_flatfield_y_53)
df_flatfield_1d.attrs["ystart_pixel"] = ystart_pixel
df_flatfield_1d.attrs["yend_pixel"] = yend_pixel
fig, ax = plt.subplots(figsize=(6,8),constrained_layout=True)
im = ax.pcolormesh(np.arange(205,255),np.arange(testy_slice_mapcoor.start,testy_slice_mapcoor.stop),
flat_trans_mapcoor[:,205:255],vmax=1.5e4,cmap=cmcm.lajolla_r,rasterized=True)
ax.tick_params(labelsize=16)
# ax.axis("scaled")
clb_ax = inset_axes(ax,width="10%",height= "100%",loc='lower left',
bbox_to_anchor=(1.05, 0., 1, 1),
bbox_transform=ax.transAxes,
borderpad=0)
clb = plt.colorbar(im,pad = 0.05,orientation='vertical',ax=ax,cax=clb_ax)
clb_ax.tick_params(labelsize=16)
clb_ax.yaxis.get_offset_text().set_fontsize(16)
clb_ax.set_ylabel('',fontsize=16)
Text(0, 0.5, '')
flatfield_slicex_51 = slice(220, 238)
sample_flatfield_y_51 = np.average(flat_trans_mapcoor[:,flatfield_slicex_51],axis=1)
sample_flatfield_y_51 = sample_flatfield_y_51/sample_flatfield_y_51.max()
fig, ax = plt.subplots(figsize=(10,6),constrained_layout=True)
ax.plot(np.arange(testy_slice_mapcoor.start,testy_slice_mapcoor.stop), sample_flatfield_y_51)
[<matplotlib.lines.Line2D at 0x18fd27a90>]
with h5py.File("../../sav/Eclipse/FlatField/skyflat_red_1d_FeX_51st.h5", 'w') as hf:
df_flatfield_1d = hf.create_dataset("flatfield_1d", data=sample_flatfield_y_51)
df_flatfield_1d.attrs["ystart_pixel"] = ystart_pixel
df_flatfield_1d.attrs["yend_pixel"] = yend_pixel
fig = plt.figure(figsize=(8,5),constrained_layout=True)
gs0 = fig.add_gridspec(5,1)
gs1 = gs0[2:].subgridspec(1,5)
ax1 = fig.add_subplot(gs0[:2])
ax2 = fig.add_subplot(gs1[0])
ax3 = fig.add_subplot(gs1[1:])
im1= ax1.imshow(flat_trans_mapcoor,origin="lower",vmax=2e4,cmap=cmcm.lajolla_r,
extent=[testx_slice_mapcoor.start-0.5,testx_slice_mapcoor.stop-0.5,
testy_slice_mapcoor.start-0.5,testy_slice_mapcoor.stop-0.5],
aspect="auto")
rec1 = patches.Rectangle((605 + testx_slice_mapcoor.start, testy_slice_mapcoor.start),
50, testy_slice_mapcoor.stop - testy_slice_mapcoor.start,linewidth=2,edgecolor="red",
facecolor="none",alpha=0.7)
ax1.add_artist(rec1)
con1 = patches.ConnectionPatch(xyA=(605 + testx_slice_mapcoor.start, testy_slice_mapcoor.start),
xyB=(605 + testx_slice_mapcoor.start, testy_slice_mapcoor.stop),
coordsA="data", coordsB="data",axesA=ax1, axesB=ax2, color="red",alpha=0.7)
con1 = patches.ConnectionPatch(xyA=(605 + testx_slice_mapcoor.start, testy_slice_mapcoor.start),
xyB=(605 + testx_slice_mapcoor.start, testy_slice_mapcoor.stop),
coordsA="data", coordsB="data",axesA=ax1, axesB=ax2, color="red",alpha=0.7)
con2 = patches.ConnectionPatch(xyA=(654 + testx_slice_mapcoor.start, testy_slice_mapcoor.start),
xyB=(654 + testx_slice_mapcoor.start, testy_slice_mapcoor.stop),
coordsA="data", coordsB="data",axesA=ax1, axesB=ax2, color="red",alpha=0.7)
ax1.add_artist(con1)
ax1.add_artist(con2)
ax1.set_ylabel(r"\textbf{CCD-Y [pixel]}",fontsize=16)
ax1.set_xlabel(r"\textbf{CCD-X [pixel]}",fontsize=16)
ax1.text(0.02,0.95,r"\textbf{(a)}",ha="left",va="top",color="black",
fontsize=16,transform=ax1.transAxes)
rec2 = patches.Rectangle((628 + testx_slice_mapcoor.start, testy_slice_mapcoor.start),
9, testy_slice_mapcoor.stop - testy_slice_mapcoor.start,linewidth=2,edgecolor="#008176",
facecolor="none",alpha=0.7)
ax2.add_artist(rec2)
im2 = ax2.imshow(flat_trans_mapcoor[:,605:655],vmax=2e4,cmap=cmcm.lajolla_r,origin="lower",
extent=[605-0.5+testx_slice_mapcoor.start, 655-0.5+testx_slice_mapcoor.start,
testy_slice_mapcoor.start-0.5, testy_slice_mapcoor.stop-0.5],aspect="auto")
ax2.set_ylabel(r"\textbf{CCD-Y [pixel]}",fontsize=16)
ax2.set_xlabel(r"\textbf{CCD-X [pixel]}",fontsize=16)
ax2.text(0.10,0.95,r"\textbf{(b)}",ha="left",va="top",color="white",
fontsize=16,transform=ax2.transAxes)
ax3.step(np.arange(testy_slice_mapcoor.start,testy_slice_mapcoor.stop), sample_flatfield_y,where="mid",
color="#0000A7")
ax3.set_ylabel(r"\textbf{Norm Counts}",fontsize=16)
ax3.set_xlabel(r"\textbf{CCD-Y [pixel]}",fontsize=16)
ax3.text(0.96,0.95,r"\textbf{(c)}",ha="right",va="top",color="black",
fontsize=16,transform=ax3.transAxes)
for ax_ in (ax1,ax2,ax3):
ax_.tick_params(labelsize=16,direction="in",top=True,right=True)
plt.savefig(fname="../../figs/ms/flatfield.pdf",format="pdf",dpi=300,bbox_inches="tight")