def temp_var(folder): os.chdir(folder) img_list = glob.glob('*.fits*') bias = cam.get_master_bias(-40) #Retrieve bias bias = bias.astype(np.int32) stack = np.zeros((naxis1, naxis2), dtype=np.int32) for i in img_list: hdu = fits.open(i) data = hdu[0].data data = data.astype(np.int32) data -= bias stack = np.dstack((stack, data)) stack = stack[:, :, 1:] #Slice off base layer var_map = np.var(stack, axis=2) dark = cam.get_master_dark(40) bias = cam.get_master_bias(-60) nonlinear_mask = (var_map > 50000) * 1 # var_map = var_map[var_map<0.6E6] plt.hist(var_map.flatten(), bins=200) plt.yscale('log') plt.grid(True) plt.xlabel('$\sigma^2$ (ADUs)') plt.ylabel('No. of pixels') plt.title('Distribution of temporal variability (DIT=450ms,NDIT=30)') plt.show() print('PROGRAM HAS COMPLETED') return nonlinear_mask
def master_flat(i, folder): dark = fits.open(dark_path) bias = cam.get_master_bias('-60') os.chdir(folder) img_list = glob.glob('*.fits*') img_list_split = [i.split('_') for i in img_list] stack = np.zeros((1040, 1296)) for j in files: if img_list_split[k][1] == str(float(int_time)): hdu = fits.open(j) img = hdu[0].data img = img - bias - dark #Subtract bias and dark from each flat stack = np.dstack((stack, data)) stack = stack[:, :, 1:] #Remove 0 array it is stacked on flat_collapsed = np.median(stack, axis=2) flat_normed = flat_collapsed / np.max(flat_collapsed) #Normalise flat flat_header = hdu[0].header flat_header.append( ('NSTACK', stack.shape[2], 'Number of exposures stacked')) flat_header.append( ('TYPE', 'MASTER_FLAT', 'Normalised median stack of flat fields')) master_name = 'mastersky_'+str(i/1000)+"s_" + str(stack.shape[2]) \ + 'stack_am' + str(am) + '.fits' #Write to FITS file fits.writeto(master_name, sky_reduced, sky_header) os.chdir(os.path.dirname(os.path.realpath(__file__)))
def ptc(folder): os.chdir(folder) img_list = glob.glob('*.fits*') bias = cam.get_master_bias(-40) bias = np.asarray(bias, dtype=np.int32) times = [] for k in img_list: hdu = fits.open(k) times.append(hdu[0].header['DITSER']) times = np.unique(times) #sort times if order is needed sets = [[] for _ in times] for j in img_list: hdu = fits.open(j) dit = hdu[0].header['DITSER'] ind = np.argwhere(times == dit) sets[ind[0, 0]].append(hdu[0].data) amp, noise = [], [] for i in sets: first = i[1].astype(np.int32) second = i[0].astype(np.int32) diff_img = first - second single = first - bias roi_diff = diff_img[200:900, 300:1000] roi_single = single[200:900, 300:1000] noise.append(np.std(roi_diff)) amp.append(np.median(roi_single)) noise = np.array(noise) / m.sqrt(2) amp = np.array(amp) amp = np.log10(amp) noise = np.log10(noise) plt.scatter(amp, noise, c='b', label='Data') x1 = amp[(amp < 4) & (amp > 3.4)] y1 = noise[(amp < 4) & (amp > 3.4)] x = np.linspace(-1, 5, 500) x2 = amp[(amp < 4) & (amp > 3.8)] y2 = noise[(amp < 4) & (amp > 3.8)] def fixed(x, b): return 0.5 * x + b popt1, _ = optimize.curve_fit(fixed, x1, y1) plt.plot(x, fixed(x, *popt1), 'r-', label='1/2 Slope Fit 1') popt2, _ = optimize.curve_fit(fixed, x2, y2) # plt.plot(x, fixed(x, *popt2), 'g-',label='1/2 Slope Fit 2') plt.axhline(1.255, c='m', linestyle='--', label='19ADU Read-noise floor') plt.ylabel('Noise (log(ADUs))') plt.xlabel('Intensity (log(ADUs))') plt.grid(True) plt.title('Photon Transfer Curve (g=3.34$e^-$/ADU)') plt.legend(loc='best') plt.show()
def ramp_plot(folder): os.chdir(folder) img_list = glob.glob('*.fits*') bias = cam.get_master_bias(-40) bias = np.asarray(bias, dtype=np.int32) times, amp = [], [] for i in img_list: hdu = fits.open(i) data = hdu[0].data data = np.asarray(data, dtype=np.int32) # data = data - bias times.append(hdu[0].header['DITSER']) #Dark Region roi_single_d = data[400:800, 400:800] amp.append(np.median(roi_single_d)) amp = np.array(amp) plt.scatter(times, amp, c='blue', label='Data') plt.xlabel('Integration Time (ms)') plt.ylabel('Intensity (ADUs)') # plt.xscale('log') # plt.yscale('log') plt.grid(True) plt.title('Integration Ramp') plt.legend(loc='best') plt.show() print('PROGRAM HAS COMPLETED')
def master_sky_plot(): bias_data = cam.get_master_bias(-40) squished = cam.median_stack(i, folder) reduced = squished - bias_data #Subtract master bias #Clip to 3 sigmas the squished image to remove recurring #dead/hot pixels reduce_clipped, _, _ = sigmaclip(reduced, 3, 3) reduce_clipped_s = reduce_clipped / 2 fig, (ax1, ax2, ax3) = plt.subplots(figsize=(13, 3), ncols=3) sky = ax1.imshow(squished, vmin=1900, vmax=2600) ax1.set_title('Median-stacked(DIT=2s,NDIT=8)') fig.colorbar(sky, ax=ax1) bias_img = ax2.imshow(bias_data, vmin=1400, vmax=2000) ax2.set_title('Master Bias(-40C)') fig.colorbar(bias_img, ax=ax2) sky_reduced = ax3.imshow(reduced, vmin=400, vmax=700) ax3.set_title('Bias-subtracted') fig.colorbar(sky_reduced, ax=ax3) plt.suptitle( 'Sky background (no filter) at airmass 2: {}ADUs/pixel/s'.format( round(np.mean(reduce_clipped_s), 2))) plt.show()
def bias_temp(n, loops): bias = cam.get_master_bias(-40) #Reference median_residuals = [] times = [] #Stamp starting time here int_t = cam.set_int_time(0.033) frame_t = cam.set_frame_time(20.033) for i in range(loops): img = np.zeros(shape=(naxis1, naxis2)) #Initiate array for coadding for i in range(n): frame, _ = cam.simple_cap() img += frame img = img / n #Stamp time of this frame here #Append time to list of times residual_img = img - bias median_residuals.append( np.median(residual_img)) #Append median of difference fig, ax1 = plt.subplots() colour = 'tab:blue' ax1 = sns.pointplot(x=temps, y=means, color=colour) ax1.set_ylabel('Median Residual', color=colour) ax1.tick_params(axis='y', labelcolor=colour) ax1.set_xlabel('Time (s)') plt.title( r'$\mathrm{Thermal\ emission\ of\ shutter\ study\(bias\ frames)}$') plt.show()
def pixel_population_ramp(folder): os.chdir(folder) img_list = glob.glob('*.fits*') bias = cam.get_master_bias(-40) bias = np.asarray(bias, dtype=np.int32) times, pixels = [], [] stack = np.zeros((10, 10), dtype=np.int32) for i in img_list: hdu = fits.open(i) data = hdu[0].data data = np.asarray(data, dtype=np.int32) data = data - bias times.append(hdu[0].header['DITSER']) #Bright Region roi = data[790:800, 790:800] stack = np.dstack((stack, roi)) stack = stack[:, :, 1:] #Slice off base layer for i in range(stack.shape[0]): for j in range(stack.shape[1]): pix_array = stack[i, j, :] plt.scatter(times, pix_array) plt.xlabel('Integration Time (ms)') plt.ylabel('Intensity (ADUs)') plt.grid(True) plt.title('Integration Ramp for 100 pixel population') plt.show() print('PROGRAM HAS COMPLETED')
def crosstalk(folder): img = '/crosstalk_2.fits' img_dir = folder + img hdu = fits.open(img_dir) frame = hdu[0].data bias = cam.get_master_bias(-40) bias = bias.astype(np.int32) dark = cam.get_master_dark(20, -40) dark = dark.astype(np.int32) frame = frame - bias - dark fig, axs = plt.subplots(nrows=1, ncols=2) cut_region = range(200, 205) cuts = frame[:, 199] for i in cut_region: cut = frame[:, i] cuts = np.vstack((cuts, cut)) cut_median = np.median(cuts, axis=0) axs[1].plot(cut_median) axs[1].set_ylabel('ADUs') axs[1].set_xlabel('y-Index') axs[0].imshow(frame) plt.suptitle('Vertical Profile at x = {}'.format(cut_region[0])) plt.show()
def bias_config_diff(): #Base Mode b_1 = cam.get_master_bias(-40) b_2 = cam.get_master_bias(-20) b_3 = cam.get_master_bias(0) b_4 = cam.get_master_bias(20) #Full Mode f_1 = cam.get_master_bias(-42) f_2 = cam.get_master_bias(-22) f_3 = cam.get_master_bias(2) f_4 = cam.get_master_bias(22) b_1 = b_1.astype(np.int32) b_2 = b_2.astype(np.int32) b_3 = b_3.astype(np.int32) b_4 = b_4.astype(np.int32) f_1 = f_1.astype(np.int32) f_2 = f_2.astype(np.int32) f_3 = f_3.astype(np.int32) f_4 = f_4.astype(np.int32) img1 = b_1 - f_1 img2 = b_2 - f_2 img3 = b_3 - f_3 img4 = b_4 - f_4 img_eq1 = exposure.equalize_hist(img1) img_eq2 = exposure.equalize_hist(img2) img_eq3 = exposure.equalize_hist(img3) img_eq4 = exposure.equalize_hist(img4) fig, axs = plt.subplots(nrows=1, ncols=4) axs[0].imshow(img1) axs[0].set_title('Temp: {}$^\circ$C, Median Difference: {}'.format( -40, int(np.median(img1)))) axs[1].imshow(img2) axs[1].set_title('Temp: {}$^\circ$C, Median Difference: {}'.format( -20, int(np.median(img2)))) axs[2].imshow(img3) axs[2].set_title('Temp: {}$^\circ$C, Median Difference: {}'.format( 0, int(np.median(img3)))) axs[3].imshow(img4) axs[3].set_title('Temp: {}$^\circ$C, Median Difference: {}'.format( 20, int(np.median(img4)))) plt.suptitle('Base-Full Bias Difference Images (DIT=33$\mu$s, NDIT=100)') plt.show() plt.tight_layout()
def ptc_gain(folder): os.chdir(folder) img_list = glob.glob('*.fits*') bias = cam.get_master_bias(-40) bias = np.asarray(bias, dtype=np.int32) times = [] for k in img_list: hdu = fits.open(k) times.append(hdu[0].header['DITSER']) times = np.unique(times) print('times retrieved') #sort times if order is needed sets = [[] for _ in times] for j in img_list: hdu = fits.open(j) dit = hdu[0].header['DITSER'] ind = np.argwhere(times == dit) sets[ind[0, 0]].append(hdu[0].data) print('sets constructed') amp, var = [], [] for i in sets: first = i[1].astype(np.int32) second = i[0].astype(np.int32) diff_img = first - second first = first - bias roi_diff = diff_img[400:800, 400:800] roi_single = first[400:800, 400:800] var.append(np.var(roi_diff)) amp.append(np.median(roi_single)) print('arrays finished') var = np.array(var) / 2 amp = np.array(amp) plt.scatter(amp, var) #,label = 'Data') # slope, intercept, r_value, _ ,_ = linregress(x,y) # fit = slope*x + intercept # plt.plot(x,fit) # rsqr = round((r_value**2),4) # plt.plot(amp,fit,'g',label = 'Linear Fit, $r^2$ = {}'.format(rsqr)) # def fixed(x,b): # return 0.31*x+b # popt1, _ = optimize.curve_fit(fixed,x,y) # plt.plot(amp, fixed(amp, *popt1), 'r-',label='Pre-determined gain slope fit (m=0.31)') plt.ylabel('$\sigma^2$ (ADUs)') plt.xlabel('Median Pixel Value (ADUs)') plt.grid(True) plt.title( 'Variance vs Intensity' ) # Gain Study 2 (SLD), g = {}ADUs/$e^-$ (n = {})'.format(round(slope,2),len(x)))
def gain_estimate(n): bias = cam.get_master_bias(-40) int_times = np.round(np.linspace(500, 5000, n), 0) medians, sigmasqrs = [], [] for j in int_times: cam.set_int_time(j) cam.set_frame_time(j + 20) #Take pair of images first, _ = cam.simple_cap() second, _ = cam.simple_cap() first = np.asarray(first, dtype=np.int32) second = np.asarray(second, dtype=np.int32) first = first - bias second = second - bias diff_img = first - second #Difference of bias-subtracted frames clipped_diff_img = cam.roi_clip(diff_img) clipped_img = cam.roi_clip(first) sigmasqrs.append(np.var(clipped_diff_img)) #variance from difference medians.append(np.median(clipped_img)) #intensity from single frame sigmasqrs = np.array(sigmasqrs) / 2 #Adjust for difference theorem medians = np.array(medians) #Linear fit slope, intercept, r_value, _, _ = stats.linregress(medians, sigmasqrs) print(slope, intercept, r_value) #Figure out parameters gain = round((1 / slope), 2) #read_noise = int(np.sqrt((gain**2)*intercept)) results_path = testing_dir +'gain_testing/' + \ 'study_2_results.txt' np.savetxt(results_path, (medians, sigmasqrs, int_times)) fit = slope * medians + intercept slope = round(slope, 2) intercept = int(intercept) rsqr = round((r_value**2), 4) plt.scatter(medians, sigmasqrs, c='red', label='Data') plt.plot(medians,fit,'g--',label = 'Linear Fit: (m = {0}, b = {1}, $r^2$ = {2})'\ .format(slope,intercept,rsqr)) plt.ylabel('$\sigma^2$ (ADUs)') plt.xlabel('Intensity (ADUs)') plt.grid(True) plt.legend(loc='best') plt.title( 'Pairwise Variance vs Intensity Gain Study, g = {0}'.format(gain)) plt.show() print('PROGRAM HAS COMPLETED')
def dark_bad_pix_var(folder, i): bias = cam.get_master_bias(-60) os.chdir(folder) i = i * 1000 #convert to ms img_list = glob.glob('*.fits*') img_list_split = [i.split('_') for i in img_list] low_map = np.zeros((naxis1, naxis2)) very_low_map = np.zeros((naxis1, naxis2)) hot_map = np.zeros((naxis1, naxis2)) very_hot_map = np.zeros((naxis1, naxis2)) c_bias = 1951 * np.ones((naxis1, naxis2)) n = 0 for k in range(len(img_list)): if img_list_split[k][1] == str(i): hdu = fits.open(img_list[k]) data = hdu[0].data dark = data - bias np.asarray(dark, dtype=np.float64) print(np.min(dark)) # hot_dark = np.median(dark)+6*np.std(dark) low_map += ((dark < 300) & (dark > 0)) * 1 very_low_map += (dark < 0) * 1 hot_map += ((dark > 2000) & (dark < 5000)) * 1 very_hot_map += (dark > 5000) * 1 print(len((very_low_map[very_low_map != 0]))) n += 1 hot_dist = (hot_map[hot_map != 0]) / n very_hot_dist = (very_hot_map[very_hot_map != 0]) / n low_dist = (low_map[low_map != 0]) / n very_low_dist = (very_low_map[very_low_map != 0]) / n print(very_low_dist) #plt.hist(hot_dist,facecolor='g',hatch='/', edgecolor='k',fill=True, alpha=0.5,\ # label=r'High $I_{dark}$') #plt.hist(very_hot_dist,facecolor='y',hatch='|', edgecolor='k',fill=True, alpha=0.5,\ # label=r'Very High $I_{dark}$') #plt.hist(low_dist,hatch='*', facecolor='c',edgecolor='k',fill=True,alpha=0.5,\ # label=r'Low $I_{dark}$') plt.hist(very_low_dist,hatch='o', facecolor='r',edgecolor='k',fill=True,alpha=0.5,\ label=r'Very Low $I_{dark}$') plt.xlabel('Recurrance Rate (%)') plt.ylabel('# of Pixels') plt.legend(loc='best') plt.title( 'Recurrance of bad pixels on dark frames(n={},DIT=40s)'.format(n)) plt.show() print('Program Complete')
def bad_pix_map(): dark = cam.get_master_dark(40) bias = cam.get_master_bias(-60) hot_dark = np.median(dark) + 5 * np.std(dark) low_dark = 300 dead_lim = np.median(bias) - 5 * np.std(bias) flag_mask = (bias == 16383) * 1 dead_mask = (bias < dead_lim) * 1 low_mask = (dark < low_dark) * 1 hot_mask = (dark > hot_dark) * 1 #*1 converts to integer bool bad_mask = dead_mask + hot_mask + flag_mask + low_mask return bad_mask
def full_well_hist(folder): os.chdir(folder) img_list = glob.glob('*.fits*') bias = cam.get_master_bias(-40) stack = np.zeros((naxis1, naxis2), dtype=np.uint16) for i in img_list: hdu_img = fits.open(i) data = hdu_img[0].data data = data - bias data[data > 60000] = 0 #Avoid unsigned integer overflow stack = np.dstack((stack, data)) stack = stack[:, :, 1:] #Remove 0 array it is stacked on collapsed = np.median(stack, axis=2) clipped, _, _ = sigmaclip(collapsed, 8, 8) #clipped *= 3.22 #gain-adjust median = np.median(clipped) sigma = np.std(clipped) early_line = median - 3 * sigma #3sigma away from distribution full-well begins fig, axs = plt.subplots(nrows=1, ncols=2) axs[0].axvline(early_line, linestyle='--', c='r', label='$3\sigma$ Full Well: {}ADUs'.format(int(early_line))) axs[0].axvline(median, linestyle='--', c='blue', label='Median: {}ADUs'.format(int(median))) axs[0].hist(clipped, bins=110, facecolor='g', edgecolor='k', fill=True) axs[0].set_yscale('log') axs[0].set_ylabel('No. of Pixels') axs[0].set_xlabel('ADUs') axs[0].grid(True) axs[0].legend(loc='best') img_eq = exposure.equalize_hist(data) axs[1].imshow(img_eq) plt.suptitle( 'Full-well Study of Oversaturated Frames (DIT={}s,NDIT={})'.format( 20, 70)) plt.show()
def cooling_test(): os.chdir('C:') os.chdir('C:/nstf/images/images19-06-2020/cooling_test_2') files = glob.glob('*.fits*') bias = cam.get_master_bias(-60) temps = [] vals = [] sigma = [] for i in files: hdu = fits.open(i) ambtemp = hdu[0].header['AMBTEMP'] temps.append(ambtemp) data = hdu[0].data data = data - bias clipped, _, _ = sigmaclip(data, 5, 5) #clip hot/dead pixels vals.append(np.median(clipped)) sigma.append(np.std(clipped)) temps = np.array(temps) vals = np.array(vals) vals = vals[temps < 10] temps = temps[temps < 10] vals = 3.23 * vals vals = vals / 2 slope, intercept, r_value, _, _ = linregress(temps, vals) fit = slope * temps + intercept slope = int(slope) rsqr = round((r_value**2), 4) plt.scatter(temps, vals, label='Data', color='black') plt.plot(temps,fit,'g--',label = 'Linear Fit (m={0}e/s/$^\circ$C, $r^2$={1})'\ .format(slope,rsqr)) plt.grid(True) plt.legend(loc='best') # plt.axvspan(26, 8, color='r', alpha=0.5, lw=0) # plt.axvspan(7.9, -11, color='g', alpha=0.5, lw=0) # plt.text(20,180,r'$FPA\ Unstable$') # plt.text(0,180,r'$FPA\ Stable$') # plt.gca().invert_xaxis() plt.xlabel('Temperature ($^\circ$C)') plt.ylabel('Median $e^-$/s/pix') plt.title('Detector Cooling Test (FPA:-60$^\circ$C, DIT=2s)') plt.show()
def bias_temp_analysis(): #Base Mode b_1 = cam.get_master_bias(-40) b_2 = cam.get_master_bias(-20) b_3 = cam.get_master_bias(0) b_4 = cam.get_master_bias(20) #Full Mode f_1 = cam.get_master_bias(-42) f_2 = cam.get_master_bias(-22) f_3 = cam.get_master_bias(2) f_4 = cam.get_master_bias(22) temps = [-40, -20, 0, 20] medians_b = [ np.median(b_1), np.median(b_2), np.median(b_3), np.median(b_4) ] medians_f = [ np.median(f_1), np.median(f_2), np.median(f_3), np.median(f_4) ] plt.plot(temps, medians_b, marker='o', linestyle='--', c='g', label='Base Mode (1-tap)') plt.plot(temps, medians_f, marker='x', c='r', label='Full Mode (4-taps)') plt.ylabel('Median (ADUs)') plt.xlabel('Temperature ($^{\circ}$C)') plt.legend(loc='best') plt.title(r'$\mathrm{Bias\ results\ against\ Temperature}$') plt.grid(True) plt.show()
def median_ptc(folder): os.chdir(folder) img_list = glob.glob('*.fits*') bias = cam.get_master_bias(-40) bias = np.asarray(bias, dtype=np.int32) times = [] for k in img_list: hdu = fits.open(k) times.append(hdu[0].header['DITSER']) times = np.unique(times) sets = [[] for _ in times] for j in img_list: hdu = fits.open(j) dit = hdu[0].header['DITSER'] ind = np.argwhere(times == dit) sets[ind[0, 0]].append(hdu[0].data) amp, var = [], [] for i in sets: print(len(i)) med, var_ele = [], [] for j in range(0, len(i), 2): #select every second array first = i[j].astype(np.int32) second = i[j + 1].astype(np.int32) diff_img = first - second roi_diff = diff_img[400:800, 400:800] roi_single = first[400:800, 400:800] med.append(np.median(roi_single)) var_ele.append(np.var(roi_diff)) var.append(np.mean(var_ele)) amp.append(np.mean(med)) var = np.array(var) / 2 amp = np.array(amp) plt.scatter(amp, var, marker='d', label='Median Results (n=20)') plt.ylabel('$\sigma^2$ (ADUs)') plt.xlabel('Median Pixel Value (ADUs)') plt.grid(True) plt.legend(loc='best') plt.title('Variance vs Intensity') plt.show()
def stack_hists(folder): os.chdir(folder) img_list = glob.glob('*.fits*') bias = cam.get_master_bias(-40) #Retrieve bias bias = bias.astype(np.int32) for i in img_list: hdu = fits.open(i) data = hdu[0].data data = data.astype(np.int32) data -= bias data = data[400:800, 400:800] plt.hist(data.flatten(), bins=100) plt.yscale('log') plt.grid(True) plt.xlabel('ADUs') plt.ylabel('No. of pixels') plt.title('Pixel Distribution Histograms (NDIT=30)') plt.show()
def master_dark_local(folder, i): ''' DIT and NDIT are inputs Function can also take tag for sorting individual frames onto local drive T is the FPA temperature used to record temperature of FPA for this dark which is written to file name and FITS header Program also outputs a .npy binary file containing 3D datacube of central (100,100) window for studying temporal variance over stack Takes folder of single frames ''' os.chdir(folder) bias = cam.get_master_bias(-60) #Retrieve bias img_list = glob.glob('*.fits*') img_list_split = [i.split('_') for i in img_list] stack = np.zeros((naxis1, naxis2), dtype=np.uint16) for k in range(len(img_list)): if img_list_split[k][1] == str(i): hdu = fits.open(img_list[k]) data = hdu[0].data data = data - bias #Bias subtract data[data > 60000] = 0 #Avoid unsigned integer overflow stack = np.dstack((stack, data)) dark_header = hdu[0].header stack = stack[:, :, 1:] #Slice off base layer ndit = stack.shape[2] master_dark = np.median(stack, axis=2) master_dark = master_dark.astype(np.uint16) dark_header.append(('NDIT', ndit, 'Number of integrations')) dark_header.append(('TYPE', 'MASTER_DARK', 'Median stack of dark frames')) #Output master frame to fits master_path = master_darks + 'master_dark_' \ + str(i/1000) + '_-10.6C.fits' fits.writeto(master_path, master_dark, dark_header) print('PROGRAM HAS COMPLETED')
def master_sky(i, folder, am, filter): ''' Takes integration time in ms, folder containing sky backgrounds an airmass and camera temperature ''' os.chdir(folder) bias = cam.get_master_bias(-60) #Retrieve bias bias = bias.astype(np.int32) dark = cam.get_master_dark(int(i / 2000)) #Retrieve dark dark = dark.astype(np.int32) img_list = glob.glob('*.fits*') img_list_split = [i.split('_') for i in img_list] stack = np.zeros((1040, 1296), dtype=np.int32) for k in range(len(img_list)): if img_list_split[k][1] == str(float(i)): hdu = fits.open(img_list[k]) data = hdu[0].data data = data.astype(np.int32) data -= bias #Bias subtract data -= dark #Dark subtract stack = np.dstack((stack, data)) stack = stack[:, :, 1:] #Remove 0 array it is stacked on #Collapse multi-dimensional array along depth axis by median sky_collapsed = np.median(stack, axis=2) #Append neccesary info to header sky_header = hdu[0].header sky_header.append(('NDIT', stack.shape[2], 'Number of integrations')) sky_header.append( ('TYPE', 'MASTER_SKY', 'Median stack of sky backgrounds')) sky_header.append(('AIRMASS', am, 'Airmass of exposures')) sky_header.append(('BAND', filter, 'Bandpass filter')) master_name = master_skys + 'mastersky_'+str(i/1000)+"s_" + str(stack.shape[2]) \ + 'stack_am' + str(am) + '.fits' #Write to FITS file fits.writeto(master_name, sky_collapsed, sky_header) os.chdir(os.path.dirname(os.path.realpath(__file__))) print('PROGRAM COMPLETE')
def var_time(folder): os.chdir(folder) img_list = glob.glob('*.fits*') bias = cam.get_master_bias(-40) bias = np.asarray(bias, dtype=np.int32) times = [] for k in img_list: hdu = fits.open(k) times.append(hdu[0].header['DITSER']) times = np.unique(times) #sort times if order is needed sets = [[] for _ in times] for j in img_list: hdu = fits.open(j) dit = hdu[0].header['DITSER'] ind = np.argwhere(times == dit) sets[ind[0, 0]].append(hdu[0].data) var = [] for i in sets: first = i[1].astype(np.int32) second = i[0].astype(np.int32) diff_img = first - second roi_diff = diff_img[400:800, 400:800] var.append(np.var(roi_diff)) var = np.array(var) / 2 plt.scatter(times, var, c='blue', label='Data') plt.ylabel('$\sigma^2$ (ADUs)') plt.xlabel('Integration Time (ms)') plt.grid(True) plt.title('Variance vs Integration Time') plt.legend(loc='best') plt.show() print('PROGRAM HAS COMPLETED')
def fringing_stack(folder, T, band): os.chdir(folder) img_list = glob.glob('*.fits*') bias = cam.get_master_bias(T) bias = bias.astype(np.int32) stack = np.zeros((naxis1, naxis2), dtype=np.int32) for i in img_list: hdu = fits.open(i) frame = hdu[0].data frame = frame.astype(np.int32) frame = frame - bias stack = np.dstack((stack, frame)) stack = stack[:, :, 1:] #Slice off base layer img = np.median(stack, axis=2) img_save = np.copy(img) masked = cam.roi_circle(img) norm_masked = masked / np.max(masked) # plt.hist(norm_masked,bins=300,label=band) return img_save
def dark_nonuniformity(folder): os.chdir(folder) dk_list = glob.glob('*.fits*') dk_list.sort() bias_20 = cam.get_master_bias(-20) bias_40 = cam.get_master_bias(-40) bias_60 = cam.get_master_bias(-60) img_20 = cam.fits_extract(dk_list[0]) img_40 = cam.fits_extract(dk_list[1]) img_60 = cam.fits_extract(dk_list[2]) img_20 -= bias_20 img_40 -= bias_40 img_60 -= bias_60 norm_20 = img_20 / np.mean(img_20) norm_40 = img_40 / np.mean(img_40) norm_60 = img_60 / np.mean(img_60) norm_20 = norm_20[100:1000, 100:1000] norm_40 = norm_40[100:1000, 100:1000] norm_60 = norm_60[100:1000, 100:1000] xx, yy = np.mgrid[0:norm_20.shape[0], 0:norm_20.shape[1]] #coords for images fig = plt.figure() ax = fig.add_subplot(1, 3, 1, projection='3d') surf = ax.plot_surface(xx, yy, norm_20, cmap='twilight_shifted', linewidth=0.2) ax.set_zlim(0.5, 1.5) ax.axes.xaxis.set_ticks([]) ax.axes.yaxis.set_ticks([]) ax.set_title('FPA: -20$^\circ$C, $\sigma$={}'.format( round(np.std(norm_20), 1))) ax.set_zlabel('Normalised Pixel Intensity') ax = fig.add_subplot(1, 3, 2, projection='3d') surf = ax.plot_surface(xx, yy, norm_40, cmap='twilight_shifted', linewidth=0.2) ax.set_title('FPA: -40$^\circ$C, $\sigma$={}'.format( round(np.std(norm_40), 1))) ax.axes.xaxis.set_ticks([]) ax.axes.yaxis.set_ticks([]) ax.set_zlabel('Normalised Pixel Intensity') ax = fig.add_subplot(1, 3, 3, projection='3d') surf = ax.plot_surface(xx, yy, norm_60, cmap='twilight_shifted', linewidth=0.2) ax.set_title('FPA: -60$^\circ$C, $\sigma$={}'.format( round(np.std(norm_60), 1))) ax.axes.xaxis.set_ticks([]) ax.axes.yaxis.set_ticks([]) ax.set_zlabel('Normalised Pixel Intensity') plt.tight_layout() plt.suptitle('Dark Current Spatial Non-uniformity with FPA Temperature') plt.show()
def master_dark(i, n, T, tag=''): ''' DIT and NDIT are inputs Function can also take tag for sorting individual frames onto local drive T is the FPA temperature used to record temperature of FPA for this dark which is written to file name and FITS header Program also outputs a .npy binary file containing 3D datacube of central (100,100) window for studying temporal variance over stack ''' cam.set_int_time(i) cam.set_frame_time(i + 20) bias = cam.get_master_bias(T) cam.printProgressBar(0, n, prefix='Progress:', suffix='Complete', length=50) stack = np.zeros((naxis1, naxis2), dtype=np.uint16) window = np.zeros((100, 100), dtype=np.uint16) for j in range(n): _, _ = cam.img_cap(routine, img_dir, 'f') hdu_img = fits.open(unsorted_img) data = hdu_img[0].data hdu_img.close() #Close image so it can be sorted data = data - bias stack = np.dstack((stack, data)) data_window = cam.window(data, 100) window = np.dstack((window, data_window)) cam.printProgressBar(j,n, prefix = 'Progress:', \ suffix = 'Complete', length = 50) if j == n - 1: #On final frame grab header dark_header = fits.getheader(unsorted_img) #Save single frame to local drive cam.file_sorting(local_img_dir, i, i + 20, tag=tag) #Median stack stack = stack[:, :, 1:] #Slice off base layer master_dark = np.median(stack, axis=2) #Prepare window for temporal analysis window = window[:, :, 1:] #Slice off base layer temp_var = np.median(np.var(stack, axis=2)) temp_path = master_darks + 'dark_cube' \ + str(i/1000) + '_' +str(T) +'C.npy' np.save(temp_path, window) dark_header.append(('NDIT', n, 'Number of integrations')) dark_header.append(('TYPE', 'MASTER_DARK', 'Median stack of dark frames')) dark_header.append(('FPATEMP', T, 'Temperature of detector')) dark_header.append( ('TEMPVAR', temp_var, 'Median temporal variance of central (100,100) window')) #Output master frame to fits master_path = master_darks + 'master_dark_' \ + str(i/1000) + '_' +str(T) +'C.fits' fits.writeto(master_path, master_dark, dark_header) print('PROGRAM HAS COMPLETED')
def nonlinearity(folder): os.chdir(folder) img_list = glob.glob('*.fits*') bias = cam.get_master_bias(-40) bias = np.asarray(bias, dtype=np.int32) times = [] for k in img_list: hdu = fits.open(k) times.append(hdu[0].header['DITSER']) times = np.unique(times) sets = [[] for _ in times] for j in img_list: hdu = fits.open(j) dit = hdu[0].header['DITSER'] ind = np.argwhere(times == dit) sets[ind[0, 0]].append(hdu[0].data) amp, var = [], [] for i in sets: first = i[1].astype(np.int32) second = i[0].astype(np.int32) diff_img = first - second first = first - bias roi_diff = diff_img[400:800, 400:800] roi_single = first[400:800, 400:800] var.append(np.var(roi_diff)) amp.append(np.median(roi_single)) var = np.array(var) / 2 #Adjust var amp = np.array(amp) #Linear Region lin_y = var[(amp > 2000) & (amp < 8000)] lin_x = amp[(amp > 2000) & (amp < 8000)] slope, intercept, r_value, _, _ = linregress(lin_x, lin_y) fit = slope * amp + intercept rsqr = round(r_value**2, 3) m = round(slope, 2) b = int(intercept) x = np.linspace(amp[0], amp[-1], 5000) noise = (20**2) + np.sqrt(x) nonlin = 11600 fwell = 13480 fig1 = plt.figure(1) frame1 = fig1.add_axes((.1, .3, .8, .6)) plt.plot(amp, fit, linestyle='--', c='g', label='Linear fit: $r^2$ = {}, m = {}, b = {}'.format(rsqr, m, b)) plt.scatter(amp, var, label='Data (n={})'.format(len(times))) plt.axvline(nonlin, c='m', label='$4\%$ Non-linearity Point: {}ADUs'.format(nonlin)) plt.axvline(fwell, c='y', label='Full-well: {}ADUs'.format(fwell)) plt.xlim(11000, 13600) plt.ylim(0, 4000) plt.ylabel('$\sigma^2$ (ADUs)') plt.title('Linear photon transfer curve with fit residuals') plt.legend(loc='best') frame1.set_xticklabels([]) plt.grid() #Residual plot resids = fit - var frame2 = fig1.add_axes((.1, .1, .8, .2)) plt.plot(amp, resids, 'or') plt.fill_between(x, -noise, noise, alpha=0.2, label='Shot/Read Noise') plt.ylabel('$\sigma^2$ Residuals (ADUs)') plt.xlabel('Median Pixel Value (ADUs)') plt.axvline(nonlin, c='m', label='$4\%$ Non-linearity Point: {}ADUs'.format(nonlin)) plt.axvline(fwell, c='y', label='Full-well: {}ADUs'.format(fwell)) plt.grid() plt.ylim(-1000, 4000) plt.xlim(11000, 13600) plt.legend(loc='best') plt.show()